From: Mark Mitchell Date: Fri, 22 May 2009 14:57:15 +0000 (+0000) Subject: tree.c (handle_dll_attribute): Mark dllexport'd inlines as non-external. X-Git-Tag: releases/gcc-4.5.0~5592 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fe2978fba2ed2c3be0d1cd6ca3e1de30bd07bf93;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2dbe9ef40f0e..514f3c44521c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2009-05-22 Mark Mitchell + + * tree.c (handle_dll_attribute): Mark dllexport'd inlines as + non-external. + 2009-05-22 Ben Elliston * Makefile.in (bversion.h, s-bversion): New targets. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 57dcb5484bfe..c876a17c23b8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2009-05-22 Mark Mitchell + + * decl2.c (decl_needed_p): Consider dllexport'd functions needed. + * semantics.c (expand_or_defer_fn): Similarly. + 2009-05-20 Ian Lance Taylor * parser.c (cp_parser_postfix_expression): Change args to a vec. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 3f753d18bd43..1b8aa495d46f 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2b12448eefd8..b37b322746a7 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1005e18a1a51..7d38e47fd687 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2009-05-22 Mark Mitchell + + * 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 PR target/37846 diff --git a/gcc/testsuite/g++.dg/ext/dllexport2.C b/gcc/testsuite/g++.dg/ext/dllexport2.C new file mode 100644 index 000000000000..71ccf670b4b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/dllexport2.C @@ -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(); diff --git a/gcc/testsuite/g++.dg/ext/dllexport2a.cc b/gcc/testsuite/g++.dg/ext/dllexport2a.cc new file mode 100644 index 000000000000..80caf3217429 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/dllexport2a.cc @@ -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(); +} diff --git a/gcc/testsuite/gcc.dg/dll-6.c b/gcc/testsuite/gcc.dg/dll-6.c new file mode 100644 index 000000000000..7907f40d1bdc --- /dev/null +++ b/gcc/testsuite/gcc.dg/dll-6.c @@ -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(); diff --git a/gcc/testsuite/gcc.dg/dll-6a.c b/gcc/testsuite/gcc.dg/dll-6a.c new file mode 100644 index 000000000000..80caf3217429 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dll-6a.c @@ -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(); +} diff --git a/gcc/testsuite/gcc.dg/dll-7.c b/gcc/testsuite/gcc.dg/dll-7.c new file mode 100644 index 000000000000..c3a5957ae6b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dll-7.c @@ -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(); diff --git a/gcc/testsuite/gcc.dg/dll-7a.c b/gcc/testsuite/gcc.dg/dll-7a.c new file mode 100644 index 000000000000..80caf3217429 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dll-7a.c @@ -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(); +} diff --git a/gcc/tree.c b/gcc/tree.c index b1ab5a5d66c5..ce339a58292b 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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)