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:
parent
e4c29fbc9e
commit
fe2978fba2
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
|
@ -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();
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue