From 12b2c414a900e6a568ca25f156ca760e17b9f79d Mon Sep 17 00:00:00 2001 From: hubicka Date: Wed, 17 Sep 2014 16:15:29 +0000 Subject: [PATCH] * ipa-devirt.c (type_pair, default_hashset_traits): New types. (odr_types_equivalent_p): Use pair hash. (odr_subtypes_equivalent_p): Likewise, do structural compare on ODR types that may be mismatched. (warn_odr): Support warning when only one field is given. (odr_types_equivalent_p): Strenghten comparsions made; support VOIDtype. (add_type_duplicate): Update VISITED hash set. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@215328 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 ++++ gcc/ipa-devirt.c | 173 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 135 insertions(+), 49 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d639a8e..baed7a3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2014-09-17 Jan Hubicka + + * ipa-devirt.c (type_pair, default_hashset_traits): New types. + (odr_types_equivalent_p): Use pair hash. + (odr_subtypes_equivalent_p): Likewise, do structural compare + on ODR types that may be mismatched. + (warn_odr): Support warning when only one field is given. + (odr_types_equivalent_p): Strenghten comparsions made; + support VOIDtype. + (add_type_duplicate): Update VISITED hash set. + 2014-09-17 Sebastian Huber * config.gcc (*-*-rtems*): Default to 'rtems' thread model. diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 2981a85..1480b29 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -136,8 +136,44 @@ along with GCC; see the file COPYING3. If not see #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 *); + hash_set *); 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 *visited) +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set *visited) { bool an1, an2; @@ -489,29 +525,39 @@ odr_subtypes_equivalent_p (tree t1, tree t2, hash_set *visited) 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, tree st2, "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 *visited) +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set *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, bool warn, bool *warned, hash_set visited; + hash_set visited; gcc_assert (in_lto_p); vec_safe_push (val->types, type); -- 2.7.4