aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/trans.c')
-rw-r--r--gcc/ada/trans.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index f3dc87d..82aaa99 100644
--- a/gcc/ada/trans.c
+++ b/gcc/ada/trans.c
@@ -4832,34 +4832,41 @@ gnat_to_gnu (Node_Id gnat_node)
|| CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))))
gnu_result = gnat_stabilize_reference (gnu_result, false);
- /* Now convert the result to the proper type. If the type is void or if
- we have no result, return error_mark_node to show we have no result.
- If the type of the result is correct or if we have a label (which doesn't
- have any well-defined type), return our result. Also don't do the
- conversion if the "desired" type involves a PLACEHOLDER_EXPR in its size
- since those are the cases where the front end may have the type wrong due
- to "instantiating" the unconstrained record with discriminant values
- or if this is a FIELD_DECL. If this is the Name of an assignment
- statement or a parameter of a procedure call, return what we have since
- the RHS has to be converted to our type there in that case, unless
- GNU_RESULT_TYPE has a simpler size. Similarly, if the two types are
- record types with the same name and GNU_RESULT_TYPE has BLKmode, don't
- convert. This will be the case when we are converting from a packable
- type to its actual type and we need those conversions to be NOPs in
- order for assignments into these types to work properly. Finally,
- don't convert integral types that are the operand of an unchecked
- conversion since we need to ignore those conversions (for 'Valid).
- Otherwise, convert the result to the proper type. */
+ /* Now convert the result to the result type, unless we are in one of the
+ following cases:
+
+ 1. If this is the Name of an assignment statement or a parameter of
+ a procedure call, return the result almost unmodified since the
+ RHS will have to be converted to our type in that case, unless
+ the result type has a simpler size. Similarly, don't convert
+ integral types that are the operands of an unchecked conversion
+ since we need to ignore those conversions (for 'Valid).
+
+ 2. If we have a label (which doesn't have any well-defined type), a
+ field or an error, return the result almost unmodified. Also don't
+ do the conversion if the result type involves a PLACEHOLDER_EXPR in
+ its size since those are the cases where the front end may have the
+ type wrong due to "instantiating" the unconstrained record with
+ discriminant values. Similarly, if the two types are record types
+ with the same name and the result type has BLKmode, don't convert.
+ This will be the case when we are converting from a packed version
+ of a type to its original type and we need those conversions to be
+ NOPs in order for assignments into these types to work properly.
+
+ 3. If the type is void or if we have no result, return error_mark_node
+ to show we have no result.
+
+ 4. Finally, if the type of the result is already correct. */
if (Present (Parent (gnat_node))
&& ((Nkind (Parent (gnat_node)) == N_Assignment_Statement
&& Name (Parent (gnat_node)) == gnat_node)
|| (Nkind (Parent (gnat_node)) == N_Procedure_Call_Statement
&& Name (Parent (gnat_node)) != gnat_node)
+ || Nkind (Parent (gnat_node)) == N_Parameter_Association
|| (Nkind (Parent (gnat_node)) == N_Unchecked_Type_Conversion
&& !AGGREGATE_TYPE_P (gnu_result_type)
- && !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result)))
- || Nkind (Parent (gnat_node)) == N_Parameter_Association)
+ && !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result))))
&& !(TYPE_SIZE (gnu_result_type)
&& TYPE_SIZE (TREE_TYPE (gnu_result))
&& (AGGREGATE_TYPE_P (gnu_result_type)
@@ -4874,16 +4881,14 @@ gnat_to_gnu (Node_Id gnat_node)
&& !(TREE_CODE (gnu_result_type) == RECORD_TYPE
&& TYPE_JUSTIFIED_MODULAR_P (gnu_result_type))))
{
- /* In this case remove padding only if the inner object type is the
- same as gnu_result_type or is of self-referential size (in that later
- case it must be an object of unconstrained type with a default
- discriminant). We want to avoid copying too much data. */
+ /* Remove padding only if the inner object is of self-referential
+ size: in that case it must be an object of unconstrained type
+ with a default discriminant and we want to avoid copying too
+ much data. */
if (TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
&& TYPE_IS_PADDING_P (TREE_TYPE (gnu_result))
- && (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result)))
- == gnu_result_type
- || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS
- (TREE_TYPE (gnu_result)))))))
+ && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS
+ (TREE_TYPE (gnu_result))))))
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
gnu_result);
}
@@ -4901,20 +4906,20 @@ gnat_to_gnu (Node_Id gnat_node)
&& TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
&& TYPE_MODE (gnu_result_type) == BLKmode))
{
- /* Remove any padding record, but do nothing more in this case. */
+ /* Remove any padding. */
if (TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
&& TYPE_IS_PADDING_P (TREE_TYPE (gnu_result)))
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
gnu_result);
}
- else if (gnu_result == error_mark_node
- || gnu_result_type == void_type_node)
- gnu_result = error_mark_node;
+ else if (gnu_result == error_mark_node || gnu_result_type == void_type_node)
+ gnu_result = error_mark_node;
+
else if (gnu_result_type != TREE_TYPE (gnu_result))
gnu_result = convert (gnu_result_type, gnu_result);
- /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RESULT. */
+ /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on the result. */
while ((TREE_CODE (gnu_result) == NOP_EXPR
|| TREE_CODE (gnu_result) == NON_LVALUE_EXPR)
&& TREE_TYPE (TREE_OPERAND (gnu_result, 0)) == TREE_TYPE (gnu_result))