From d84db1ed8ab30d720ca46e008bb8864d06fac02b Mon Sep 17 00:00:00 2001 From: Jan Hubicka <jh@suse.cz> Date: Fri, 21 Jun 2013 08:43:39 +0200 Subject: [PATCH] gimple-fold.c (gimple_extract_devirt_binfo_from_cst): Use types_same_for_odr. * gimple-fold.c (gimple_extract_devirt_binfo_from_cst): Use types_same_for_odr. * tree.c (decls_same_for_odr): New function. (same_for_edr): New function. (types_same_for_odr): New function. (get_binfo_at_offset): Use it. * tree.h (types_same_for_odr): Declare. From-SVN: r200288 --- gcc/ChangeLog | 10 ++++ gcc/gimple-fold.c | 2 +- gcc/tree.c | 126 +++++++++++++++++++++++++++++++++++++++++++++- gcc/tree.h | 1 + 4 files changed, 136 insertions(+), 3 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e3484bd5a4ee..c18f056d06e2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2013-06-20 Jan Hubicka <jh@suse.cz> + + * gimple-fold.c (gimple_extract_devirt_binfo_from_cst): Use + types_same_for_odr. + * tree.c (decls_same_for_odr): New function. + (same_for_edr): New function. + (types_same_for_odr): New function. + (get_binfo_at_offset): Use it. + * tree.h (types_same_for_odr): Declare. + 2013-06-20 Oleg Endo <oleg.endo@t-online.de> Jason Merrill <jason@redhat.com> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index b6d22b3a7c83..728d3610f11c 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1038,7 +1038,7 @@ gimple_extract_devirt_binfo_from_cst (tree cst) HOST_WIDE_INT pos, size; tree fld; - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type)) + if (types_same_for_odr (type, expected_type)) break; if (offset < 0) return NULL_TREE; diff --git a/gcc/tree.c b/gcc/tree.c index 67553b89294d..ab1173525c71 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -218,6 +218,7 @@ static void print_value_expr_statistics (void); static int type_hash_marked_p (const void *); static unsigned int type_hash_list (const_tree, hashval_t); static unsigned int attribute_hash_list (const_tree, hashval_t); +static bool decls_same_for_odr (tree decl1, tree decl2); tree global_trees[TI_MAX]; tree integer_types[itk_none]; @@ -11711,6 +11712,127 @@ lhd_gcc_personality (void) return gcc_eh_personality_decl; } +/* For languages with One Definition Rule, work out if + trees are actually the same even if the tree representation + differs. This handles only decls appearing in TYPE_NAME + and TYPE_CONTEXT. That is NAMESPACE_DECL, TYPE_DECL, + RECORD_TYPE and IDENTIFIER_NODE. */ + +static bool +same_for_odr (tree t1, tree t2) +{ + if (t1 == t2) + return true; + if (!t1 || !t2) + return false; + /* C and C++ FEs differ by using IDENTIFIER_NODE and TYPE_DECL. */ + if (TREE_CODE (t1) == IDENTIFIER_NODE + && TREE_CODE (t2) == TYPE_DECL + && DECL_FILE_SCOPE_P (t1)) + { + t2 = DECL_NAME (t2); + gcc_assert (TREE_CODE (t2) == IDENTIFIER_NODE); + } + if (TREE_CODE (t2) == IDENTIFIER_NODE + && TREE_CODE (t1) == TYPE_DECL + && DECL_FILE_SCOPE_P (t2)) + { + t1 = DECL_NAME (t1); + gcc_assert (TREE_CODE (t1) == IDENTIFIER_NODE); + } + if (TREE_CODE (t1) != TREE_CODE (t2)) + return false; + if (TYPE_P (t1)) + return types_same_for_odr (t1, t2); + if (DECL_P (t1)) + return decls_same_for_odr (t1, t2); + return false; +} + +/* For languages with One Definition Rule, work out if + decls are actually the same even if the tree representation + differs. This handles only decls appearing in TYPE_NAME + and TYPE_CONTEXT. That is NAMESPACE_DECL, TYPE_DECL, + RECORD_TYPE and IDENTIFIER_NODE. */ + +static bool +decls_same_for_odr (tree decl1, tree decl2) +{ + if (decl1 && TREE_CODE (decl1) == TYPE_DECL + && DECL_ORIGINAL_TYPE (decl1)) + decl1 = DECL_ORIGINAL_TYPE (decl1); + if (decl2 && TREE_CODE (decl2) == TYPE_DECL + && DECL_ORIGINAL_TYPE (decl2)) + decl2 = DECL_ORIGINAL_TYPE (decl2); + if (decl1 == decl2) + return true; + if (!decl1 || !decl2) + return false; + gcc_checking_assert (DECL_P (decl1) && DECL_P (decl2)); + if (TREE_CODE (decl1) != TREE_CODE (decl2)) + return false; + if (TREE_CODE (decl1) == TRANSLATION_UNIT_DECL) + return true; + if (TREE_CODE (decl1) != NAMESPACE_DECL + && TREE_CODE (decl1) != TYPE_DECL) + return false; + if (!DECL_NAME (decl1)) + return false; + gcc_checking_assert (TREE_CODE (DECL_NAME (decl1)) == IDENTIFIER_NODE); + gcc_checking_assert (!DECL_NAME (decl2) + || TREE_CODE (DECL_NAME (decl2)) == IDENTIFIER_NODE); + if (DECL_NAME (decl1) != DECL_NAME (decl2)) + return false; + return same_for_odr (DECL_CONTEXT (decl1), + DECL_CONTEXT (decl2)); +} + +/* For languages with One Definition Rule, work out if + types are same even if the tree representation differs. + This is non-trivial for LTO where minnor differences in + the type representation may have prevented type merging + to merge two copies of otherwise equivalent type. */ + +bool +types_same_for_odr (tree type1, tree type2) +{ + gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2)); + type1 = TYPE_MAIN_VARIANT (type1); + type2 = TYPE_MAIN_VARIANT (type2); + if (type1 == type2) + return true; + + /* If types are not structuraly same, do not bother to contnue. + Match in the remainder of code would mean ODR violation. */ + if (!types_compatible_p (type1, type2)) + return false; + +#ifndef ENABLE_CHECKING + if (!in_lto_p) + return false; +#endif + + /* Check for anonymous namespaces. Those have !TREE_PUBLIC + on the corresponding TYPE_STUB_DECL. */ + if (TYPE_STUB_DECL (type1) != TYPE_STUB_DECL (type2) + && (!TYPE_STUB_DECL (type1) + || !TYPE_STUB_DECL (type2) + || !TREE_PUBLIC (TYPE_STUB_DECL (type1)) + || !TREE_PUBLIC (TYPE_STUB_DECL (type2)))) + return false; + + if (!TYPE_NAME (type1)) + return false; + if (!decls_same_for_odr (TYPE_NAME (type1), TYPE_NAME (type2))) + return false; + if (!same_for_odr (TYPE_CONTEXT (type1), TYPE_CONTEXT (type2))) + return false; + /* When not in LTO the MAIN_VARIANT check should be the same. */ + gcc_assert (in_lto_p); + + return true; +} + /* Try to find a base info of BINFO that would have its field decl at offset OFFSET within the BINFO type and which is of EXPECTED_TYPE. If it can be found, return, otherwise return NULL_TREE. */ @@ -11726,7 +11848,7 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) tree fld; int i; - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type)) + if (types_same_for_odr (type, expected_type)) return binfo; if (offset < 0) return NULL_TREE; @@ -11756,7 +11878,7 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) { tree base_binfo, found_binfo = NULL_TREE; for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) - if (TREE_TYPE (base_binfo) == TREE_TYPE (fld)) + if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld))) { found_binfo = base_binfo; break; diff --git a/gcc/tree.h b/gcc/tree.h index cbbdd0bbc083..b4445170088e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5974,6 +5974,7 @@ extern location_t tree_nonartificial_location (tree); extern tree block_ultimate_origin (const_tree); extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree); +extern bool types_same_for_odr (tree type1, tree type2); extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, HOST_WIDE_INT *); extern bool contains_bitfld_component_ref_p (const_tree); -- GitLab