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

Jakub Jelinek jakub@redhat.com
Fri Apr 12 07:30:00 GMT 2019


Hi!

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).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Though, maybe we could do that TYPE_NAME (remove) = olddecl; unconditionally
and only do the removal from variant list conditionally.  Would you prefer
that?

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 change
	TYPE_NAME to olddecl.
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 change
	TYPE_NAME to olddecl.
testsuite/
	* c-c++-common/pr89933.c: New test.

--- gcc/c/c-decl.c.jj	2019-03-20 12:24:57.896298849 +0100
+++ gcc/c/c-decl.c	2019-04-11 16:43:48.437746631 +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)
+	    TYPE_NAME (remove) = olddecl;
+	  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-09 15:18:36.860833102 +0200
+++ gcc/cp/decl.c	2019-04-11 16:46:40.176923681 +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)
+		TYPE_NAME (remove) = olddecl;
+	      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-11 16:50:13.808415292 +0200
+++ gcc/testsuite/c-c++-common/pr89933.c	2019-04-11 16:49:57.090689737 +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