gcc/
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 May 2009 14:57:15 +0000 (14:57 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 May 2009 14:57:15 +0000 (14:57 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147799 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/dllexport2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/dllexport2a.cc [new file with mode: 0644]
gcc/testsuite/gcc.dg/dll-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/dll-6a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/dll-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/dll-7a.c [new file with mode: 0644]
gcc/tree.c

index 2dbe9ef..514f3c4 100644 (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.
index 57dcb54..c876a17 100644 (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.
index 3f753d1..1b8aa49 100644 (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;
index 2b12448..b37b322 100644 (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);
     }
 
index 1005e18..7d38e47 100644 (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
diff --git a/gcc/testsuite/g++.dg/ext/dllexport2.C b/gcc/testsuite/g++.dg/ext/dllexport2.C
new file mode 100644 (file)
index 0000000..71ccf67
--- /dev/null
@@ -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 (file)
index 0000000..80caf32
--- /dev/null
@@ -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 (file)
index 0000000..7907f40
--- /dev/null
@@ -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 (file)
index 0000000..80caf32
--- /dev/null
@@ -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 (file)
index 0000000..c3a5957
--- /dev/null
@@ -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 (file)
index 0000000..80caf32
--- /dev/null
@@ -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 b1ab5a5..ce339a5 100644 (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)