summaryrefslogtreecommitdiff
path: root/gcc/ipa-devirt.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2015-05-16 23:18:29 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2015-05-16 23:18:29 +0000
commit40175f70b0e3a6ecc82cd5601ec12c49b1f5b354 (patch)
tree50d7960821ec80bd6136c7a2e9106406f64e8633 /gcc/ipa-devirt.c
parent17223f318bbd597b8bf71b8bd3cbbdd8ee3773ea (diff)
downloadgcc-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.c113
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)