Commit 0ec479dc by Eric Botcazou Committed by Eric Botcazou

trans.c (lvalue_required_p): Take base node directly instead of its parent.

	* trans.c (lvalue_required_p): Take base node directly instead
	of its parent.  Rename second parameter to 'gnu_type'.
	<N_Indexed_Component>: Return 0 if the node isn't the prefix.
	<N_Slice>: Likewise.
	(Identifier_to_gnu): Rename parent_requires_lvalue to require_lvalue.
	Adjust calls to lvalue_required_p.

From-SVN: r130626
parent e37ab973
2007-12-05 Eric Botcazou <ebotcazou@adacore.com>
* trans.c (lvalue_required_p): Take base node directly instead
of its parent. Rename second parameter to 'gnu_type'.
<N_Indexed_Component>: Return 0 if the node isn't the prefix.
<N_Slice>: Likewise.
(Identifier_to_gnu): Rename parent_requires_lvalue to require_lvalue.
Adjust calls to lvalue_required_p.
2007-12-05 Samuel Tardieu <sam@rfc1149.net> 2007-12-05 Samuel Tardieu <sam@rfc1149.net>
PR ada/21489 PR ada/21489
...@@ -379,22 +379,29 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name, ...@@ -379,22 +379,29 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name,
error_gnat_node = Empty; error_gnat_node = Empty;
} }
/* Returns a positive value if GNAT_NODE requires an lvalue for an /* Return a positive value if an lvalue is required for GNAT_NODE.
operand of OPERAND_TYPE, whose aliasing is specified by ALIASED, GNU_TYPE is the type that will be used for GNAT_NODE in the
zero otherwise. This is int instead of bool to facilitate usage translated GNU tree. ALIASED indicates whether the underlying
in non purely binary logic contexts. */ object represented by GNAT_NODE is aliased in the Ada sense.
The function climbs up the GNAT tree starting from the node and
returns 1 upon encountering a node that effectively requires an
lvalue downstream. It returns int instead of bool to facilitate
usage in non purely binary logic contexts. */
static int static int
lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased) lvalue_required_p (Node_Id gnat_node, tree gnu_type, int aliased)
{ {
switch (Nkind (gnat_node)) Node_Id gnat_parent = Parent (gnat_node), gnat_temp;
switch (Nkind (gnat_parent))
{ {
case N_Reference: case N_Reference:
return 1; return 1;
case N_Attribute_Reference: case N_Attribute_Reference:
{ {
unsigned char id = Get_Attribute_Id (Attribute_Name (gnat_node)); unsigned char id = Get_Attribute_Id (Attribute_Name (gnat_parent));
return id == Attr_Address return id == Attr_Address
|| id == Attr_Access || id == Attr_Access
|| id == Attr_Unchecked_Access || id == Attr_Unchecked_Access
...@@ -404,32 +411,36 @@ lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased) ...@@ -404,32 +411,36 @@ lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased)
case N_Parameter_Association: case N_Parameter_Association:
case N_Function_Call: case N_Function_Call:
case N_Procedure_Call_Statement: case N_Procedure_Call_Statement:
return must_pass_by_ref (operand_type) return (must_pass_by_ref (gnu_type) || default_pass_by_ref (gnu_type));
|| default_pass_by_ref (operand_type);
case N_Indexed_Component: case N_Indexed_Component:
{ /* Only the array expression can require an lvalue. */
Node_Id gnat_temp; if (Prefix (gnat_parent) != gnat_node)
/* ??? Consider that referencing an indexed component with a return 0;
non-constant index forces the whole aggregate to memory.
Note that N_Integer_Literal is conservative, any static /* ??? Consider that referencing an indexed component with a
expression in the RM sense could probably be accepted. */ non-constant index forces the whole aggregate to memory.
for (gnat_temp = First (Expressions (gnat_node)); Note that N_Integer_Literal is conservative, any static
Present (gnat_temp); expression in the RM sense could probably be accepted. */
gnat_temp = Next (gnat_temp)) for (gnat_temp = First (Expressions (gnat_parent));
if (Nkind (gnat_temp) != N_Integer_Literal) Present (gnat_temp);
return 1; gnat_temp = Next (gnat_temp))
} if (Nkind (gnat_temp) != N_Integer_Literal)
return 1;
/* ... fall through ... */ /* ... fall through ... */
case N_Slice: case N_Slice:
aliased |= Has_Aliased_Components (Etype (Prefix (gnat_node))); /* Only the array expression can require an lvalue. */
return lvalue_required_p (Parent (gnat_node), operand_type, aliased); if (Prefix (gnat_parent) != gnat_node)
return 0;
aliased |= Has_Aliased_Components (Etype (gnat_node));
return lvalue_required_p (gnat_parent, gnu_type, aliased);
case N_Selected_Component: case N_Selected_Component:
aliased |= Is_Aliased (Entity (Selector_Name (gnat_node))); aliased |= Is_Aliased (Entity (Selector_Name (gnat_parent)));
return lvalue_required_p (Parent (gnat_node), operand_type, aliased); return lvalue_required_p (gnat_parent, gnu_type, aliased);
case N_Object_Renaming_Declaration: case N_Object_Renaming_Declaration:
/* We need to make a real renaming only if the constant object is /* We need to make a real renaming only if the constant object is
...@@ -439,8 +450,8 @@ lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased) ...@@ -439,8 +450,8 @@ lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased)
attached to the CONST_DECL. */ attached to the CONST_DECL. */
return (aliased != 0 return (aliased != 0
/* This should match the constant case of the renaming code. */ /* This should match the constant case of the renaming code. */
|| Is_Composite_Type (Etype (Name (gnat_node))) || Is_Composite_Type (Etype (Name (gnat_parent)))
|| Nkind (Name (gnat_node)) == N_Identifier); || Nkind (Name (gnat_parent)) == N_Identifier);
default: default:
return 0; return 0;
...@@ -450,20 +461,19 @@ lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased) ...@@ -450,20 +461,19 @@ lvalue_required_p (Node_Id gnat_node, tree operand_type, int aliased)
} }
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Identifier, /* Subroutine of gnat_to_gnu to translate gnat_node, an N_Identifier,
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer to to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer
where we should place the result type. */ to where we should place the result type. */
static tree static tree
Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
{ {
tree gnu_result_type;
tree gnu_result;
Node_Id gnat_temp, gnat_temp_type; Node_Id gnat_temp, gnat_temp_type;
tree gnu_result, gnu_result_type;
/* Whether the parent of gnat_node requires an lvalue. Needed in /* Whether we should require an lvalue for GNAT_NODE. Needed in
specific circumstances only, so evaluated lazily. < 0 means unknown, specific circumstances only, so evaluated lazily. < 0 means
> 0 means known true, 0 means known false. */ unknown, > 0 means known true, 0 means known false. */
int parent_requires_lvalue = -1; int require_lvalue = -1;
/* If GNAT_NODE is a constant, whether we should use the initialization /* If GNAT_NODE is a constant, whether we should use the initialization
value instead of the constant entity, typically for scalars with an value instead of the constant entity, typically for scalars with an
...@@ -539,9 +549,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) ...@@ -539,9 +549,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
gnu_result_type = get_unpadded_type (gnat_temp_type); gnu_result_type = get_unpadded_type (gnat_temp_type);
/* If this is a non-imported scalar constant with an address clause, /* If this is a non-imported scalar constant with an address clause,
retrieve the value instead of a pointer to be dereferenced unless the retrieve the value instead of a pointer to be dereferenced unless
parent requires an lvalue. This is generally more efficient and an lvalue is required. This is generally more efficient and actually
actually required if this is a static expression because it might be used required if this is a static expression because it might be used
in a context where a dereference is inappropriate, such as a case in a context where a dereference is inappropriate, such as a case
statement alternative or a record discriminant. There is no possible statement alternative or a record discriminant. There is no possible
volatile-ness shortciruit here since Volatile constants must be imported volatile-ness shortciruit here since Volatile constants must be imported
...@@ -550,10 +560,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) ...@@ -550,10 +560,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
&& !Is_Imported (gnat_temp) && !Is_Imported (gnat_temp)
&& Present (Address_Clause (gnat_temp))) && Present (Address_Clause (gnat_temp)))
{ {
parent_requires_lvalue require_lvalue = lvalue_required_p (gnat_node, gnu_result_type,
= lvalue_required_p (Parent (gnat_node), gnu_result_type, Is_Aliased (gnat_temp));
Is_Aliased (gnat_temp)); use_constant_initializer = !require_lvalue;
use_constant_initializer = !parent_requires_lvalue;
} }
if (use_constant_initializer) if (use_constant_initializer)
...@@ -646,21 +655,21 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) ...@@ -646,21 +655,21 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
of places and the need of elaboration code if this Id is used as of places and the need of elaboration code if this Id is used as
an initializer itself. */ an initializer itself. */
if (TREE_CONSTANT (gnu_result) if (TREE_CONSTANT (gnu_result)
&& DECL_P (gnu_result) && DECL_INITIAL (gnu_result)) && DECL_P (gnu_result)
&& DECL_INITIAL (gnu_result))
{ {
tree object tree object
= (TREE_CODE (gnu_result) == CONST_DECL = (TREE_CODE (gnu_result) == CONST_DECL
? DECL_CONST_CORRESPONDING_VAR (gnu_result) : gnu_result); ? DECL_CONST_CORRESPONDING_VAR (gnu_result) : gnu_result);
/* If there is a corresponding variable, we only want to return the CST /* If there is a corresponding variable, we only want to return
value if the parent doesn't require an lvalue. Evaluate this now if the CST value if an lvalue is not required. Evaluate this
we have not already done so. */ now if we have not already done so. */
if (object && parent_requires_lvalue < 0) if (object && require_lvalue < 0)
parent_requires_lvalue require_lvalue = lvalue_required_p (gnat_node, gnu_result_type,
= lvalue_required_p (Parent (gnat_node), gnu_result_type, Is_Aliased (gnat_temp));
Is_Aliased (gnat_temp));
if (!object || !parent_requires_lvalue) if (!object || !require_lvalue)
gnu_result = unshare_expr (DECL_INITIAL (gnu_result)); gnu_result = unshare_expr (DECL_INITIAL (gnu_result));
} }
......
2007-12-05 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/elab1.ads: New test.
2007-12-05 Uros Bizjak <ubizjak@gmail.com> 2007-12-05 Uros Bizjak <ubizjak@gmail.com>
PR target/34312 PR target/34312
-- { dg-do compile }
pragma Restrictions(No_Elaboration_Code);
with System;
package Elab1 is
type Ptrs_Type is array (Integer range 1 .. 2) of System.Address;
type Vars_Array is array (Integer range 1 .. 2) of Integer;
Vars : Vars_Array;
Val1 : constant Integer := 1;
Val2 : constant Integer := 2;
Ptrs : constant Ptrs_Type :=
(1 => Vars (Val1)'Address,
2 => Vars (Val2)'Address);
end Elab1;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment