aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/utils.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-04-08 11:41:59 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-04-08 11:41:59 +0000
commitba3f46d0910139e56300a68bc7992c0217b7adb9 (patch)
treee039d18b7e69f9b896b96ec52a36f7115dac70fc /gcc/ada/utils.c
parent373140ef746ba530ad7d3ff56c9e6aea4aacdf0f (diff)
downloadgcc-ba3f46d0910139e56300a68bc7992c0217b7adb9.zip
gcc-ba3f46d0910139e56300a68bc7992c0217b7adb9.tar.gz
gcc-ba3f46d0910139e56300a68bc7992c0217b7adb9.tar.bz2
decl.c (gnat_to_gnu_entity): If -gnatd.a and not optimizing alignment for space...
* decl.c (gnat_to_gnu_entity) <object>: If -gnatd.a and not optimizing alignment for space, promote the alignment of non-scalar variables with no size and alignment. * gigi.h (gnat_types_compatible_p): Declare. * misc.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Set to above predicate. * trans.c (gnat_to_gnu): Revert revision 129339 change. Minor cleanup. * utils.c (gnat_types_compatible_p) : New predicate. (convert): Use it throughout to test for cases where a mere view conversion is sufficient. * utils2.c (build_binary_op): Minor tweaks. (build_unary_op): Likewise. From-SVN: r134092
Diffstat (limited to 'gcc/ada/utils.c')
-rw-r--r--gcc/ada/utils.c81
1 files changed, 57 insertions, 24 deletions
diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c
index 5c96217..5186ccb 100644
--- a/gcc/ada/utils.c
+++ b/gcc/ada/utils.c
@@ -2378,6 +2378,42 @@ gnat_signed_type (tree type_node)
return type;
}
+/* Return 1 if the types T1 and T2 are compatible, i.e. if they can be
+ transparently converted to each other. */
+
+int
+gnat_types_compatible_p (tree t1, tree t2)
+{
+ enum tree_code code;
+
+ /* This is the default criterion. */
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return 1;
+
+ /* We only check structural equivalence here. */
+ if ((code = TREE_CODE (t1)) != TREE_CODE (t2))
+ return 0;
+
+ /* Array types are also compatible if they are constrained and have
+ the same component type and the same domain. */
+ if (code == ARRAY_TYPE
+ && TREE_TYPE (t1) == TREE_TYPE (t2)
+ && tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (t1)),
+ TYPE_MIN_VALUE (TYPE_DOMAIN (t2)))
+ && tree_int_cst_equal (TYPE_MAX_VALUE (TYPE_DOMAIN (t1)),
+ TYPE_MAX_VALUE (TYPE_DOMAIN (t2))))
+ return 1;
+
+ /* Padding record types are also compatible if they pad the same
+ type and have the same constant size. */
+ if (code == RECORD_TYPE
+ && TYPE_IS_PADDING_P (t1) && TYPE_IS_PADDING_P (t2)
+ && TREE_TYPE (TYPE_FIELDS (t1)) == TREE_TYPE (TYPE_FIELDS (t2))
+ && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
+ return 1;
+
+ return 0;
+}
/* EXP is an expression for the size of an object. If this size contains
discriminant references, replace them with the maximum (if MAX_P) or
@@ -3368,15 +3404,15 @@ convert (tree type, tree expr)
/* If both input and output have padding and are of variable size, do this
as an unchecked conversion. Likewise if one is a mere variant of the
other, so we avoid a pointless unpad/repad sequence. */
- else if (ecode == RECORD_TYPE && code == RECORD_TYPE
+ else if (code == RECORD_TYPE && ecode == RECORD_TYPE
&& TYPE_IS_PADDING_P (type) && TYPE_IS_PADDING_P (etype)
&& (!TREE_CONSTANT (TYPE_SIZE (type))
|| !TREE_CONSTANT (TYPE_SIZE (etype))
- || TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype)))
+ || gnat_types_compatible_p (type, etype)))
;
- /* If the output type has padding, make a constructor to build the
- record. */
+ /* If the output type has padding, convert to the inner type and
+ make a constructor to build the record. */
else if (code == RECORD_TYPE && TYPE_IS_PADDING_P (type))
{
/* If we previously converted from another type and our type is
@@ -3387,12 +3423,15 @@ convert (tree type, tree expr)
expr = TREE_OPERAND (expr, 0);
/* If we are just removing the padding from expr, convert the original
- object if we have variable size. That will avoid the need
- for some variable-size temporaries. */
+ object if we have variable size in order to avoid the need for some
+ variable-size temporaries. Likewise if the padding is a mere variant
+ of the other, so we avoid a pointless unpad/repad sequence. */
if (TREE_CODE (expr) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE
&& TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
- && !TREE_CONSTANT (TYPE_SIZE (type)))
+ && (!TREE_CONSTANT (TYPE_SIZE (type))
+ || gnat_types_compatible_p (type,
+ TREE_TYPE (TREE_OPERAND (expr, 0)))))
return convert (type, TREE_OPERAND (expr, 0));
/* If the result type is a padded type with a self-referentially-sized
@@ -3506,14 +3545,9 @@ convert (tree type, tree expr)
break;
case CONSTRUCTOR:
- /* If we are converting a CONSTRUCTOR to another constrained array type
- with the same domain, just make a new one in the proper type. */
- if (code == ecode && code == ARRAY_TYPE
- && TREE_TYPE (type) == TREE_TYPE (etype)
- && tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
- TYPE_MIN_VALUE (TYPE_DOMAIN (etype)))
- && tree_int_cst_equal (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
- TYPE_MAX_VALUE (TYPE_DOMAIN (etype))))
+ /* If we are converting a CONSTRUCTOR to a mere variant type, just make
+ a new one in the proper type. */
+ if (gnat_types_compatible_p (type, etype))
{
expr = copy_node (expr);
TREE_TYPE (expr) = type;
@@ -3539,7 +3573,6 @@ convert (tree type, tree expr)
the inner operand to the output type is fine in most cases, it
might expose unexpected input/output type mismatches in special
circumstances so we avoid such recursive calls when we can. */
-
tree op0 = TREE_OPERAND (expr, 0);
/* If we are converting back to the original type, we can just
@@ -3549,13 +3582,13 @@ convert (tree type, tree expr)
return op0;
/* Otherwise, if we're converting between two aggregate types, we
- might be allowed to substitute the VIEW_CONVERT target type in
- place or to just convert the inner expression. */
+ might be allowed to substitute the VIEW_CONVERT_EXPR target type
+ in place or to just convert the inner expression. */
if (AGGREGATE_TYPE_P (type) && AGGREGATE_TYPE_P (etype))
{
- /* If we are converting between type variants, we can just
- substitute the VIEW_CONVERT in place. */
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype))
+ /* If we are converting between mere variants, we can just
+ substitute the VIEW_CONVERT_EXPR in place. */
+ if (gnat_types_compatible_p (type, etype))
return build1 (VIEW_CONVERT_EXPR, type, op0);
/* Otherwise, we may just bypass the input view conversion unless
@@ -3594,10 +3627,10 @@ convert (tree type, tree expr)
if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype))
return convert_to_fat_pointer (type, expr);
- /* If we're converting between two aggregate types that have the same main
- variant, just make a VIEW_CONVER_EXPR. */
+ /* If we're converting between two aggregate types that are mere
+ variants, just make a VIEW_CONVERT_EXPR. */
else if (AGGREGATE_TYPE_P (type)
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype))
+ && gnat_types_compatible_p (type, etype))
return build1 (VIEW_CONVERT_EXPR, type, expr);
/* In all other cases of related types, make a NOP_EXPR. */