diff mbox series

[C/C++] Further typedef duplicate decl fixes (PR c++/90108)

Message ID 20190418062552.GZ21066@tucnak
State New
Headers show
Series [C/C++] Further typedef duplicate decl fixes (PR c++/90108) | expand

Commit Message

Jakub Jelinek April 18, 2019, 6:25 a.m. UTC
Hi!

As reported, the newly added testcase ICEs with --param ggc-min-heapsize=0.
The problem is that while the remove type is not referenced by anything
else, it is a distinct type created to hold the attributes, there is another
type with TYPE_NAME equal to the newdecl we want to tree.  That one is
created in common_handle_aligned_attribute:
    {
      if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
        /* OK, modify the type in place.  */;
      /* If we have a TYPE_DECL, then copy the type, so that we
         don't accidentally modify a builtin type.  See pushdecl.  */
      else if (decl && TREE_TYPE (decl) != error_mark_node
               && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
        {
          tree tt = TREE_TYPE (decl);
          *type = build_variant_type_copy (*type);
          DECL_ORIGINAL_TYPE (decl) = tt;
          TYPE_NAME (*type) = decl;
          TREE_USED (*type) = TREE_USED (decl);
          TREE_TYPE (decl) = *type;
        }
      else
        *type = build_variant_type_copy (*type);
where we create a variant type and set the TYPE_NAME too.  I've tried to
remove that else if ... and just do *type = build_variant_type_copy (*type);
but that regressed some DWARF DW_AT_alignment tests.

So, the following patch instead removes the remove type from the variants
list if it is not a main variant (as before), otherwise tries to find in
TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (newdecl)) variant list a type
with TYPE_NAME equal to newdecl and remove that one.

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

2019-04-18  Jakub Jelinek  <jakub@redhat.com>

	PR c++/90108
	* c-decl.c (merge_decls): If remove is main variant and
	DECL_ORIGINAL_TYPE is some other type, remove a DECL_ORIGINAL_TYPE
	variant that has newdecl as TYPE_NAME if any.

	* decl.c (duplicate_decls): If remove is main variant and
	DECL_ORIGINAL_TYPE is some other type, remove a DECL_ORIGINAL_TYPE
	variant that has newdecl as TYPE_NAME if any.

	* c-c++-common/pr90108.c: New test.


	Jakub

Comments

Jason Merrill April 19, 2019, 5:32 a.m. UTC | #1
OK.

On Wed, Apr 17, 2019 at 11:25 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> Hi!
>
> As reported, the newly added testcase ICEs with --param ggc-min-heapsize=0.
> The problem is that while the remove type is not referenced by anything
> else, it is a distinct type created to hold the attributes, there is another
> type with TYPE_NAME equal to the newdecl we want to tree.  That one is
> created in common_handle_aligned_attribute:
>     {
>       if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
>         /* OK, modify the type in place.  */;
>       /* If we have a TYPE_DECL, then copy the type, so that we
>          don't accidentally modify a builtin type.  See pushdecl.  */
>       else if (decl && TREE_TYPE (decl) != error_mark_node
>                && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
>         {
>           tree tt = TREE_TYPE (decl);
>           *type = build_variant_type_copy (*type);
>           DECL_ORIGINAL_TYPE (decl) = tt;
>           TYPE_NAME (*type) = decl;
>           TREE_USED (*type) = TREE_USED (decl);
>           TREE_TYPE (decl) = *type;
>         }
>       else
>         *type = build_variant_type_copy (*type);
> where we create a variant type and set the TYPE_NAME too.  I've tried to
> remove that else if ... and just do *type = build_variant_type_copy (*type);
> but that regressed some DWARF DW_AT_alignment tests.
>
> So, the following patch instead removes the remove type from the variants
> list if it is not a main variant (as before), otherwise tries to find in
> TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (newdecl)) variant list a type
> with TYPE_NAME equal to newdecl and remove that one.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2019-04-18  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c++/90108
>         * c-decl.c (merge_decls): If remove is main variant and
>         DECL_ORIGINAL_TYPE is some other type, remove a DECL_ORIGINAL_TYPE
>         variant that has newdecl as TYPE_NAME if any.
>
>         * decl.c (duplicate_decls): If remove is main variant and
>         DECL_ORIGINAL_TYPE is some other type, remove a DECL_ORIGINAL_TYPE
>         variant that has newdecl as TYPE_NAME if any.
>
>         * c-c++-common/pr90108.c: New test.
>
> --- gcc/c/c-decl.c.jj   2019-04-17 21:21:39.936133112 +0200
> +++ gcc/c/c-decl.c      2019-04-17 23:25:08.098936888 +0200
> @@ -2513,7 +2513,24 @@ merge_decls (tree newdecl, tree olddecl,
>         {
>           tree remove = TREE_TYPE (newdecl);
>           if (TYPE_MAIN_VARIANT (remove) == remove)
> -           gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
> +           {
> +             gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
> +             /* If remove is the main variant, no need to remove that
> +                from the list.  One of the DECL_ORIGINAL_TYPE
> +                variants, e.g. created for aligned attribute, might still
> +                refer to the newdecl TYPE_DECL though, so remove that one
> +                in that case.  */
> +             if (DECL_ORIGINAL_TYPE (newdecl)
> +                 && DECL_ORIGINAL_TYPE (newdecl) != remove)
> +               for (tree t = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (newdecl));
> +                    t; t = TYPE_MAIN_VARIANT (t))
> +                 if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl)
> +                   {
> +                     TYPE_NEXT_VARIANT (t)
> +                       = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t));
> +                     break;
> +                   }
> +           }
>           else
>             for (tree t = TYPE_MAIN_VARIANT (remove); ;
>                  t = TYPE_NEXT_VARIANT (t))
> --- gcc/cp/decl.c.jj    2019-04-17 21:21:39.753136091 +0200
> +++ gcc/cp/decl.c       2019-04-17 23:27:13.995875527 +0200
> @@ -2133,7 +2133,24 @@ next_arg:;
>             {
>               tree remove = TREE_TYPE (newdecl);
>               if (TYPE_MAIN_VARIANT (remove) == remove)
> -               gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
> +               {
> +                 gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
> +                 /* If remove is the main variant, no need to remove that
> +                    from the list.  One of the DECL_ORIGINAL_TYPE
> +                    variants, e.g. created for aligned attribute, might still
> +                    refer to the newdecl TYPE_DECL though, so remove that one
> +                    in that case.  */
> +                 if (tree orig = DECL_ORIGINAL_TYPE (newdecl))
> +                   if (orig != remove)
> +                     for (tree t = TYPE_MAIN_VARIANT (orig); t;
> +                          t = TYPE_MAIN_VARIANT (t))
> +                       if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl)
> +                         {
> +                           TYPE_NEXT_VARIANT (t)
> +                             = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t));
> +                           break;
> +                         }
> +               }
>               else
>                 for (tree t = TYPE_MAIN_VARIANT (remove); ;
>                      t = TYPE_NEXT_VARIANT (t))
> --- gcc/testsuite/c-c++-common/pr90108.c.jj     2019-04-17 23:18:23.466566296 +0200
> +++ gcc/testsuite/c-c++-common/pr90108.c        2019-04-17 23:18:23.466566296 +0200
> @@ -0,0 +1,6 @@
> +/* PR c++/90108 */
> +/* { dg-do compile } */
> +/* { dg-options "--param ggc-min-heapsize=0" } */
> +
> +typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__));
> +typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__));
>
>         Jakub
diff mbox series

