From 872d5034baa1007606d405e37937908602fbbe51 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 19 May 2015 19:17:21 +0200 Subject: [PATCH] tree.c (verify_type_variant): Fix #undef. * tree.c (verify_type_variant): Fix #undef. (gimple_canonical_types_compatible_p): Move here from lto.c (verify_type): Verify TYPE_CANONICAL compatibility. * tree.h (gimple_canonical_types_compatible_p): Declare. * lto.c (gimple_canonical_types_compatible_p): Move to tree.c From-SVN: r223391 --- gcc/ChangeLog | 7 ++ gcc/lto/ChangeLog | 4 + gcc/lto/lto.c | 202 ------------------------------------- gcc/tree.c | 247 +++++++++++++++++++++++++++++++++++++++++++++- gcc/tree.h | 2 + 5 files changed, 259 insertions(+), 203 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5ab8283a8be..8c8a5268018 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-05-19 Jan Hubicka + + * tree.c (verify_type_variant): Fix #undef. + (gimple_canonical_types_compatible_p): Move here from lto.c + (verify_type): Verify TYPE_CANONICAL compatibility. + * tree.h (gimple_canonical_types_compatible_p): Declare. + 2015-05-19 Jakub Jelinek PR middle-end/66199 diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 3725d1a25eb..335bd545fe0 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,7 @@ +2015-05-19 Jan Hubicka + + * lto.c (gimple_canonical_types_compatible_p): Move to tree.c + 2015-05-17 Jan Hubicka * lto-symtab.c (warn_type_compatibility_p): Break out from ...; diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 4b4005b4b36..26697443010 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -441,208 +441,6 @@ gimple_canonical_type_hash (const void *p) } -/* The TYPE_CANONICAL merging machinery. It should closely resemble - the middle-end types_compatible_p function. It needs to avoid - claiming types are different for types that should be treated - the same with respect to TBAA. Canonical types are also used - for IL consistency checks via the useless_type_conversion_p - predicate which does not handle all type kinds itself but falls - back to pointer-comparison of TYPE_CANONICAL for aggregates - for example. */ - -/* Return true iff T1 and T2 are structurally identical for what - TBAA is concerned. */ - -static bool -gimple_canonical_types_compatible_p (tree t1, tree t2) -{ - /* Before starting to set up the SCC machinery handle simple cases. */ - - /* Check first for the obvious case of pointer identity. */ - if (t1 == t2) - return true; - - /* Check that we have two types to compare. */ - if (t1 == NULL_TREE || t2 == NULL_TREE) - return false; - - /* If the types have been previously registered and found equal - they still are. */ - if (TYPE_CANONICAL (t1) - && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)) - return true; - - /* Can't be the same type if the types don't have the same code. */ - if (TREE_CODE (t1) != TREE_CODE (t2)) - return false; - - /* Qualifiers do not matter for canonical type comparison purposes. */ - - /* Void types and nullptr types are always the same. */ - if (TREE_CODE (t1) == VOID_TYPE - || TREE_CODE (t1) == NULLPTR_TYPE) - return true; - - /* Can't be the same type if they have different mode. */ - if (TYPE_MODE (t1) != TYPE_MODE (t2)) - return false; - - /* Non-aggregate types can be handled cheaply. */ - if (INTEGRAL_TYPE_P (t1) - || SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1) - || TREE_CODE (t1) == VECTOR_TYPE - || TREE_CODE (t1) == COMPLEX_TYPE - || TREE_CODE (t1) == OFFSET_TYPE - || POINTER_TYPE_P (t1)) - { - /* Can't be the same type if they have different sign or precision. */ - if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) - || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) - return false; - - if (TREE_CODE (t1) == INTEGER_TYPE - && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) - return false; - - /* For canonical type comparisons we do not want to build SCCs - so we cannot compare pointed-to types. But we can, for now, - require the same pointed-to type kind and match what - useless_type_conversion_p would do. */ - if (POINTER_TYPE_P (t1)) - { - if (TYPE_ADDR_SPACE (TREE_TYPE (t1)) - != TYPE_ADDR_SPACE (TREE_TYPE (t2))) - return false; - - if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2))) - return false; - } - - /* Tail-recurse to components. */ - if (TREE_CODE (t1) == VECTOR_TYPE - || TREE_CODE (t1) == COMPLEX_TYPE) - return gimple_canonical_types_compatible_p (TREE_TYPE (t1), - TREE_TYPE (t2)); - - return true; - } - - /* Do type-specific comparisons. */ - switch (TREE_CODE (t1)) - { - case ARRAY_TYPE: - /* Array types are the same if the element types are the same and - the number of elements are the same. */ - if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)) - || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2) - || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2)) - return false; - else - { - tree i1 = TYPE_DOMAIN (t1); - tree i2 = TYPE_DOMAIN (t2); - - /* 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; - else if (i1 == NULL_TREE || i2 == NULL_TREE) - return false; - else - { - tree min1 = TYPE_MIN_VALUE (i1); - tree min2 = TYPE_MIN_VALUE (i2); - tree max1 = TYPE_MAX_VALUE (i1); - tree max2 = TYPE_MAX_VALUE (i2); - - /* The minimum/maximum values have to be the same. */ - if ((min1 == min2 - || (min1 && min2 - && ((TREE_CODE (min1) == PLACEHOLDER_EXPR - && TREE_CODE (min2) == PLACEHOLDER_EXPR) - || operand_equal_p (min1, min2, 0)))) - && (max1 == max2 - || (max1 && max2 - && ((TREE_CODE (max1) == PLACEHOLDER_EXPR - && TREE_CODE (max2) == PLACEHOLDER_EXPR) - || operand_equal_p (max1, max2, 0))))) - return true; - else - return false; - } - } - - case METHOD_TYPE: - case FUNCTION_TYPE: - /* Function types are the same if the return type and arguments types - are the same. */ - if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) - return false; - - if (!comp_type_attributes (t1, t2)) - return false; - - if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) - return true; - else - { - tree parms1, parms2; - - for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); - parms1 && parms2; - parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2)) - { - if (!gimple_canonical_types_compatible_p - (TREE_VALUE (parms1), TREE_VALUE (parms2))) - return false; - } - - if (parms1 || parms2) - return false; - - return true; - } - - case RECORD_TYPE: - case UNION_TYPE: - case QUAL_UNION_TYPE: - { - tree f1, f2; - - /* For aggregate types, all the fields must be the same. */ - for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); - f1 || f2; - f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) - { - /* Skip non-fields. */ - while (f1 && TREE_CODE (f1) != FIELD_DECL) - f1 = TREE_CHAIN (f1); - while (f2 && TREE_CODE (f2) != FIELD_DECL) - f2 = TREE_CHAIN (f2); - if (!f1 || !f2) - break; - /* The fields must have the same name, offset and type. */ - if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2) - || !gimple_compare_field_offset (f1, f2) - || !gimple_canonical_types_compatible_p - (TREE_TYPE (f1), TREE_TYPE (f2))) - return false; - } - - /* If one aggregate has more fields than the other, they - are not the same. */ - if (f1 || f2) - return false; - - return true; - } - - default: - gcc_unreachable (); - } -} - /* Returns nonzero if P1 and P2 are equal. */ diff --git a/gcc/tree.c b/gcc/tree.c index 6297f04865c..0ab965f3c94 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12687,10 +12687,225 @@ verify_type_variant (const_tree t, tree tv) return false; } return true; -#undef verify_type_variant +#undef verify_variant_match } +/* The TYPE_CANONICAL merging machinery. It should closely resemble + the middle-end types_compatible_p function. It needs to avoid + claiming types are different for types that should be treated + the same with respect to TBAA. Canonical types are also used + for IL consistency checks via the useless_type_conversion_p + predicate which does not handle all type kinds itself but falls + back to pointer-comparison of TYPE_CANONICAL for aggregates + for example. */ + +/* Return true iff T1 and T2 are structurally identical for what + TBAA is concerned. + This function is used both by lto.c canonical type merging and by the + verifier. If TRUST_TYPE_CANONICAL we do not look into structure of types + that have TYPE_CANONICAL defined and assume them equivalent. */ + +bool +gimple_canonical_types_compatible_p (const_tree t1, const_tree t2, + bool trust_type_canonical) +{ + /* Before starting to set up the SCC machinery handle simple cases. */ + + /* Check first for the obvious case of pointer identity. */ + if (t1 == t2) + return true; + + /* Check that we have two types to compare. */ + if (t1 == NULL_TREE || t2 == NULL_TREE) + return false; + + /* If the types have been previously registered and found equal + they still are. */ + if (TYPE_CANONICAL (t1) && TYPE_CANONICAL (t2) + && trust_type_canonical) + return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2); + + /* Can't be the same type if the types don't have the same code. */ + if (TREE_CODE (t1) != TREE_CODE (t2)) + return false; + + /* Qualifiers do not matter for canonical type comparison purposes. */ + + /* Void types and nullptr types are always the same. */ + if (TREE_CODE (t1) == VOID_TYPE + || TREE_CODE (t1) == NULLPTR_TYPE) + return true; + + /* Can't be the same type if they have different mode. */ + if (TYPE_MODE (t1) != TYPE_MODE (t2)) + return false; + + /* Non-aggregate types can be handled cheaply. */ + if (INTEGRAL_TYPE_P (t1) + || SCALAR_FLOAT_TYPE_P (t1) + || FIXED_POINT_TYPE_P (t1) + || TREE_CODE (t1) == VECTOR_TYPE + || TREE_CODE (t1) == COMPLEX_TYPE + || TREE_CODE (t1) == OFFSET_TYPE + || POINTER_TYPE_P (t1)) + { + /* Can't be the same type if they have different sign or precision. */ + if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) + || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) + return false; + + if (TREE_CODE (t1) == INTEGER_TYPE + && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) + return false; + + /* For canonical type comparisons we do not want to build SCCs + so we cannot compare pointed-to types. But we can, for now, + require the same pointed-to type kind and match what + useless_type_conversion_p would do. */ + if (POINTER_TYPE_P (t1)) + { + if (TYPE_ADDR_SPACE (TREE_TYPE (t1)) + != TYPE_ADDR_SPACE (TREE_TYPE (t2))) + return false; + + if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2))) + return false; + } + + /* Tail-recurse to components. */ + if (TREE_CODE (t1) == VECTOR_TYPE + || TREE_CODE (t1) == COMPLEX_TYPE) + return gimple_canonical_types_compatible_p (TREE_TYPE (t1), + TREE_TYPE (t2), + trust_type_canonical); + + return true; + } + + /* Do type-specific comparisons. */ + switch (TREE_CODE (t1)) + { + case ARRAY_TYPE: + /* Array types are the same if the element types are the same and + the number of elements are the same. */ + if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2), + trust_type_canonical) + || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2) + || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2)) + return false; + else + { + tree i1 = TYPE_DOMAIN (t1); + tree i2 = TYPE_DOMAIN (t2); + + /* 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; + else if (i1 == NULL_TREE || i2 == NULL_TREE) + return false; + else + { + tree min1 = TYPE_MIN_VALUE (i1); + tree min2 = TYPE_MIN_VALUE (i2); + tree max1 = TYPE_MAX_VALUE (i1); + tree max2 = TYPE_MAX_VALUE (i2); + + /* The minimum/maximum values have to be the same. */ + if ((min1 == min2 + || (min1 && min2 + && ((TREE_CODE (min1) == PLACEHOLDER_EXPR + && TREE_CODE (min2) == PLACEHOLDER_EXPR) + || operand_equal_p (min1, min2, 0)))) + && (max1 == max2 + || (max1 && max2 + && ((TREE_CODE (max1) == PLACEHOLDER_EXPR + && TREE_CODE (max2) == PLACEHOLDER_EXPR) + || operand_equal_p (max1, max2, 0))))) + return true; + else + return false; + } + } + + case METHOD_TYPE: + case FUNCTION_TYPE: + /* Function types are the same if the return type and arguments types + are the same. */ + if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2), + trust_type_canonical)) + return false; + + if (!comp_type_attributes (t1, t2)) + return false; + + if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) + return true; + else + { + tree parms1, parms2; + + for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); + parms1 && parms2; + parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2)) + { + if (!gimple_canonical_types_compatible_p + (TREE_VALUE (parms1), TREE_VALUE (parms2), + trust_type_canonical)) + return false; + } + + if (parms1 || parms2) + return false; + + return true; + } + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + { + tree f1, f2; + + /* For aggregate types, all the fields must be the same. */ + for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); + f1 || f2; + f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) + { + /* Skip non-fields. */ + while (f1 && TREE_CODE (f1) != FIELD_DECL) + f1 = TREE_CHAIN (f1); + while (f2 && TREE_CODE (f2) != FIELD_DECL) + f2 = TREE_CHAIN (f2); + if (!f1 || !f2) + break; + /* The fields must have the same name, offset and type. */ + if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2) + || !gimple_compare_field_offset (f1, f2) + || !gimple_canonical_types_compatible_p + (TREE_TYPE (f1), TREE_TYPE (f2), + trust_type_canonical)) + return false; + } + + /* If one aggregate has more fields than the other, they + are not the same. */ + if (f1 || f2) + return false; + + return true; + } + + default: + /* Consider all types with language specific trees in them mutually + compatible. This is executed only from verify_type and false + positives can be tolerated. */ + gcc_assert (!in_lto_p); + return true; + } +} + /* Verify type T. */ void @@ -12712,6 +12927,36 @@ verify_type (const_tree t) else if (t != mv && !verify_type_variant (t, mv)) error_found = true; + tree ct = TYPE_CANONICAL (t); + if (!ct) + ; + else if (TYPE_CANONICAL (t) != ct) + { + error ("TYPE_CANONICAL has different TYPE_CANONICAL"); + debug_tree (ct); + error_found = true; + } + /* Method and function types can not be used to address memory and thus + TYPE_CANONICAL really matters only for determining useless conversions. + + FIXME: C++ FE does not agree with gimple_canonical_types_compatible_p + here. gimple_canonical_types_compatible_p calls comp_type_attributes + while for C++ FE the attributes does not make difference. */ + else if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE) + ; + else if (t != ct + /* FIXME: gimple_canonical_types_compatible_p can not compare types + with variably sized arrays because their sizes possibly + gimplified to different variables. */ + && !variably_modified_type_p (ct, NULL) + && !gimple_canonical_types_compatible_p (t, ct, false)) + { + error ("TYPE_CANONICAL is not compatible"); + debug_tree (ct); + error_found = true; + } + + /* Check various uses of TYPE_MINVAL. */ if (RECORD_OR_UNION_TYPE_P (t)) { diff --git a/gcc/tree.h b/gcc/tree.h index 1d88e297d63..2bac6988bcf 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4569,6 +4569,8 @@ extern int tree_map_base_eq (const void *, const void *); extern unsigned int tree_map_base_hash (const void *); extern int tree_map_base_marked_p (const void *); extern void DEBUG_FUNCTION verify_type (const_tree t); +extern bool gimple_canonical_types_compatible_p (const_tree, const_tree, + bool trust_type_canonical = true); #define tree_map_eq tree_map_base_eq extern unsigned int tree_map_hash (const void *); -- 2.30.2