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