diff options
author | Jan Hubicka <jh@suse.cz> | 2013-06-21 08:43:39 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2013-06-21 06:43:39 +0000 |
commit | d84db1ed8ab30d720ca46e008bb8864d06fac02b (patch) | |
tree | bcd4e436084bd33e82d78d3f7a748097b5c85733 | |
parent | bc6ad87f60c29b76fddc2a4c770c26291d399556 (diff) | |
download | gcc-d84db1ed8ab30d720ca46e008bb8864d06fac02b.zip gcc-d84db1ed8ab30d720ca46e008bb8864d06fac02b.tar.gz gcc-d84db1ed8ab30d720ca46e008bb8864d06fac02b.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 2 | ||||
-rw-r--r-- | gcc/tree.c | 126 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
4 files changed, 136 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e3484bd..c18f056 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 b6d22b3..728d361 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; @@ -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; @@ -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); |