public inbox for gcc-bugs@sourceware.org help / color / mirror / Atom feed
From: "hubicka at ucw dot cz" <gcc-bugzilla@gcc.gnu.org> To: gcc-bugs@gcc.gnu.org Subject: [Bug lto/63226] ICE with -flto-odr-type-merging Date: Fri, 12 Sep 2014 00:18:00 -0000 [thread overview] Message-ID: <bug-63226-4-cuzT9w5Ecn@http.gcc.gnu.org/bugzilla/> (raw) In-Reply-To: <bug-63226-4@http.gcc.gnu.org/bugzilla/> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63226 --- Comment #4 from Jan Hubicka <hubicka at ucw dot cz> --- Hi, this is patch I am testing. It fixes few issues in the ODR comparsions code and seems to handle this testcase sanely. Honza Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 215196) +++ ipa-devirt.c (working copy) @@ -136,8 +136,44 @@ along with GCC; see the file COPYING3. #include "intl.h" #include "hash-map.h" +/* Hash based set of pairs of types. */ +typedef struct +{ + tree first; + tree second; +} type_pair; + +struct pair_traits : default_hashset_traits +{ + static hashval_t + hash (type_pair p) + { + return TYPE_UID (p.first) ^ TYPE_UID (p.second); + } + static bool + is_empty (type_pair p) + { + return p.first == NULL; + } + static bool + is_deleted (type_pair p ATTRIBUTE_UNUSED) + { + return false; + } + static bool + equal (const type_pair &a, const type_pair &b) + { + return a.first==b.first && a.second == b.second; + } + static void + mark_empty (type_pair &e) + { + e.first = NULL; + } +}; + static bool odr_types_equivalent_p (tree, tree, bool, bool *, - hash_set<tree> *); + hash_set<type_pair,pair_traits> *); static bool odr_violation_reported = false; @@ -471,7 +507,7 @@ set_type_binfo (tree type, tree binfo) /* Compare T2 and T2 based on name or structure. */ static bool -odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited) +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<type_pair,pair_traits> *visited) { bool an1, an2; @@ -489,29 +525,39 @@ odr_subtypes_equivalent_p (tree t1, tree if (an1 != an2 || an1) return false; - /* For types where we can not establish ODR equivalency (either by ODR names - or by virtual tables), recurse and deeply compare. */ - if ((!odr_type_p (t1) || !odr_type_p (t2)) - && (TREE_CODE (t1) != RECORD_TYPE || TREE_CODE (t2) != RECORD_TYPE - || !TYPE_BINFO (t1) || !TYPE_BINFO (t2) - || !polymorphic_type_binfo_p (TYPE_BINFO (t1)) - || !polymorphic_type_binfo_p (TYPE_BINFO (t2)))) + /* For ODR types be sure to compare their names. */ + if ((odr_type_p (t1) && !odr_type_p (t2)) + || (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE + && TYPE_BINFO (t1) && TYPE_BINFO (t2) + && polymorphic_type_binfo_p (TYPE_BINFO (t1)) + && polymorphic_type_binfo_p (TYPE_BINFO (t2)))) { - if (TREE_CODE (t1) != TREE_CODE (t2)) - return false; - if ((TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE)) - return false; - if (TYPE_NAME (t1) && DECL_NAME (TYPE_NAME (t1)) != DECL_NAME (TYPE_NAME (t2))) - return false; - /* This should really be a pair hash, but for the moment we do not need - 100% reliability and it would be better to compare all ODR types so - recursion here is needed only for component types. */ - if (visited->add (t1)) - return true; - return odr_types_equivalent_p (t1, t2, false, NULL, visited); + if (!types_same_for_odr (t1, t2)) + return false; + /* Limit recursion: If subtypes are ODR types and we know + that they are same, be happy. */ + if (!get_odr_type (t1, true)->odr_violated) + return true; } - return types_same_for_odr (t1, t2); + /* Component types, builtins and possibly vioalting ODR types + have to be compared structurally. */ + if (TREE_CODE (t1) != TREE_CODE (t2)) + return false; + if ((TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE)) + return false; + if (TYPE_NAME (t1) && DECL_NAME (TYPE_NAME (t1)) != DECL_NAME (TYPE_NAME (t2))) + return false; + + type_pair pair={t1,t2}; + if (TYPE_UID (t1) > TYPE_UID (t2)) + { + pair.first = t2; + pair.second = t1; + } + if (visited->add (pair)) + return true; + return odr_types_equivalent_p (t1, t2, false, NULL, visited); } /* Compare two virtual tables, PREVAILING and VTABLE and output ODR @@ -646,16 +692,25 @@ warn_odr (tree t1, tree t2, tree st1, tr "type %qT violates one definition rule", t1)) return; - if (!st1) + if (!st1 && !st2) ; - else if (TREE_CODE (st1) == FIELD_DECL) + /* For FIELD_DECL support also case where one of fields is + NULL - this is used when the structures have mismatching number of + elements. */ + else if (!st1 || TREE_CODE (st1) == FIELD_DECL) { inform (DECL_SOURCE_LOCATION (decl2), "a different type is defined in another translation unit"); + if (!st1) + { + st1 = st2; + st2 = NULL; + } inform (DECL_SOURCE_LOCATION (st1), "the first difference of corresponding definitions is field %qD", st1); - decl2 = st2; + if (st2) + decl2 = st2; } else if (TREE_CODE (st1) == FUNCTION_DECL) { @@ -710,7 +765,7 @@ warn_types_mismatch (tree t1, tree t2) gimple_canonical_types_compatible_p. */ static bool -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited) +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<type_pair,pair_traits> *visited) { /* Check first for the obvious case of pointer identity. */ if (t1 == t2) @@ -834,7 +889,6 @@ odr_types_equivalent_p (tree t1, tree t2 } } - /* Tail-recurse to components. */ if ((TREE_CODE (t1) == VECTOR_TYPE || TREE_CODE (t1) == COMPLEX_TYPE) && !odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2), visited)) { @@ -846,17 +900,9 @@ odr_types_equivalent_p (tree t1, tree t2 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2)); return false; } - - gcc_assert (operand_equal_p (TYPE_SIZE (t1), TYPE_SIZE (t2), 0)); - gcc_assert (operand_equal_p (TYPE_SIZE_UNIT (t1), - TYPE_SIZE_UNIT (t2), 0)); - gcc_assert (TYPE_MODE (t1) == TYPE_MODE (t2)); - - return true; } - /* Do type-specific comparisons. */ - switch (TREE_CODE (t1)) + else switch (TREE_CODE (t1)) { case ARRAY_TYPE: { @@ -896,11 +942,8 @@ odr_types_equivalent_p (tree t1, tree t2 "in another translation unit")); return false; } - gcc_assert (operand_equal_p (TYPE_SIZE (t1), TYPE_SIZE (t2), 0)); - gcc_assert (operand_equal_p (TYPE_SIZE_UNIT (t1), - TYPE_SIZE_UNIT (t2), 0)); } - return true; + break; case METHOD_TYPE: case FUNCTION_TYPE: @@ -1013,9 +1056,20 @@ odr_types_equivalent_p (tree t1, tree t2 are not the same. */ if (f1 || f2) { - warn_odr (t1, t2, NULL, NULL, warn, warned, - G_("a type with different number of fields " - "is defined in another translation unit")); + if (f1 && DECL_ARTIFICIAL (f1)) + f1 = NULL; + if (f2 && DECL_ARTIFICIAL (f2)) + f2 = NULL; + if (f1 || f2) + warn_odr (t1, t2, f1, f2, warn, warned, + G_("a type with different number of fields " + "is defined in another translation unit")); + /* Ideally we should never get this generic message. */ + else + warn_odr (t1, t2, f1, f2, warn, warned, + G_("a type with different memory representation " + "is defined in another translation unit")); + return false; } if ((TYPE_MAIN_VARIANT (t1) == t1 || TYPE_MAIN_VARIANT (t2) == t2) @@ -1063,17 +1117,35 @@ odr_types_equivalent_p (tree t1, tree t2 return false; } } - gcc_assert (operand_equal_p (TYPE_SIZE (t1), TYPE_SIZE (t2), 0)); - gcc_assert (operand_equal_p (TYPE_SIZE_UNIT (t1), - TYPE_SIZE_UNIT (t2), 0)); } - - return true; + break; } default: gcc_unreachable (); } + + /* Those are better to come last as they are utterly uninformative. */ + if (TYPE_SIZE (t1) && TYPE_SIZE (t2) + && !operand_equal_p (TYPE_SIZE (t1), TYPE_SIZE (t2), 0)) + { + warn_odr (t1, t2, NULL, NULL, warn, warned, + G_("a type with different size " + "is defined in another translation unit")); + return false; + } + if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2) + && TYPE_ALIGN (t1) != TYPE_ALIGN (t2)) + { + warn_odr (t1, t2, NULL, NULL, warn, warned, + G_("a type with different alignment " + "is defined in another translation unit")); + return false; + } + gcc_assert (!TYPE_SIZE_UNIT (t1) || !TYPE_SIZE_UNIT (t2) + || operand_equal_p (TYPE_SIZE_UNIT (t1), + TYPE_SIZE_UNIT (t2), 0)); + return true; } /* TYPE is equivalent to VAL by ODR, but its tree representation differs @@ -1106,7 +1178,7 @@ add_type_duplicate (odr_type val, tree t bool base_mismatch = false; unsigned int i,j; bool warned = false; - hash_set<tree> visited; + hash_set<type_pair,pair_traits> visited; gcc_assert (in_lto_p); vec_safe_push (val->types, type);
next prev parent reply other threads:[~2014-09-12 0:18 UTC|newest] Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top 2014-09-11 13:48 [Bug lto/63226] New: " burnus at gcc dot gnu.org 2014-09-11 19:01 ` [Bug lto/63226] " hubicka at gcc dot gnu.org 2014-09-11 20:13 ` hubicka at gcc dot gnu.org 2014-09-12 0:18 ` hubicka at ucw dot cz [this message] 2014-09-12 14:55 ` burnus at gcc dot gnu.org 2014-09-12 14:55 ` burnus at gcc dot gnu.org 2014-09-12 15:02 ` burnus at gcc dot gnu.org 2014-09-15 15:03 ` [Bug lto/63226] [5 Regression] " trippels at gcc dot gnu.org 2014-09-19 21:40 ` hubicka at gcc dot gnu.org 2014-09-22 11:58 ` trippels at gcc dot gnu.org 2014-09-24 21:39 ` burnus at gcc dot gnu.org
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=bug-63226-4-cuzT9w5Ecn@http.gcc.gnu.org/bugzilla/ \ --to=gcc-bugzilla@gcc.gnu.org \ --cc=gcc-bugs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).