aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index f78a2c2..02f0a7a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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