From: Jan Hubicka Date: Fri, 26 Oct 2018 07:20:01 +0000 (+0200) Subject: ipa-devirt.c (warn_odr): Make static. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=420672bc92e560bcebf12bdd1f3423362c93bf2e;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 46524ee4d51..87e79471af8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2018-10-26 Jan Hubicka + + * 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 PR tree-optimization/87746 diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 0c6e76a65fe..df880fe4145 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -175,6 +175,8 @@ struct default_hash_traits static bool odr_types_equivalent_p (tree, tree, bool, bool *, hash_set *, 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 *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. */ diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index 7d663ec6b0e..371b2fbdb98 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -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; diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 598492df527..2d52d4a8f4e 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -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 diff --git a/gcc/tree.h b/gcc/tree.h index 2e45f9db2e3..0ef96ba5612 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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);