On Fri, Apr 12, 2019 at 02:46:19PM -0400, Jason Merrill wrote:
> On 4/12/19 3:19 AM, Jakub Jelinek wrote:
> > In r234626 Marek has added code to remove TREE_TYPE (newdecl) from
> > its variant list for typedefs, because we'll ggc_free the TYPE_NAME of that
> > type.  Unfortunately, that code will ICE if TREE_TYPE (newdecl) is its own
> > TYPE_MAIN_VARIANT.  This can happen if due to attributes the newdecl's type
> > has been build_distinct_type_copy created but hasn't been type_hash_canon
> > merged (which we do for a few attributes like aligned, but certainly don't
> > do it for most other attributes).  In the likely case there are no variants
> > for that type yet, there is just nothing to remove.  If there are some (in
> > theory), the options are do what the following patch does, keep the type
> > in the variant list as the main variant, just change the TYPE_NAME, so that
> > it doesn't refer to ggc_freed TYPE_DECL, or try to pick up some other type
> > as the main variant and adjust the whole variant list (I don't think the
> > C/C++ FEs unlike Ada FE like e.g. qualified types as main variant though).
> 
> If the typedef is a duplicate, the type ought to be garbage as well, no?

I'd hope so.
So, would you prefer this instead, where instead of changing the TYPE_NAME
of the type we assert it has no variants?  I was just worried there might be
variants, but duplicate_decls should happen immediately on the typedef, so
there shouldn't be time to create the variants.

Tried
typedef const unsigned int a __attribute__ ((__aligned__(8), __may_alias__));
typedef const unsigned int a __attribute__ ((__aligned__(8), __may_alias__));
and it works too.

2019-04-12  Jakub Jelinek  <ja...@redhat.com>

        PR c/89933
c/
        * c-decl.c (merge_decls): When newdecl's type is its main variant,
        don't try to remove it from the variant list, but instead assert
        it has no variants.
cp/
        * decl.c (duplicate_decls): When newdecl's type is its main variant,
        don't try to remove it from the variant list, but instead assert
        it has no variants.
testsuite/
        * c-c++-common/pr89933.c: New test.

--- gcc/c/c-decl.c.jj   2019-04-11 17:25:08.873026245 +0200
+++ gcc/c/c-decl.c      2019-04-12 21:48:15.815779025 +0200
@@ -2512,13 +2512,16 @@ merge_decls (tree newdecl, tree olddecl,
       if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl)
        {
          tree remove = TREE_TYPE (newdecl);
-         for (tree t = TYPE_MAIN_VARIANT (remove); ;
-              t = TYPE_NEXT_VARIANT (t))
-           if (TYPE_NEXT_VARIANT (t) == remove)
-             {
-               TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
-               break;
-             }
+         if (TYPE_MAIN_VARIANT (remove) == remove)
+           gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+         else
+           for (tree t = TYPE_MAIN_VARIANT (remove); ;
+                t = TYPE_NEXT_VARIANT (t))
+             if (TYPE_NEXT_VARIANT (t) == remove)
+               {
+                 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
+                 break;
+               }
        }
     }
 
--- gcc/cp/decl.c.jj    2019-04-11 17:25:08.664029678 +0200
+++ gcc/cp/decl.c       2019-04-12 21:48:28.926563001 +0200
@@ -2132,13 +2132,16 @@ next_arg:;
          if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl)
            {
              tree remove = TREE_TYPE (newdecl);
-             for (tree t = TYPE_MAIN_VARIANT (remove); ;
-                  t = TYPE_NEXT_VARIANT (t))
-               if (TYPE_NEXT_VARIANT (t) == remove)
-                 {
-                   TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
-                   break;
-                 }
+             if (TYPE_MAIN_VARIANT (remove) == remove)
+               gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+             else
+               for (tree t = TYPE_MAIN_VARIANT (remove); ;
+                    t = TYPE_NEXT_VARIANT (t))
+                 if (TYPE_NEXT_VARIANT (t) == remove)
+                   {
+                     TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
+                     break;
+                   }
            }
        }
       else if (merge_attr)
--- gcc/testsuite/c-c++-common/pr89933.c.jj     2019-04-12 21:47:46.189267166 
+0200
+++ gcc/testsuite/c-c++-common/pr89933.c        2019-04-12 21:47:46.189267166 
+0200
@@ -0,0 +1,5 @@
+/* PR c/89933 */
+/* { dg-do compile } */
+
+typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__));
+typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__));


        Jakub

Reply via email to