[C/C++ PATCH] Fix ICE with typedef redeclaration with attributes (PR c/89933, take 2)

Jakub Jelinek jakub@redhat.com
Fri Apr 12 20:06:00 GMT 2019


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  <jakub@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



More information about the Gcc-patches mailing list