re PR ipa/61659 (Extra undefined symbol because of devirtualization)
authorJason Merrill <jason@redhat.com>
Wed, 10 Sep 2014 17:28:59 +0000 (13:28 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 10 Sep 2014 17:28:59 +0000 (13:28 -0400)
PR c++/61659
* decl.c (grokfndecl): Don't set DECL_COMDAT on static inlines.
(duplicate_decls, start_decl): Likewise.
* pt.c (check_explicit_specialization): Likewise.
(push_template_decl_real): Or static templates.

From-SVN: r215134

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/abi/no-weak1.C [new file with mode: 0644]

index ae54a68b73a47c219d0dca8d829601f6a48591f5..565b940f0be9e544f3ad239a8c5144221536b244 100644 (file)
@@ -1,3 +1,11 @@
+2014-09-10  Jason Merrill  <jason@redhat.com>
+
+       PR c++/61659
+       * decl.c (grokfndecl): Don't set DECL_COMDAT on static inlines.
+       (duplicate_decls, start_decl): Likewise.
+       * pt.c (check_explicit_specialization): Likewise.
+       (push_template_decl_real): Or static templates.
+
 2014-09-08  Jason Merrill  <jason@redhat.com>
 
        * typeck.c (build_class_member_access_expr): Move
index d8fb35e2123742d7a25d24e4cd5c579468c8cdeb..6e195bb803d5859d53743fca705e4e7143a998ef 100644 (file)
@@ -2215,7 +2215,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
                      olddecl);
 
          SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
-         DECL_COMDAT (newdecl) = DECL_DECLARED_INLINE_P (newdecl);
+         DECL_COMDAT (newdecl) = (TREE_PUBLIC (newdecl)
+                                  && DECL_DECLARED_INLINE_P (newdecl));
 
          /* Don't propagate visibility from the template to the
             specialization here.  We'll do that in determine_visibility if
@@ -4718,7 +4719,8 @@ start_decl (const cp_declarator *declarator,
        {
          SET_DECL_TEMPLATE_SPECIALIZATION (decl);
          if (TREE_CODE (decl) == FUNCTION_DECL)
-           DECL_COMDAT (decl) = DECL_DECLARED_INLINE_P (decl);
+           DECL_COMDAT (decl) = (TREE_PUBLIC (decl)
+                                 && DECL_DECLARED_INLINE_P (decl));
          else
            DECL_COMDAT (decl) = false;
 
@@ -7699,7 +7701,8 @@ grokfndecl (tree ctype,
   if (inlinep)
     {
       DECL_DECLARED_INLINE_P (decl) = 1;
-      DECL_COMDAT (decl) = 1;
+      if (publicp)
+       DECL_COMDAT (decl) = 1;
     }
   if (inlinep & 2)
     DECL_DECLARED_CONSTEXPR_P (decl) = true;
index 44569e23b1f6ccfc0c49b8aca04a9aedb6513900..3c9317883eeebd9f6d8b66b6624b95575cd206db 100644 (file)
@@ -2813,7 +2813,8 @@ check_explicit_specialization (tree declarator,
            SET_DECL_IMPLICIT_INSTANTIATION (decl);
          else if (TREE_CODE (decl) == FUNCTION_DECL)
            /* A specialization is not necessarily COMDAT.  */
-           DECL_COMDAT (decl) = DECL_DECLARED_INLINE_P (decl);
+           DECL_COMDAT (decl) = (TREE_PUBLIC (decl)
+                                 && DECL_DECLARED_INLINE_P (decl));
          else if (TREE_CODE (decl) == VAR_DECL)
            DECL_COMDAT (decl) = false;
 
@@ -5059,6 +5060,7 @@ template arguments to %qD do not match original template %qD",
 
   if (flag_implicit_templates
       && !is_friend
+      && TREE_PUBLIC (decl)
       && VAR_OR_FUNCTION_DECL_P (decl))
     /* Set DECL_COMDAT on template instantiations; if we force
        them to be emitted by explicit instantiation or -frepo,
diff --git a/gcc/testsuite/g++.dg/abi/no-weak1.C b/gcc/testsuite/g++.dg/abi/no-weak1.C
new file mode 100644 (file)
index 0000000..663643f
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-fno-weak" }
+// { dg-final { scan-assembler "local\[ \t\]*_ZZL1fvE1i" { target x86_64-*-*gnu } } }
+// { dg-final { scan-assembler "local\[ \t\]*_ZZ1gIiEvvE1i" { target x86_64-*-*gnu } } }
+
+static inline void f()
+{
+  static int i;
+  ++i;
+};
+
+template <class T> static void g()
+{
+  static int i;
+  ++i;
+}
+
+int main()
+{
+  f();
+  g<int>();
+}