diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 32 |
1 files changed, 27 insertions, 5 deletions
@@ -13012,6 +13012,23 @@ verify_type_variant (const_tree t, tree tv) back to pointer-comparison of TYPE_CANONICAL for aggregates for example. */ +/* Return true if TYPE_UNSIGNED of TYPE should be ignored for canonical + type calculation because we need to allow inter-operability between signed + and unsigned variants. */ + +bool +type_with_interoperable_signedness (const_tree type) +{ + /* Fortran standard require C_SIGNED_CHAR to be interoperable with both + signed char and unsigned char. Similarly fortran FE builds + C_SIZE_T as signed type, while C defines it unsigned. */ + + return tree_code_for_canonical_type_merging (TREE_CODE (type)) + == INTEGER_TYPE + && (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node) + || TYPE_PRECISION (type) == TYPE_PRECISION (size_type_node)); +} + /* 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 @@ -13062,8 +13079,8 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2, 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_for_canonical_type_merging (TREE_CODE (t1)) - != tree_code_for_canonical_type_merging (TREE_CODE (t2))) + enum tree_code code = tree_code_for_canonical_type_merging (TREE_CODE (t1)); + if (code != tree_code_for_canonical_type_merging (TREE_CODE (t2))) return false; /* Qualifiers do not matter for canonical type comparison purposes. */ @@ -13086,9 +13103,14 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2, || 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)) + /* Can't be the same type if they have different recision. */ + if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)) + return false; + + /* In some cases the signed and unsigned types are required to be + inter-operable. */ + if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2) + && !type_with_interoperable_signedness (t1)) return false; /* Fortran's C_SIGNED_CHAR is !TYPE_STRING_FLAG but needs to be |