tree.c (handle_dll_attribute): Mark dllexport'd inlines as non-external.

gcc/
	* tree.c (handle_dll_attribute): Mark dllexport'd inlines as
	non-external.

	gcc/cp
	* decl2.c (decl_needed_p): Consider dllexport'd functions needed.
	* semantics.c (expand_or_defer_fn): Similarly.

	gcc/testsuite/
	* gcc.dg/dll-6.c: New test.
	* gcc.dg/dll-6a.c: Likewise.
	* gcc.dg/dll-7.c: Likewise.
	* gcc.dg/dll-7a.c: Likewise.
	* g++.dg/ext/dllexport2.C: Likewise.
	* g++.dg/ext/dllexport2a.cc: Likewise.

From-SVN: r147799
This commit is contained in:
Mark Mitchell 2009-05-22 14:57:15 +00:00 committed by Nathan Sidwell
parent e4c29fbc9e
commit fe2978fba2
12 changed files with 253 additions and 3 deletions

View File

@ -1,3 +1,8 @@
2009-05-22 Mark Mitchell <mark@codesourcery.com>
* tree.c (handle_dll_attribute): Mark dllexport'd inlines as
non-external.
2009-05-22 Ben Elliston <bje@au.ibm.com>
* Makefile.in (bversion.h, s-bversion): New targets.

View File

@ -1,3 +1,8 @@
2009-05-22 Mark Mitchell <mark@codesourcery.com>
* decl2.c (decl_needed_p): Consider dllexport'd functions needed.
* semantics.c (expand_or_defer_fn): Similarly.
2009-05-20 Ian Lance Taylor <iant@google.com>
* parser.c (cp_parser_postfix_expression): Change args to a vec.

View File

@ -1707,6 +1707,10 @@ decl_needed_p (tree decl)
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
return true;
/* Functions marked "dllexport" must be emitted so that they are
visible to other DLLs. */
if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
return true;
/* Otherwise, DECL does not need to be emitted -- yet. A subsequent
reference to DECL might cause it to be emitted later. */
return false;

View File

@ -3268,8 +3268,10 @@ expand_or_defer_fn (tree fn)
/* If the user wants us to keep all inline functions, then mark
this function as needed so that finish_file will make sure to
output it later. */
if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn))
output it later. Similarly, all dllexport'd functions must
be emitted; there may be callers in other DLLs. */
if ((flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn))
|| lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))
mark_needed (fn);
}

View File

@ -1,3 +1,12 @@
2009-05-22 Mark Mitchell <mark@codesourcery.com>
* gcc.dg/dll-6.c: New test.
* gcc.dg/dll-6a.c: Likewise.
* gcc.dg/dll-7.c: Likewise.
* gcc.dg/dll-7a.c: Likewise.
* g++.dg/ext/dllexport2.C: Likewise.
* g++.dg/ext/dllexport2a.cc: Likewise.
2009-05-21 Steve Ellcey <sje@cup.hp.com>
PR target/37846

View File

@ -0,0 +1,52 @@
// { dg-do link }
// { dg-require-dll "" }
// { dg-additional-sources "dllexport2a.cc" }
// { dg-options "-O2" }
/* Test that inline functions declared "dllexport" appear in object
files, even if they are not called.
This behavior is required by the ARM C++ ABI:
Exporting a function that can be inlined should force the
creation and export of an out-of-line copy of it.
and should presumably also apply.
Visual Studio 2005 also honors that rule. */
__declspec(dllexport) inline void i1() {}
__declspec(dllexport) extern inline void e1() {}
/* It is invalid to declare the function inline after its definition. */
#if 0
__declspec(dllexport) void i2() {}
inline void i2();
__declspec(dllexport) extern void e2() {}
inline void e2();
#endif
__declspec(dllexport) inline void i3() {}
void i3();
__declspec(dllexport) inline void e3() {}
extern void e3();
__declspec(dllexport) void i4();
inline void i4() {};
__declspec(dllexport) extern void e4();
inline void e4() {};
__declspec(dllexport) inline void i5();
void i5() {};
__declspec(dllexport) inline void e5();
extern void e5() {};
/* Make sure that just declaring the function -- without defining it
-- does not cause errors. */
__declspec(dllexport) inline void i6();
__declspec(dllexport) extern inline void e6();

View File

