summaryrefslogtreecommitdiff
path: root/gcc/ada/utils2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/utils2.c')
-rw-r--r--gcc/ada/utils2.c155
1 files changed, 79 insertions, 76 deletions
diff --git a/gcc/ada/utils2.c b/gcc/ada/utils2.c
index e9b5429520b..f681f1c2508 100644
--- a/gcc/ada/utils2.c
+++ b/gcc/ada/utils2.c
@@ -6,9 +6,9 @@
* *
* C Implementation File *
* *
- * $Revision: 1.3 $
+ * $Revision$
* *
- * Copyright (C) 1992-2001, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2002, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -233,7 +233,7 @@ contains_save_expr_p (exp)
case ADDR_EXPR: case INDIRECT_REF:
case COMPONENT_REF:
- case NOP_EXPR: case CONVERT_EXPR: case UNCHECKED_CONVERT_EXPR:
+ case NOP_EXPR: case CONVERT_EXPR: case VIEW_CONVERT_EXPR:
return contains_save_expr_p (TREE_OPERAND (exp, 0));
case CONSTRUCTOR:
@@ -446,7 +446,7 @@ compare_arrays (result_type, a1, a2)
result = build_binary_op (TRUTH_ANDIF_EXPR, result_type, result,
- build (EQ_EXPR, result_type, a1, a2));
+ fold (build (EQ_EXPR, result_type, a1, a2)));
}
@@ -647,7 +647,7 @@ build_binary_op (op_code, result_type, left_operand, right_operand)
unless we are not changing the mode. */
while ((TREE_CODE (left_operand) == CONVERT_EXPR
|| TREE_CODE (left_operand) == NOP_EXPR
- || TREE_CODE (left_operand) == UNCHECKED_CONVERT_EXPR)
+ || TREE_CODE (left_operand) == VIEW_CONVERT_EXPR)
&& (((INTEGRAL_TYPE_P (left_type)
|| POINTER_TYPE_P (left_type))
&& (INTEGRAL_TYPE_P (TREE_TYPE
@@ -680,20 +680,20 @@ build_binary_op (op_code, result_type, left_operand, right_operand)
/* If the RHS has a conversion between record and array types and
an inner type is no worse, use it. Note we cannot do this for
- modular types or types with TYPE_ALIGN_OK_P, since the latter
+ modular types or types with TYPE_ALIGN_OK, since the latter
might indicate a conversion between a root type and a class-wide
type, which we must not remove. */
- while (TREE_CODE (right_operand) == UNCHECKED_CONVERT_EXPR
+ while (TREE_CODE (right_operand) == VIEW_CONVERT_EXPR
&& ((TREE_CODE (right_type) == RECORD_TYPE
&& ! TYPE_LEFT_JUSTIFIED_MODULAR_P (right_type)
- && ! TYPE_ALIGN_OK_P (right_type)
+ && ! TYPE_ALIGN_OK (right_type)
&& ! TYPE_IS_FAT_POINTER_P (right_type))
|| TREE_CODE (right_type) == ARRAY_TYPE)
&& (((TREE_CODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
== RECORD_TYPE)
&& ! (TYPE_LEFT_JUSTIFIED_MODULAR_P
(TREE_TYPE (TREE_OPERAND (right_operand, 0))))
- && ! (TYPE_ALIGN_OK_P
+ && ! (TYPE_ALIGN_OK
(TREE_TYPE (TREE_OPERAND (right_operand, 0))))
&& ! (TYPE_IS_FAT_POINTER_P
(TREE_TYPE (TREE_OPERAND (right_operand, 0)))))
@@ -719,32 +719,45 @@ build_binary_op (op_code, result_type, left_operand, right_operand)
operation_type = best_type;
/* If a class-wide type may be involved, force use of the RHS type. */
- if (TREE_CODE (right_type) == RECORD_TYPE
- && TYPE_ALIGN_OK_P (right_type))
+ if (TREE_CODE (right_type) == RECORD_TYPE && TYPE_ALIGN_OK (right_type))
operation_type = right_type;
- /* After we strip off any COMPONENT_REF, ARRAY_REF, or ARRAY_RANGE_REF
- from the lhs, we must have either an INDIRECT_REF or a decl. Allow
- UNCHECKED_CONVERT_EXPRs, but set TREE_ADDRESSABLE to show they are
- in an LHS. Finally, allow NOP_EXPR if both types are the same tree
- code and mode because we know these will be nops. */
- for (result = left_operand;
- TREE_CODE (result) == COMPONENT_REF
- || TREE_CODE (result) == ARRAY_REF
- || TREE_CODE (result) == ARRAY_RANGE_REF
- || TREE_CODE (result) == REALPART_EXPR
- || TREE_CODE (result) == IMAGPART_EXPR
- || TREE_CODE (result) == WITH_RECORD_EXPR
- || TREE_CODE (result) == UNCHECKED_CONVERT_EXPR
- || ((TREE_CODE (result) == NOP_EXPR
- || TREE_CODE (result) == CONVERT_EXPR)
- && (TREE_CODE (TREE_TYPE (result))
- == TREE_CODE (TREE_TYPE (TREE_OPERAND (result, 0))))
- && (TYPE_MODE (TREE_TYPE (TREE_OPERAND (result, 0)))
- == TYPE_MODE (TREE_TYPE (result))));
- result = TREE_OPERAND (result, 0))
- if (TREE_CODE (result) == UNCHECKED_CONVERT_EXPR)
- TREE_ADDRESSABLE (result) = 1;
+ /* Ensure everything on the LHS is valid. If we have a field reference,
+ strip anything that get_inner_reference can handle. Then remove any
+ conversions with type types having the same code and mode. Mark
+ VIEW_CONVERT_EXPRs with TREE_ADDRESSABLE. When done, we must have
+ either an INDIRECT_REF or a decl. */
+ result = left_operand;
+ while (1)
+ {
+ tree restype = TREE_TYPE (result);
+
+ if (TREE_CODE (result) == COMPONENT_REF
+ || TREE_CODE (result) == ARRAY_REF
+ || TREE_CODE (result) == ARRAY_RANGE_REF)
+ while (handled_component_p (result))
+ result = TREE_OPERAND (result, 0);
+ else if (TREE_CODE (result) == REALPART_EXPR
+ || TREE_CODE (result) == IMAGPART_EXPR
+ || TREE_CODE (result) == WITH_RECORD_EXPR
+ || ((TREE_CODE (result) == NOP_EXPR
+ || TREE_CODE (result) == CONVERT_EXPR)
+ && (((TREE_CODE (restype)
+ == TREE_CODE (TREE_TYPE
+ (TREE_OPERAND (result, 0))))
+ && (TYPE_MODE (TREE_TYPE
+ (TREE_OPERAND (result, 0)))
+ == TYPE_MODE (restype)))
+ || TYPE_ALIGN_OK (restype))))
+ result = TREE_OPERAND (result, 0);
+ else if (TREE_CODE (result) == VIEW_CONVERT_EXPR)
+ {
+ TREE_ADDRESSABLE (result) = 1;
+ result = TREE_OPERAND (result, 0);
+ }
+ else
+ break;
+ }
if (TREE_CODE (result) != INDIRECT_REF && TREE_CODE (result) != NULL_EXPR
&& ! DECL_P (result))
@@ -807,17 +820,6 @@ build_binary_op (op_code, result_type, left_operand, right_operand)
|| op_code == ARRAY_RANGE_REF)
mark_addressable (left_operand);
- /* If the array is an UNCHECKED_CONVERT_EXPR from and to BLKmode
- types, convert it to a normal conversion since GCC can deal
- with any mis-alignment as part of the handling of compponent
- references. */
-
- if (TREE_CODE (left_operand) == UNCHECKED_CONVERT_EXPR
- && TYPE_MODE (TREE_TYPE (left_operand)) == BLKmode
- && TYPE_MODE (TREE_TYPE (TREE_OPERAND (left_operand, 0))) == BLKmode)
- left_operand = build1 (CONVERT_EXPR, TREE_TYPE (left_operand),
- TREE_OPERAND (left_operand, 0));
-
modulus = 0;
break;
@@ -865,20 +867,6 @@ build_binary_op (op_code, result_type, left_operand, right_operand)
right_base_type = get_base_type (right_type);
}
- /* If either object if an UNCHECKED_CONVERT_EXPR between two BLKmode
- objects, change it to a CONVERT_EXPR. */
- if (TREE_CODE (left_operand) == UNCHECKED_CONVERT_EXPR
- && TYPE_MODE (left_type) == BLKmode
- && TYPE_MODE (TREE_TYPE (TREE_OPERAND (left_operand, 0))) == BLKmode)
- left_operand = build1 (CONVERT_EXPR, left_type,
- TREE_OPERAND (left_operand, 0));
- if (TREE_CODE (right_operand) == UNCHECKED_CONVERT_EXPR
- && TYPE_MODE (right_type) == BLKmode
- && (TYPE_MODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
- == BLKmode))
- right_operand = build1 (CONVERT_EXPR, right_type,
- TREE_OPERAND (right_operand, 0));
-
/* If both objects are arrays, compare them specially. */
if ((TREE_CODE (left_type) == ARRAY_TYPE
|| (TREE_CODE (left_type) == INTEGER_TYPE
@@ -1058,8 +1046,8 @@ build_binary_op (op_code, result_type, left_operand, right_operand)
TREE_SIDE_EFFECTS (result) |= has_side_effects;
TREE_CONSTANT (result)
- = (TREE_CONSTANT (left_operand) & TREE_CONSTANT (right_operand)
- && op_code != ARRAY_REF && op_code != ARRAY_RANGE_REF);
+ |= (TREE_CONSTANT (left_operand) & TREE_CONSTANT (right_operand)
+ && op_code != ARRAY_REF && op_code != ARRAY_RANGE_REF);
if ((op_code == ARRAY_REF || op_code == ARRAY_RANGE_REF)
&& TYPE_VOLATILE (operation_type))
@@ -1183,6 +1171,11 @@ build_unary_op (op_code, result_type, operand)
if (offset == 0)
offset = size_zero_node;
+ if (bitpos % BITS_PER_UNIT != 0)
+ post_error
+ ("taking address of object not aligned on storage unit?",
+ error_gnat_node);
+
offset = size_binop (PLUS_EXPR, offset,
size_int (bitpos / BITS_PER_UNIT));
@@ -1415,7 +1408,25 @@ build_cond_expr (result_type, condition_operand, true_operand, false_operand)
result = fold (build (COND_EXPR, result_type, condition_operand,
true_operand, false_operand));
- if (addr_p)
+
+ /* If either operand is a SAVE_EXPR (possibly surrounded by
+ arithmetic, make sure it gets done. */
+ while (TREE_CODE_CLASS (TREE_CODE (true_operand)) == '1'
+ || (TREE_CODE_CLASS (TREE_CODE (true_operand)) == '2'
+ && TREE_CONSTANT (TREE_OPERAND (true_operand, 1))))
+ true_operand = TREE_OPERAND (true_operand, 0);
+
+ while (TREE_CODE_CLASS (TREE_CODE (false_operand)) == '1'
+ || (TREE_CODE_CLASS (TREE_CODE (false_operand)) == '2'
+ && TREE_CONSTANT (TREE_OPERAND (false_operand, 1))))
+ false_operand = TREE_OPERAND (false_operand, 0);
+
+ if (TREE_CODE (true_operand) == SAVE_EXPR)
+ result = build (COMPOUND_EXPR, result_type, true_operand, result);
+ if (TREE_CODE (false_operand) == SAVE_EXPR)
+ result = build (COMPOUND_EXPR, result_type, false_operand, result);
+
+ if (addr_p)
result = build_unary_op (INDIRECT_REF, NULL_TREE, result);
return result;
@@ -1475,13 +1486,14 @@ build_call_0_expr (fundecl)
return call;
}
-/* Call a function FCN that raises an exception and pass the line
- number and file name, if requested. */
+/* Call a function that raises an exception and pass the line number and file
+ name, if requested. MSG says which exception function to call. */
tree
-build_call_raise (fndecl)
- tree fndecl;
+build_call_raise (msg)
+ int msg;
{
+ tree fndecl = gnat_raise_decls[msg];
const char *str = discard_file_names ? "" : ref_filename;
int len = strlen (str) + 1;
tree filename = build_string (len, str);
@@ -1641,15 +1653,6 @@ build_simple_component_ref (record_variable, component, field)
if (field == 0)
return 0;
- /* If the record variable is an UNCHECKED_CONVERT_EXPR from and to BLKmode
- types, convert it to a normal conversion since GCC can deal with any
- mis-alignment as part of the handling of compponent references. */
- if (TREE_CODE (record_variable) == UNCHECKED_CONVERT_EXPR
- && TYPE_MODE (TREE_TYPE (record_variable)) == BLKmode
- && TYPE_MODE (TREE_TYPE (TREE_OPERAND (record_variable, 0))) == BLKmode)
- record_variable = build1 (CONVERT_EXPR, TREE_TYPE (record_variable),
- TREE_OPERAND (record_variable, 0));
-
/* It would be nice to call "fold" here, but that can lose a type
we need to tag a PLACEHOLDER_EXPR with, so we can't do it. */
ref = build (COMPONENT_REF, TREE_TYPE (field), record_variable, field);
@@ -1683,7 +1686,7 @@ build_component_ref (record_variable, component, field)
else if (field != 0)
return build1 (NULL_EXPR, TREE_TYPE (field),
- build_call_raise (raise_constraint_error_decl));
+ build_call_raise (CE_Discriminant_Check_Failed));
else
gigi_abort (512);
}
@@ -1861,7 +1864,7 @@ build_allocator (type, init, result_type, gnat_proc, gnat_pool)
storage = build_call_alloc_dealloc (NULL_TREE, size,
TYPE_ALIGN (storage_type),
gnat_proc, gnat_pool);
- storage = convert (storage_ptr_type, make_save_expr (storage));
+ storage = convert (storage_ptr_type, protect_multiple_eval (storage));
if (TREE_CODE (type) == RECORD_TYPE && TYPE_IS_PADDING_P (type))
{