re PR c++/65879 (Bogus linkage errors for member class of anonymous class)
authorJason Merrill <jason@redhat.com>
Tue, 23 Jun 2015 14:08:30 +0000 (10:08 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 23 Jun 2015 14:08:30 +0000 (10:08 -0400)
PR c++/65879
* decl.c (grokfndecl): Check the linkage of ctype, not just
TYPE_ANONYMOUS_P.
* tree.c (no_linkage_check): Skip the 'this' pointer.

From-SVN: r224844

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/abi/anon2.C
gcc/testsuite/g++.dg/other/anon7.C [new file with mode: 0644]

index de8fdacdedf046758e18bbc3fb8f1fade038df88..d08d02cd3a3ae59187f03957c5eb240e81bb1843 100644 (file)
@@ -1,5 +1,10 @@
 2015-06-23  Jason Merrill  <jason@redhat.com>
 
+       PR c++/65879
+       * decl.c (grokfndecl): Check the linkage of ctype, not just
+       TYPE_ANONYMOUS_P.
+       * tree.c (no_linkage_check): Skip the 'this' pointer.
+
        PR c++/66501
        * class.c (type_has_nontrivial_assignment): New.
        * init.c (build_vec_init): Use it.
index d14ffe218fc53cb077acf2c1e2aae4a5927bbced..a8fc1a57a959f6b55fafb2a3ff91f54b77b601e5 100644 (file)
@@ -7794,7 +7794,7 @@ grokfndecl (tree ctype,
 
   /* Members of anonymous types and local classes have no linkage; make
      them internal.  If a typedef is made later, this will be changed.  */
-  if (ctype && (TYPE_ANONYMOUS_P (ctype)
+  if (ctype && (!TREE_PUBLIC (TYPE_MAIN_DECL (ctype))
                || decl_function_context (TYPE_MAIN_DECL (ctype))))
     publicp = 0;
 
index a9c9214132a3704d3a86e664ef5bc4cf8136ac31..bc8428db0a4825004091851e1f13e17d81136c22 100644 (file)
@@ -2299,14 +2299,14 @@ no_linkage_check (tree t, bool relaxed_p)
       return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t), relaxed_p);
 
     case METHOD_TYPE:
-      r = no_linkage_check (TYPE_METHOD_BASETYPE (t), relaxed_p);
-      if (r)
-       return r;
-      /* Fall through.  */
     case FUNCTION_TYPE:
       {
-       tree parm;
-       for (parm = TYPE_ARG_TYPES (t);
+       tree parm = TYPE_ARG_TYPES (t);
+       if (TREE_CODE (t) == METHOD_TYPE)
+         /* The 'this' pointer isn't interesting; a method has the same
+            linkage (or lack thereof) as its enclosing class.  */
+         parm = TREE_CHAIN (parm);
+       for (;
             parm && parm != void_list_node;
             parm = TREE_CHAIN (parm))
          {
index cee92371043f5f9ce154cfd1712fb485d0b6f839..396edd3de8571785dcf9936563a688b84f31e158 100644 (file)
@@ -23,9 +23,9 @@ namespace N2 {
     typedef struct { } B;
     struct C {
       // { dg-final { scan-assembler-not ".weak\(_definition\)?\[ \t\]_?_ZN2N23._31C3fn1ENS0_1BE" { target c++11 } } }
-      static void fn1 (B) { } // { dg-error "no linkage" "" { target { ! c++11 } } }
+      static void fn1 (B) { }
       // { dg-final { scan-assembler-not ".weak\(_definition\)?\[ \t\]_?_ZN2N23._31C3fn2ES1_" { target c++11 } } }
-      static void fn2 (C) { } // { dg-error "no linkage" "" { target { ! c++11 } } }
+      static void fn2 (C) { }
     };
   } const D;
 
diff --git a/gcc/testsuite/g++.dg/other/anon7.C b/gcc/testsuite/g++.dg/other/anon7.C
new file mode 100644 (file)
index 0000000..12c1ab2
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/65879
+
+static struct
+{
+  void f();
+  struct Inner
+  {
+    void g();
+  };
+} x;