struct A { virtual void foo (); }; template <class> class B : A {}; typedef void (__attribute__((fastcall)) F) (); B<F> e; ICEs with -m32 on x86_64-linux (and on i686-linux), starting with r267359.
Seems TYPE_CANONICAL is NULL on the RECORD_TYPE B as well as its TYPE_MAIN_VARIANT.
This comes from build_type_attribute_qual_variant: 1159 if (ntype != dtype) 1160 /* This variant was already in the hash table, don't mess with 1161 TYPE_CANONICAL. */; 1162 else if (TYPE_STRUCTURAL_EQUALITY_P (ttype) 1163 || !comp_type_attributes (ntype, ttype)) 1164 /* If the target-dependent attributes make NTYPE different from 1165 its canonical type, we will need to use structural equality 1166 checks for this type. 1167 1168 We shouldn't get here for stripping attributes from a type; 1169 the no-attribute type might not need structural comparison. But 1170 we can if was discarded from type_hash_table. */ 1171 SET_TYPE_STRUCTURAL_EQUALITY (ntype); 1172 else if (TYPE_CANONICAL (ntype) == ntype) 1173 TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); for the FUNCTION_TYPE, so the fntype has NULL TYPE_CANONICAL and then: 9558 if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist)) 9559 /* This instantiation is another name for the primary 9560 template type. Set the TYPE_CANONICAL field 9561 appropriately. */ 9562 TYPE_CANONICAL (t) = template_type; 9563 else if (any_template_arguments_need_structural_equality_p (arglist)) 9564 /* Some of the template arguments require structural 9565 equality testing, so this template class requires 9566 structural equality testing. */ 9567 SET_TYPE_STRUCTURAL_EQUALITY (t); because any_template_arguments_need_structural_equality_p is true, we keep TYPE_CANONICAL cleared. The following patch fixes the ICE for me, but am not sure if it is 100% correct. I don't see other parts in the middle-end that would not accept types with NULL TYPE_CANONICAL, they sometimes punt, or do more careful comparison, but don't just ICE. --- gcc/ipa-devirt.c.jj 2019-04-15 19:45:28.796340266 +0200 +++ gcc/ipa-devirt.c 2019-05-02 10:46:03.077896176 +0200 @@ -2020,7 +2020,7 @@ obj_type_ref_class (const_tree ref) ref = TREE_VALUE (TYPE_ARG_TYPES (ref)); gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE); tree ret = TREE_TYPE (ref); - if (!in_lto_p) + if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret)) ret = TYPE_CANONICAL (ret); else ret = get_odr_type (ret)->type; @@ -2042,7 +2042,7 @@ get_odr_type (tree type, bool insert) int base_id = -1; type = TYPE_MAIN_VARIANT (type); - if (!in_lto_p) + if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type)) type = TYPE_CANONICAL (type); gcc_checking_assert (can_be_name_hashed_p (type)
> This comes from build_type_attribute_qual_variant: > 1159 if (ntype != dtype) > 1160 /* This variant was already in the hash table, don't mess with > 1161 TYPE_CANONICAL. */; > 1162 else if (TYPE_STRUCTURAL_EQUALITY_P (ttype) > 1163 || !comp_type_attributes (ntype, ttype)) > 1164 /* If the target-dependent attributes make NTYPE different from > 1165 its canonical type, we will need to use structural equality > 1166 checks for this type. > 1167 > 1168 We shouldn't get here for stripping attributes from a type; > 1169 the no-attribute type might not need structural comparison. > But > 1170 we can if was discarded from type_hash_table. */ > 1171 SET_TYPE_STRUCTURAL_EQUALITY (ntype); Hmm, bit odd code. > > --- gcc/ipa-devirt.c.jj 2019-04-15 19:45:28.796340266 +0200 > +++ gcc/ipa-devirt.c 2019-05-02 10:46:03.077896176 +0200 > @@ -2020,7 +2020,7 @@ obj_type_ref_class (const_tree ref) > ref = TREE_VALUE (TYPE_ARG_TYPES (ref)); > gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE); > tree ret = TREE_TYPE (ref); > - if (!in_lto_p) > + if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret)) This code is here to go from incomplete type to complete type after free_lang_data was run. By punting here we will lose optimization. Perhaps it is safe to go to main variant first and then to type canonical since the main variant will not have type_canonical cleared by hunk above? Honza > ret = TYPE_CANONICAL (ret); > else > ret = get_odr_type (ret)->type; > @@ -2042,7 +2042,7 @@ get_odr_type (tree type, bool insert) > int base_id = -1; > > type = TYPE_MAIN_VARIANT (type); > - if (!in_lto_p) > + if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type)) > type = TYPE_CANONICAL (type); > > gcc_checking_assert (can_be_name_hashed_p (type) > > -- > You are receiving this mail because: > You are on the CC list for the bug.
No, TYPE_CANONICAL (TYPE_MAIN_VARIANT (type)) is also NULL, for the same reasons. It is a template instantiation with a template parameter that needs structural equality.
I see, i suppose we may lose some optimizations in early opts because of this but your patch is safe and I don't think the missed optimizations are very important (if they are we should avoid having structural equality on such types) Honza
Author: jakub Date: Fri May 3 07:32:06 2019 New Revision: 270835 URL: https://gcc.gnu.org/viewcvs?rev=270835&root=gcc&view=rev Log: PR tree-optimization/90303 * ipa-devirt.c (obj_type_ref_class, get_odr_type): Don't use TYPE_CANONICAL for TYPE_STRUCTURAL_EQUALITY_P types in !in_lto_p mode. * g++.target/i386/pr90303.C: New test. Added: trunk/gcc/testsuite/g++.target/i386/pr90303.C Modified: trunk/gcc/ChangeLog trunk/gcc/ipa-devirt.c trunk/gcc/testsuite/ChangeLog
Fixed for 10.1+ so far.
Author: jakub Date: Fri May 17 19:48:25 2019 New Revision: 271349 URL: https://gcc.gnu.org/viewcvs?rev=271349&root=gcc&view=rev Log: Backported from mainline 2019-05-03 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/90303 * ipa-devirt.c (obj_type_ref_class, get_odr_type): Don't use TYPE_CANONICAL for TYPE_STRUCTURAL_EQUALITY_P types in !in_lto_p mode. * g++.target/i386/pr90303.C: New test. Added: branches/gcc-9-branch/gcc/testsuite/g++.target/i386/pr90303.C Modified: branches/gcc-9-branch/gcc/ChangeLog branches/gcc-9-branch/gcc/ipa-devirt.c branches/gcc-9-branch/gcc/testsuite/ChangeLog
Fixed.