Commit 420672bc by Jan Hubicka Committed by Jan Hubicka

ipa-devirt.c (warn_odr): Make static.


	* ipa-devirt.c (warn_odr): Make static.
	(types_same_for_odr): Drop strict variant.
	(types_odr_comparable): Likewise.
	(odr_or_derived_type_p): Look for main variants.
	(odr_name_hasher::equal): Cleanup comment.
	(odr_subtypes_equivalent): Add warn and warned arguments; check main
	variants.
	(type_variants_equivalent_p): break out from ...
	(odr_types_equivalent): ... here; go for main variants where needed.
	(warn_odr): ... here; turn static.
	(warn_types_mismatch): Compare mangled names of main variants.
	* ipa-utils.h (types_odr_comparable): Drop strict parameter.
	(type_with_linkage_p): Sanity check that we look at main variant.
	* lto.c (lto_read_decls): Only consider main variant to be ODR type.
	* tree.h (types_same_for_odr): Drop strict argument.

From-SVN: r265519
parent 99976e27
2018-10-26 Jan Hubicka <jh@suse.cz>
* ipa-devirt.c (warn_odr): Make static.
(types_same_for_odr): Drop strict variant.
(types_odr_comparable): Likewise.
(odr_or_derived_type_p): Look for main variants.
(odr_name_hasher::equal): Cleanup comment.
(odr_subtypes_equivalent): Add warn and warned arguments; check main
variants.
(type_variants_equivalent_p): break out from ...
(odr_types_equivalent): ... here; go for main variants where needed.
(warn_odr): ... here; turn static.
(warn_types_mismatch): Compare mangled names of main variants.
* ipa-utils.h (types_odr_comparable): Drop strict parameter.
(type_with_linkage_p): Sanity check that we look at main variant.
* lto.c (lto_read_decls): Only consider main variant to be ODR type.
* tree.h (types_same_for_odr): Drop strict argument.
2018-10-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/87746
......@@ -175,6 +175,8 @@ struct default_hash_traits <type_pair>
static bool odr_types_equivalent_p (tree, tree, bool, bool *,
hash_set<type_pair> *,
location_t, location_t);
static void warn_odr (tree t1, tree t2, tree st1, tree st2,
bool warn, bool *warned, const char *reason);
static bool odr_violation_reported = false;
......@@ -381,22 +383,15 @@ odr_vtable_hasher::hash (const odr_type_d *odr_type)
Until we start streaming mangled type names, this function works
only for polymorphic types.
When STRICT is true, we compare types by their names for purposes of
ODR violation warnings. When strict is false, we consider variants
equivalent, because it is all that matters for devirtualization machinery.
*/
bool
types_same_for_odr (const_tree type1, const_tree type2, bool strict)
types_same_for_odr (const_tree type1, const_tree type2)
{
gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2));
if (!strict)
{
type1 = TYPE_MAIN_VARIANT (type1);
type2 = TYPE_MAIN_VARIANT (type2);
}
type1 = TYPE_MAIN_VARIANT (type1);
type2 = TYPE_MAIN_VARIANT (type2);
if (type1 == type2)
return true;
......@@ -470,17 +465,15 @@ types_same_for_odr (const_tree type1, const_tree type2, bool strict)
/* Return true if we can decide on ODR equivalency.
In non-LTO it is always decide, in LTO however it depends in the type has
ODR info attached.
When STRICT is false, compare main variants. */
ODR info attached. */
bool
types_odr_comparable (tree t1, tree t2, bool strict)
types_odr_comparable (tree t1, tree t2)
{
return (!in_lto_p
|| t1 == t2
|| (!strict && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
|| (odr_type_p (t1) && odr_type_p (t2))
|| TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)
|| (odr_type_p (TYPE_MAIN_VARIANT (t1))
&& odr_type_p (TYPE_MAIN_VARIANT (t2)))
|| (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE
&& TYPE_BINFO (t1) && TYPE_BINFO (t2)
&& polymorphic_type_binfo_p (TYPE_BINFO (t1))
......@@ -525,7 +518,7 @@ odr_or_derived_type_p (const_tree t)
{
do
{
if (odr_type_p (t))
if (odr_type_p (TYPE_MAIN_VARIANT (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.
......@@ -540,7 +533,7 @@ odr_or_derived_type_p (const_tree t)
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)))
if (odr_or_derived_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (t))))
return true;
return false;
}
......@@ -566,8 +559,7 @@ odr_name_hasher::equal (const odr_type_d *o1, const tree_node *t2)
return true;
if (!in_lto_p)
return false;
/* Check for anonymous namespaces. Those have !TREE_PUBLIC
on the corresponding TYPE_STUB_DECL. */
/* Check for anonymous namespaces. */
if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
|| (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
return false;
......@@ -639,10 +631,45 @@ set_type_binfo (tree type, tree binfo)
gcc_assert (!TYPE_BINFO (type));
}
/* Return true if type variants match.
This assumes that we already verified that T1 and T2 are variants of the
same type. */
static bool
type_variants_equivalent_p (tree t1, tree t2, bool warn, bool *warned)
{
if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different qualifiers is defined in another "
"translation unit"));
return false;
}
if (comp_type_attributes (t1, t2) != 1)
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different attributes "
"is defined in another translation unit"));
return false;
}
if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)
&& TYPE_ALIGN (t1) != TYPE_ALIGN (t2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different alignment "
"is defined in another translation unit"));
return false;
}
return true;
}
/* Compare T1 and T2 based on name or structure. */
static bool
odr_subtypes_equivalent_p (tree t1, tree t2,
odr_subtypes_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
hash_set<type_pair> *visited,
location_t loc1, location_t loc2)
{
......@@ -654,20 +681,25 @@ odr_subtypes_equivalent_p (tree t1, tree t2,
return true;
/* Anonymous namespace types must match exactly. */
if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
|| (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
|| (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
return false;
/* For ODR types be sure to compare their names.
To support -Wno-odr-type-merging we allow one type to be non-ODR
and other ODR even though it is a violation. */
if (types_odr_comparable (t1, t2, true))
if (types_odr_comparable (t1, t2))
{
if (!types_same_for_odr (t1, t2, true))
if (!types_same_for_odr (t1, t2))
return false;
if (!type_variants_equivalent_p (t1, t2, warn, warned))
return false;
/* Limit recursion: If subtypes are ODR types and we know
that they are same, be happy. */
if (!odr_type_p (t1) || !get_odr_type (t1, true)->odr_violated)
if (!odr_type_p (TYPE_MAIN_VARIANT (t1))
|| !get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated)
return true;
}
......@@ -679,15 +711,19 @@ odr_subtypes_equivalent_p (tree t1, tree t2,
&& (TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE))
return false;
type_pair pair={t1,t2};
if (TYPE_UID (t1) > TYPE_UID (t2))
type_pair pair={TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2)};
if (TYPE_UID (TYPE_MAIN_VARIANT (t1)) > TYPE_UID (TYPE_MAIN_VARIANT (t2)))
{
pair.first = t2;
pair.second = t1;
pair.first = TYPE_MAIN_VARIANT (t2);
pair.second = TYPE_MAIN_VARIANT (t1);
}
if (visited->add (pair))
return true;
return odr_types_equivalent_p (t1, t2, false, NULL, visited, loc1, loc2);
if (odr_types_equivalent_p (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2),
false, NULL, visited, loc1, loc2)
&& !type_variants_equivalent_p (t1, t2, warn, warned))
return false;
return true;
}
/* Return true if DECL1 and DECL2 are identical methods. Consider
......@@ -959,7 +995,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
If WARN is false, do nothing. Set WARNED if warning was indeed
output. */
void
static void
warn_odr (tree t1, tree t2, tree st1, tree st2,
bool warn, bool *warned, const char *reason)
{
......@@ -1083,10 +1119,13 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
/* It is a quite common bug to reference anonymous namespace type in
non-anonymous namespace class. */
if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
|| (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
|| (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
{
if (type_with_linkage_p (t1) && !type_in_anonymous_namespace_p (t1))
if (type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
&& !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
{
std::swap (t1, t2);
std::swap (loc_t1, loc_t2);
......@@ -1094,10 +1133,15 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
gcc_assert (TYPE_NAME (t1) && TYPE_NAME (t2)
&& TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
&& TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL);
tree n1 = TYPE_NAME (t1);
tree n2 = TYPE_NAME (t2);
if (TREE_CODE (n1) == TYPE_DECL)
n1 = DECL_NAME (n1);
if (TREE_CODE (n2) == TYPE_DECL)
n1 = DECL_NAME (n2);
/* Most of the time, the type names will match, do not be unnecesarily
verbose. */
if (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t1)))
!= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t2))))
if (IDENTIFIER_POINTER (n1) != IDENTIFIER_POINTER (n2))
inform (loc_t1,
"type %qT defined in anonymous namespace can not match "
"type %qT across the translation unit boundary",
......@@ -1112,22 +1156,24 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
"the incompatible type defined in another translation unit");
return;
}
tree mt1 = TYPE_MAIN_VARIANT (t1);
tree mt2 = TYPE_MAIN_VARIANT (t2);
/* If types have mangled ODR names and they are different, it is most
informative to output those.
This also covers types defined in different namespaces. */
if (TYPE_NAME (t1) && TYPE_NAME (t2)
&& TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
&& TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
&& DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t1))
&& DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t2))
&& DECL_ASSEMBLER_NAME (TYPE_NAME (t1))
!= DECL_ASSEMBLER_NAME (TYPE_NAME (t2)))
if (TYPE_NAME (mt1) && TYPE_NAME (mt2)
&& TREE_CODE (TYPE_NAME (mt1)) == TYPE_DECL
&& TREE_CODE (TYPE_NAME (mt2)) == TYPE_DECL
&& DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (mt1))
&& DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (mt2))
&& DECL_ASSEMBLER_NAME (TYPE_NAME (mt1))
!= DECL_ASSEMBLER_NAME (TYPE_NAME (mt2)))
{
char *name1 = xstrdup (cplus_demangle
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t1))),
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (mt1))),
DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES));
char *name2 = cplus_demangle
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t2))),
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (mt2))),
DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES);
if (name1 && name2 && strcmp (name1, name2))
{
......@@ -1216,8 +1262,8 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
return;
}
if (types_odr_comparable (t1, t2, true)
&& types_same_for_odr (t1, t2, true))
if (types_odr_comparable (t1, t2)
&& types_same_for_odr (t1, t2))
inform (loc_t1,
"type %qT itself violates the C++ One Definition Rule", t1);
/* Prevent pointless warnings like "struct aa" should match "struct aa". */
......@@ -1246,8 +1292,10 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
/* Check first for the obvious case of pointer identity. */
if (t1 == t2)
return true;
gcc_assert (!type_with_linkage_p (t1) || !type_in_anonymous_namespace_p (t1));
gcc_assert (!type_with_linkage_p (t2) || !type_in_anonymous_namespace_p (t2));
gcc_assert (!type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
|| !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)));
gcc_assert (!type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
|| !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2)));
/* Can't be the same type if the types don't have the same code. */
if (TREE_CODE (t1) != TREE_CODE (t2))
......@@ -1257,16 +1305,10 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
return false;
}
if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different qualifiers is defined in another "
"translation unit"));
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)))
if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
|| (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
{
/* We can not trip this when comparing ODR types, only when trying to
match different ODR derivations from different declarations.
......@@ -1275,14 +1317,6 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
return false;
}
if (comp_type_attributes (t1, t2) != 1)
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different attributes "
"is defined in another translation unit"));
return false;
}
if (TREE_CODE (t1) == ENUMERAL_TYPE
&& TYPE_VALUES (t1) && TYPE_VALUES (t2))
{
......@@ -1366,7 +1400,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
}
if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
visited, loc1, loc2))
warn, warned, visited, loc1, loc2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("it is defined as a pointer to different type "
......@@ -1380,6 +1414,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
if ((TREE_CODE (t1) == VECTOR_TYPE || TREE_CODE (t1) == COMPLEX_TYPE)
&& !odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
warn, warned,
visited, loc1, loc2))
{
/* Probably specific enough. */
......@@ -1399,7 +1434,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
/* Array types are the same if the element types are the same and
the number of elements are the same. */
if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
visited, loc1, loc2))
warn, warned, visited, loc1, loc2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a different type is defined in another "
......@@ -1417,7 +1452,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
/* For an incomplete external array, the type domain can be
NULL_TREE. Check this condition also. */
if (i1 == NULL_TREE || i2 == NULL_TREE)
return true;
return type_variants_equivalent_p (t1, t2, warn, warned);
tree min1 = TYPE_MIN_VALUE (i1);
tree min2 = TYPE_MIN_VALUE (i2);
......@@ -1441,7 +1476,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
/* Function types are the same if the return type and arguments types
are the same. */
if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
visited, loc1, loc2))
warn, warned, visited, loc1, loc2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("has different return value "
......@@ -1453,7 +1488,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)
|| !prototype_p (t1) || !prototype_p (t2))
return true;
return type_variants_equivalent_p (t1, t2, warn, warned);
else
{
tree parms1, parms2;
......@@ -1463,8 +1498,8 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
{
if (!odr_subtypes_equivalent_p
(TREE_VALUE (parms1), TREE_VALUE (parms2), visited,
loc1, loc2))
(TREE_VALUE (parms1), TREE_VALUE (parms2), warn, warned,
visited, loc1, loc2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("has different parameters in another "
......@@ -1484,7 +1519,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
return false;
}
return true;
return type_variants_equivalent_p (t1, t2, warn, warned);
}
case RECORD_TYPE:
......@@ -1544,8 +1579,8 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
return false;
}
if (!odr_subtypes_equivalent_p (TREE_TYPE (f1),
TREE_TYPE (f2), visited,
loc1, loc2))
TREE_TYPE (f2), warn, warned,
visited, loc1, loc2))
{
/* Do not warn about artificial fields and just go into
generic field mismatch warning. */
......@@ -1622,18 +1657,11 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
"is defined in another translation unit"));
return false;
}
if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)
&& TYPE_ALIGN (t1) != TYPE_ALIGN (t2))
{
warn_odr (t1, t2, NULL, NULL, warn, warned,
G_("a type with different alignment "
"is defined in another translation unit"));
return false;
}
gcc_assert (!TYPE_SIZE_UNIT (t1) || !TYPE_SIZE_UNIT (t2)
|| operand_equal_p (TYPE_SIZE_UNIT (t1),
TYPE_SIZE_UNIT (t2), 0));
return true;
return type_variants_equivalent_p (t1, t2, warn, warned);
}
/* Return true if TYPE1 and TYPE2 are equivalent for One Definition Rule. */
......
......@@ -83,7 +83,7 @@ bool type_known_to_have_no_derivations_p (tree);
bool contains_polymorphic_type_p (const_tree);
void register_odr_type (tree);
bool types_must_be_same_for_odr (tree, tree);
bool types_odr_comparable (tree, tree, bool strict = false);
bool types_odr_comparable (tree, tree);
cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT,
ipa_polymorphic_call_context);
void warn_types_mismatch (tree t1, tree t2, location_t loc1 = UNKNOWN_LOCATION,
......@@ -179,6 +179,7 @@ polymorphic_type_binfo_p (const_tree binfo)
inline bool
type_with_linkage_p (const_tree t)
{
gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
return false;
......
......@@ -1827,7 +1827,7 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
type canonical of a derived type in the same SCC. */
if (!TYPE_CANONICAL (t))
gimple_register_canonical_type (t);
if (odr_type_p (t))
if (TYPE_MAIN_VARIANT (t) == t && odr_type_p (t))
odr_types.safe_push (t);
}
/* Link shared INTEGER_CSTs into TYPE_CACHED_VALUEs of its
......
......@@ -4958,8 +4958,7 @@ extern tree block_ultimate_origin (const_tree);
extern tree get_binfo_at_offset (tree, poly_int64, tree);
extern bool virtual_method_call_p (const_tree);
extern tree obj_type_ref_class (const_tree ref);
extern bool types_same_for_odr (const_tree type1, const_tree type2,
bool strict=false);
extern bool types_same_for_odr (const_tree type1, const_tree type2);
extern bool contains_bitfld_component_ref_p (const_tree);
extern bool block_may_fallthru (const_tree);
extern void using_eh_for_cleanups (void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment