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 <ja...@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