+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.
+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.
|| (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;
/* 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);
}
+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
--- /dev/null
+// { 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();
--- /dev/null
+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();
+}
--- /dev/null
+/* { 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();
--- /dev/null
+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();
+}
--- /dev/null
+/* { 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();
--- /dev/null
+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();
+}
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. */
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))
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)