Patch

--- gcc/c/c-decl.c.jj	2019-04-17 21:21:39.936133112 +0200
+++ gcc/c/c-decl.c	2019-04-17 23:25:08.098936888 +0200
@@ -2513,7 +2513,24 @@  merge_decls (tree newdecl, tree olddecl,
 	{
 	  tree remove = TREE_TYPE (newdecl);
 	  if (TYPE_MAIN_VARIANT (remove) == remove)
-	    gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+	    {
+	      gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+	      /* If remove is the main variant, no need to remove that
+		 from the list.  One of the DECL_ORIGINAL_TYPE
+		 variants, e.g. created for aligned attribute, might still
+		 refer to the newdecl TYPE_DECL though, so remove that one
+		 in that case.  */
+	      if (DECL_ORIGINAL_TYPE (newdecl)
+		  && DECL_ORIGINAL_TYPE (newdecl) != remove)
+		for (tree t = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (newdecl));
+		     t; t = TYPE_MAIN_VARIANT (t))
+		  if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl)
+		    {
+		      TYPE_NEXT_VARIANT (t)
+			= TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t));
+		      break;
+		    }
+	    }	    
 	  else
 	    for (tree t = TYPE_MAIN_VARIANT (remove); ;
 		 t = TYPE_NEXT_VARIANT (t))
--- gcc/cp/decl.c.jj	2019-04-17 21:21:39.753136091 +0200
+++ gcc/cp/decl.c	2019-04-17 23:27:13.995875527 +0200
@@ -2133,7 +2133,24 @@  next_arg:;
 	    {
 	      tree remove = TREE_TYPE (newdecl);
 	      if (TYPE_MAIN_VARIANT (remove) == remove)
-		gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+		{
+		  gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+		  /* If remove is the main variant, no need to remove that
+		     from the list.  One of the DECL_ORIGINAL_TYPE
+		     variants, e.g. created for aligned attribute, might still
+		     refer to the newdecl TYPE_DECL though, so remove that one
+		     in that case.  */
+		  if (tree orig = DECL_ORIGINAL_TYPE (newdecl))
+		    if (orig != remove)
+		      for (tree t = TYPE_MAIN_VARIANT (orig); t;
+			   t = TYPE_MAIN_VARIANT (t))
+			if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl)
+			  {
+			    TYPE_NEXT_VARIANT (t)
+			      = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t));
+			    break;
+			  }
+		}	    
 	      else
 		for (tree t = TYPE_MAIN_VARIANT (remove); ;
 		     t = TYPE_NEXT_VARIANT (t))
--- gcc/testsuite/c-c++-common/pr90108.c.jj	2019-04-17 23:18:23.466566296 +0200
+++ gcc/testsuite/c-c++-common/pr90108.c	2019-04-17 23:18:23.466566296 +0200
@@ -0,0 +1,6 @@ 
+/* PR c++/90108 */
+/* { dg-do compile } */
+/* { dg-options "--param ggc-min-heapsize=0" } */
+
+typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__));
+typedef unsigned int a __attribute__ ((__aligned__(8), __may_alias__));