Hi, this patch fixes another problem with ODR warnings (and I hope I am one patch away from closing that PR).
As shown in the first testcase Martin attached, we output very confusing warning about wrong alignment of subtype instead of noticing that type contains field of type that already violates ODR. This used to (mostly) work by accient since types was registered in streaming order that goes by SCCs. Since Maritn sabilized the order to follow locations this is no longer true. It was not robust anyway since two types may share SCC (they ought not anymore but still it is better to not have correctness of warnings dependent on details on the streaming). This patch fixes it by simply making register_odr_type to first recurse to subtypes to be sure that everything is registered in right order. Testcases are still missing - there is location being output wrong which I will work next. lto-bootstrapped/regtested x86_64-linux, will commit it shortly. Honza PR lto/87957 * ipa-devirt.c (odr_subtypes_equivalent_p): Report ODR violation when sybtype already violates ODR. (get_odr_type): Do not ICE when insert is false and type duplicate is not registered yet. (register_odr_type): Be sure to register subtypes first. Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 266314) +++ ipa-devirt.c (working copy) @@ -692,14 +692,17 @@ odr_subtypes_equivalent_p (tree t1, tree and other ODR even though it is a violation. */ if (types_odr_comparable (t1, t2)) { + if (t1 != t2 + && odr_type_p (TYPE_MAIN_VARIANT (t1)) + && get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated) + return false; if (!types_same_for_odr (t1, t2)) return false; if (!type_variants_equivalent_p (t1, t2, warn, warned)) return false; /* Limit recursion: If subtypes are ODR types and we know that they are same, be happy. */ - if (!odr_type_p (TYPE_MAIN_VARIANT (t1)) - || !get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated) + if (odr_type_p (TYPE_MAIN_VARIANT (t1))) return true; } @@ -2047,10 +2050,9 @@ get_odr_type (tree type, bool insert) else if (*vtable_slot) val = *vtable_slot; - if (val->type != type + if (val->type != type && insert && (!val->types_set || !val->types_set->add (type))) { - gcc_assert (insert); /* We have type duplicate, but it may introduce vtable name or mangled name; be sure to keep hashes in sync. */ if (in_lto_p && can_be_vtable_hashed_p (type) @@ -2144,7 +2146,36 @@ register_odr_type (tree type) odr_vtable_hash = new odr_vtable_hash_type (23); } if (type == TYPE_MAIN_VARIANT (type)) - get_odr_type (type, true); + { + /* To get ODR warings right, first register all sub-types. */ + if (RECORD_OR_UNION_TYPE_P (type) + && COMPLETE_TYPE_P (type)) + { + /* Limit recursion on types which are already registered. */ + odr_type ot = get_odr_type (type, false); + if (ot + && (ot->type == type + || (ot->types_set + && ot->types_set->contains (type)))) + return; + for (tree f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + tree subtype = TREE_TYPE (f); + + while (TREE_CODE (subtype) == ARRAY_TYPE) + subtype = TREE_TYPE (subtype); + if (type_with_linkage_p (TYPE_MAIN_VARIANT (subtype))) + register_odr_type (TYPE_MAIN_VARIANT (subtype)); + } + if (TYPE_BINFO (type)) + for (unsigned int i = 0; + i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) + register_odr_type (BINFO_TYPE (BINFO_BASE_BINFO + (TYPE_BINFO (type), i))); + } + get_odr_type (type, true); + } } /* Return true if type is known to have no derivations. */