diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-05-16 23:18:29 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-05-16 23:18:29 +0000 |
commit | 40175f70b0e3a6ecc82cd5601ec12c49b1f5b354 (patch) | |
tree | 50d7960821ec80bd6136c7a2e9106406f64e8633 /gcc/ipa-devirt.c | |
parent | 17223f318bbd597b8bf71b8bd3cbbdd8ee3773ea (diff) | |
download | gcc-40175f70b0e3a6ecc82cd5601ec12c49b1f5b354.tar.gz |
* ipa-utils.h (warn_types_mismatch, odr_or_derived_type_p,
odr_types_equivalent_p): Declare.
(odr_type_p): Use gcc_checking_assert.
(type_in_anonymous_namespace_p) Declare.
(type_with_linkage_p): Declare.
* common.opt (Wlto-type-mismatch): New warning.
* ipa-devirt.c (compound_type_base): New function.
(odr_or_derived_type_p): New function.
(odr_types_equivalent_p): New function.
(add_type_duplicate): Simplify.
(type_with_linkage_p): Add hack to prevent false positives on C types
(type_in_anonymous_namespace_p): Likewise.
* tree.c (need_assembler_name_p): Use type_with_linkage.
* tree.h (type_in_anonymous_namespace_p): Remove.
* doc/invoke.texi (-Wlto-type-mismatch): Document
* lto-symtab.c (warn_type_compatibility_p): Break out from ...;
compare ODR types (if available) and function types.
(lto_symtab_merge): ... here; output ODR violation warnings
and call warn_types_mismatch.
* gfortran.dg/lto/20091028-2_1.c: Fix return value.
* gfortran.dg/lto/pr41576_1.f90: Add interface.
* gfortran.dg/lto/pr41521_0.f90: Disable lto-type-mismatch
* gfortran.dg/lto/pr60635_0.f90: Disable lto-type-mismatch.
* gfortran.dg/lto/20091028-1_1.c: Fix return type.
* gcc.dg/lto/20120723_0.c: Disbale lto-type-mismatch.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223258 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-devirt.c')
-rw-r--r-- | gcc/ipa-devirt.c | 113 |
1 files changed, 100 insertions, 13 deletions
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index c073ac879b2..bf43859f47e 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -247,9 +247,14 @@ struct GTY(()) odr_type_d /* Return true if T is a type with linkage defined. */ -static bool +bool type_with_linkage_p (const_tree t) { + /* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */ + if (!TYPE_CONTEXT (t) + || !TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL) + return false; + return (RECORD_OR_UNION_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE); } @@ -261,12 +266,21 @@ bool type_in_anonymous_namespace_p (const_tree t) { gcc_assert (type_with_linkage_p (t)); - /* TREE_PUBLIC of TYPE_STUB_DECL may not be properly set for - backend produced types (such as va_arg_type); those have CONTEXT NULL - and never are considered anonymoius. */ - if (!TYPE_CONTEXT (t)) - return false; - return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t))); + + if (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t))) + { + tree ctx = DECL_CONTEXT (TYPE_NAME (t)); + while (ctx) + { + if (TREE_CODE (ctx) == NAMESPACE_DECL) + return !TREE_PUBLIC (ctx); + if (TREE_CODE (ctx) == BLOCK) + ctx = BLOCK_SUPERCONTEXT (ctx); + else + ctx = get_containing_scope (ctx); + } + } + return false; } /* Return true of T is type with One Definition Rule info attached. @@ -589,6 +603,59 @@ types_must_be_same_for_odr (tree t1, tree t2) return TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2); } +/* If T is compound type, return type it is based on. */ + +static tree +compound_type_base (const_tree t) +{ + if (TREE_CODE (t) == ARRAY_TYPE + || POINTER_TYPE_P (t) + || TREE_CODE (t) == COMPLEX_TYPE + || VECTOR_TYPE_P (t)) + return TREE_TYPE (t); + if (TREE_CODE (t) == METHOD_TYPE) + return TYPE_METHOD_BASETYPE (t); + if (TREE_CODE (t) == OFFSET_TYPE) + return TYPE_OFFSET_BASETYPE (t); + return NULL_TREE; +} + +/* Return true if T is either ODR type or compound type based from it. + If the function return true, we know that T is a type originating from C++ + source even at link-time. */ + +bool +odr_or_derived_type_p (const_tree t) +{ + do + { + if (odr_type_p (t)) + return true; + /* Function type is a tricky one. Basically we can consider it + ODR derived if return type or any of the parameters is. + We need to check all parameters because LTO streaming merges + common types (such as void) and they are not considered ODR then. */ + if (TREE_CODE (t) == FUNCTION_TYPE) + { + if (TYPE_METHOD_BASETYPE (t)) + t = TYPE_METHOD_BASETYPE (t); + else + { + if (TREE_TYPE (t) && odr_or_derived_type_p (TREE_TYPE (t))) + return true; + for (t = TYPE_ARG_TYPES (t); t; t = TREE_CHAIN (t)) + if (odr_or_derived_type_p (TREE_VALUE (t))) + return true; + return false; + } + } + else + t = compound_type_base (t); + } + while (t); + return t; +} + /* Compare types T1 and T2 and return true if they are equivalent. */ @@ -1223,6 +1290,16 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, return false; } + if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1)) + || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2))) + { + /* We can not trip this when comparing ODR types, only when trying to + match different ODR derivations from different declarations. + So WARN should be always false. */ + gcc_assert (!warn); + return false; + } + if (comp_type_attributes (t1, t2) != 1) { warn_odr (t1, t2, NULL, NULL, warn, warned, @@ -1625,6 +1702,20 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, return true; } +/* Return true if TYPE1 and TYPE2 are equivalent for One Definition Rule. */ + +bool +odr_types_equivalent_p (tree type1, tree type2) +{ + hash_set<type_pair,pair_traits> visited; + +#ifdef ENABLE_CHECKING + gcc_assert (odr_or_derived_type_p (type1) && odr_or_derived_type_p (type2)); +#endif + return odr_types_equivalent_p (type1, type2, false, NULL, + &visited); +} + /* TYPE is equivalent to VAL by ODR, but its tree representation differs from VAL->type. This may happen in LTO where tree merging did not merge all variants of the same type or due to ODR violation. @@ -1749,12 +1840,8 @@ add_type_duplicate (odr_type val, tree type) base_mismatch = true; } else - { - hash_set<type_pair,pair_traits> visited; - if (!odr_types_equivalent_p (type1, type2, false, NULL, - &visited)) - base_mismatch = true; - } + if (!odr_types_equivalent_p (type1, type2)) + base_mismatch = true; if (base_mismatch) { if (!warned && !val->odr_violated) |