re PR c++/90108 (ICE: Segmentation fault (in c_tree_chain_next))
authorJakub Jelinek <jakub@redhat.com>
Fri, 19 Apr 2019 08:24:05 +0000 (10:24 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 19 Apr 2019 08:24:05 +0000 (10:24 +0200)
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.

From-SVN: r270453

gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr90108.c [new file with mode: 0644]

index c8e5e1a..27660b9 100644 (file)
@@ -1,3 +1,10 @@
+2019-04-19  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.
+
 2019-04-12  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/89933
index ef9b874..c8e7cd0 100644 (file)
@@ -2513,7 +2513,24 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
        {
          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))
index 7bb464f..9c1c49b 100644 (file)
@@ -1,3 +1,10 @@
+2019-04-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/90108
+       * 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.
+
 2019-04-18  Jason Merrill  <jason@redhat.com>
 
        PR c++/87554 - ICE with extern template and reference member.
index 420d6d8..21b4cc6 100644 (file)
@@ -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))
index 451f190..15e1d14 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/90108
+       * c-c++-common/pr90108.c: New test.
+
 2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR middle-end/85164
diff --git a/gcc/testsuite/c-c++-common/pr90108.c b/gcc/testsuite/c-c++-common/pr90108.c
new file mode 100644 (file)
index 0000000..fa5b846
--- /dev/null
@@ -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__));