c++: ICE with anonymous union [PR97974]
authorJason Merrill <jason@redhat.com>
Sat, 10 Apr 2021 18:00:15 +0000 (14:00 -0400)
committerJason Merrill <jason@redhat.com>
Thu, 29 Apr 2021 18:34:05 +0000 (14:34 -0400)
While working on the GCC 11 patch, it occurred to me that we could move
the errors about invalid members from finish_struct_anon_r to here, so we
properly get a diagnostic in g++.law/union4.C.

gcc/cp/ChangeLog:

PR c++/97974
* class.c (finish_struct_anon_r): Drop complain parm.
Remove non-field diagnostic.
(finish_struct_anon): Adjust.
* decl.c (fixup_anonymous_aggr): Move non-field diagnostic here.

gcc/testsuite/ChangeLog:

PR c++/97974
* g++.old-deja/g++.law/union4.C: Add expected diagnostic.

gcc/cp/class.c
gcc/cp/decl.c
gcc/testsuite/g++.old-deja/g++.law/union4.C

index 2cf527e..d693b43 100644 (file)
@@ -3023,7 +3023,7 @@ warn_hidden (tree t)
 /* Recursive helper for finish_struct_anon.  */
 
 static void
-finish_struct_anon_r (tree field, bool complain)
+finish_struct_anon_r (tree field)
 {
   for (tree elt = TYPE_FIELDS (TREE_TYPE (field)); elt; elt = DECL_CHAIN (elt))
     {
@@ -3039,34 +3039,6 @@ finish_struct_anon_r (tree field, bool complain)
              || TYPE_UNNAMED_P (TREE_TYPE (elt))))
        continue;
 
-      if (complain
-         && (TREE_CODE (elt) != FIELD_DECL
-             || (TREE_PRIVATE (elt) || TREE_PROTECTED (elt))))
-       {
-         /* We already complained about static data members in
-            finish_static_data_member_decl.  */
-         if (!VAR_P (elt))
-           {
-             auto_diagnostic_group d;
-             if (permerror (DECL_SOURCE_LOCATION (elt),
-                            TREE_CODE (TREE_TYPE (field)) == UNION_TYPE
-                            ? "%q#D invalid; an anonymous union may "
-                            "only have public non-static data members"
-                            : "%q#D invalid; an anonymous struct may "
-                            "only have public non-static data members", elt))
-               {
-                 static bool hint;
-                 if (flag_permissive && !hint)
-                   {
-                     hint = true;
-                     inform (DECL_SOURCE_LOCATION (elt),
-                             "this flexibility is deprecated and will be "
-                             "removed");
-                   }
-               }
-           }
-       }
-
       TREE_PRIVATE (elt) = TREE_PRIVATE (field);
       TREE_PROTECTED (elt) = TREE_PROTECTED (field);
 
@@ -3084,7 +3056,7 @@ finish_struct_anon_r (tree field, bool complain)
         int j=A().i;  */
       if (DECL_NAME (elt) == NULL_TREE
          && ANON_AGGR_TYPE_P (TREE_TYPE (elt)))
-       finish_struct_anon_r (elt, /*complain=*/false);
+       finish_struct_anon_r (elt);
     }
 }
 
@@ -3103,7 +3075,7 @@ finish_struct_anon (tree t)
 
       if (DECL_NAME (field) == NULL_TREE
          && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
-       finish_struct_anon_r (field, /*complain=*/true);
+       finish_struct_anon_r (field);
     }
 }
 
index 60dc2bf..e51c1b0 100644 (file)
@@ -5005,12 +5005,47 @@ fixup_anonymous_aggr (tree t)
   TYPE_HAS_COPY_ASSIGN (t) = 0;
   TYPE_HAS_CONST_COPY_ASSIGN (t) = 0;
 
-  /* Splice the implicitly generated functions out of TYPE_FIELDS.  */
+  /* Splice the implicitly generated functions out of TYPE_FIELDS and diagnose
+     invalid members.  */
   for (tree probe, *prev_p = &TYPE_FIELDS (t); (probe = *prev_p);)
-    if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe))
-      *prev_p = DECL_CHAIN (probe);
-    else
-      prev_p = &DECL_CHAIN (probe);
+    {
+      if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe))
+       *prev_p = DECL_CHAIN (probe);
+      else
+       prev_p = &DECL_CHAIN (probe);
+
+      if (DECL_ARTIFICIAL (probe)
+         && (!DECL_IMPLICIT_TYPEDEF_P (probe)
+             || TYPE_ANON_P (TREE_TYPE (probe))))
+       continue;
+
+      if (TREE_CODE (probe) != FIELD_DECL
+         || (TREE_PRIVATE (probe) || TREE_PROTECTED (probe)))
+       {
+         /* We already complained about static data members in
+            finish_static_data_member_decl.  */
+         if (!VAR_P (probe))
+           {
+             auto_diagnostic_group d;
+             if (permerror (DECL_SOURCE_LOCATION (probe),
+                            TREE_CODE (t) == UNION_TYPE
+                            ? "%q#D invalid; an anonymous union may "
+                            "only have public non-static data members"
+                            : "%q#D invalid; an anonymous struct may "
+                            "only have public non-static data members", probe))
+               {
+                 static bool hint;
+                 if (flag_permissive && !hint)
+                   {
+                     hint = true;
+                     inform (DECL_SOURCE_LOCATION (probe),
+                             "this flexibility is deprecated and will be "
+                             "removed");
+                   }
+               }
+           }
+       }
+      }
 
   /* Splice all functions out of CLASSTYPE_MEMBER_VEC.  */
   vec<tree,va_gc>* vec = CLASSTYPE_MEMBER_VEC (t);
index 958ff0a..ec30d1e 100644 (file)
@@ -7,7 +7,7 @@
 // Message-ID: <m0pA49A-0000LdC@piano.veritas.com>
 
 static union {
-        struct SS {
+        struct SS {            // { dg-error "anonymous union" }
                 int ss;
         };
 };// { dg-error "no members" }