@ -0,0 +1,21 @@
extern void i1();
extern void i3();
extern void i4();
extern void i5();
extern void e1();
extern void e3();
extern void e4();
extern void e5();
int main () {
i1();
i3();
i4();
i5();
e1();
e3();
e4();
e5();
}

View File

@ -0,0 +1,52 @@
/* { dg-do link } */
/* { dg-require-dll "" } */
/* { dg-additional-sources "dll-6a.c" } */
/* { dg-options "-w -O2 -std=gnu89" } */
/* Test that inline functions declared "dllexport" appear in object
files, even if they are not called.
This behavior is required by the ARM C++ ABI:
Exporting a function that can be inlined should force the
creation and export of an out-of-line copy of it.
and should presumably also apply.
Visual Studio 2005 also honors that rule. */
__declspec(dllexport) inline void i1() {}
__declspec(dllexport) extern inline void e1() {}
/* It is invalid to declare the function inline after its definition. */
#if 0
__declspec(dllexport) void i2() {}
inline void i2();
__declspec(dllexport) extern void e2() {}
inline void e2();
#endif
__declspec(dllexport) inline void i3() {}
void i3();
__declspec(dllexport) inline void e3() {}
extern void e3();
__declspec(dllexport) void i4();
inline void i4() {};
__declspec(dllexport) extern void e4();
inline void e4() {};
__declspec(dllexport) inline void i5();
void i5() {};
__declspec(dllexport) inline void e5();
extern void e5() {};
/* Make sure that just declaring the function -- without defining it
-- does not cause errors. */
__declspec(dllexport) inline void i6();
__declspec(dllexport) extern inline void e6();

View File

@ -0,0 +1,21 @@
extern void i1();
extern void i3();
extern void i4();
extern void i5();
extern void e1();
extern void e3();
extern void e4();
extern void e5();
int main () {
i1();
i3();
i4();
i5();
e1();
e3();
e4();
e5();
}

View File

@ -0,0 +1,52 @@
/* { dg-do link } */
/* { dg-require-dll "" } */
/* { dg-additional-sources "dll-7a.c" } */
/* { dg-options "-w -O2 -std=gnu99" } */
/* Test that inline functions declared "dllexport" appear in object
files, even if they are not called.
This behavior is required by the ARM C++ ABI:
Exporting a function that can be inlined should force the
creation and export of an out-of-line copy of it.
and should presumably also apply.
Visual Studio 2005 also honors that rule. */
__declspec(dllexport) inline void i1() {}
__declspec(dllexport) extern inline void e1() {}
/* It is invalid to declare the function inline after its definition. */
#if 0
__declspec(dllexport) void i2() {}
inline void i2();
__declspec(dllexport) extern void e2() {}
inline void e2();
#endif
__declspec(dllexport) inline void i3() {}
void i3();
__declspec(dllexport) inline void e3() {}
extern void e3();
__declspec(dllexport) void i4();
inline void i4() {};
__declspec(dllexport) extern void e4();
inline void e4() {};
__declspec(dllexport) inline void i5();
void i5() {};
__declspec(dllexport) inline void e5();
extern void e5() {};
/* Make sure that just declaring the function -- without defining it
-- does not cause errors. */
__declspec(dllexport) inline void i6();
__declspec(dllexport) extern inline void e6();

View File

@ -0,0 +1,21 @@
extern void i1();
extern void i3();
extern void i4();
extern void i5();
extern void e1();
extern void e3();
extern void e4();
extern void e5();
int main () {
i1();
i3();
i4();
i5();
e1();
e3();
e4();
e5();
}

View File

@ -4075,6 +4075,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
bool *no_add_attrs)
{
tree node = *pnode;
bool is_dllimport;
/* These attributes may apply to structure and union types being created,
but otherwise should pass to the declaration involved. */
@ -4122,9 +4123,11 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
return NULL_TREE;
}
is_dllimport = is_attribute_p ("dllimport", name);
/* Report error on dllimport ambiguities seen now before they cause
any damage. */
else if (is_attribute_p ("dllimport", name))
if (is_dllimport)
{
/* Honor any target-specific overrides. */
if (!targetm.valid_dllimport_attribute_p (node))
@ -4166,6 +4169,9 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
if (*no_add_attrs == false)
DECL_DLLIMPORT_P (node) = 1;
}
else if (DECL_DECLARED_INLINE_P (node))
/* An exported function, even if inline, must be emitted. */
DECL_EXTERNAL (node) = 0;
/* Report error if symbol is not accessible at global scope. */
if (!TREE_PUBLIC (node)