This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

dllexport and inline


I've committed this patch from Mark, after porting it from our stable 4.3 branch. the issue here is that functions marked dllexport must be emitted, even if they are (also) inline.

tested on i686-mingw32

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery

Index: tree.c
===================================================================
--- tree.c	(revision 147795)
+++ tree.c	(working copy)
@@ -4075,6 +4075,7 @@ handle_dll_attribute (tree * pnode, tree
 		      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
       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
       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)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 147795)
+++ ChangeLog	(working copy)
@@ -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.
Index: testsuite/gcc.target/mips/branch-2.c
===================================================================
Index: testsuite/gcc.dg/dll-7.c
===================================================================
--- testsuite/gcc.dg/dll-7.c	(revision 0)
+++ testsuite/gcc.dg/dll-7.c	(revision 0)
@@ -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();
Index: testsuite/gcc.dg/dll-7a.c
===================================================================
--- testsuite/gcc.dg/dll-7a.c	(revision 0)
+++ testsuite/gcc.dg/dll-7a.c	(revision 0)
@@ -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();
+}
Index: testsuite/gcc.dg/dll-6a.c
===================================================================
--- testsuite/gcc.dg/dll-6a.c	(revision 0)
+++ testsuite/gcc.dg/dll-6a.c	(revision 0)
@@ -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();
+}
Index: testsuite/gcc.dg/dll-6.c
===================================================================
--- testsuite/gcc.dg/dll-6.c	(revision 0)
+++ testsuite/gcc.dg/dll-6.c	(revision 0)
@@ -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();
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 147795)
+++ testsuite/ChangeLog	(working copy)
@@ -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
Index: testsuite/g++.dg/ext/dllexport2a.cc
===================================================================
--- testsuite/g++.dg/ext/dllexport2a.cc	(revision 0)
+++ testsuite/g++.dg/ext/dllexport2a.cc	(revision 0)
@@ -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();
+}
Index: testsuite/g++.dg/ext/dllexport2.C
===================================================================
--- testsuite/g++.dg/ext/dllexport2.C	(revision 0)
+++ testsuite/g++.dg/ext/dllexport2.C	(revision 0)
@@ -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();
Index: cp/ChangeLog
===================================================================
--- cp/ChangeLog	(revision 147795)
+++ cp/ChangeLog	(working copy)
@@ -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.
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 147795)
+++ cp/semantics.c	(working copy)
@@ -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);
     }
 
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 147795)
+++ cp/decl2.c	(working copy)
@@ -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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]