@@ -241,11 +241,6 @@ package body Exp_Ch4 is
-- and X is a simple entity, and op is a comparison operator, optimizes it
-- into a comparison of X'First and X'Last.
- procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id);
- -- Inspect and process statement list Stmt of if or case expression N for
- -- transient objects. If such objects are found, the routine generates code
- -- to clean them up when the context of the expression is evaluated.
-
procedure Process_Transient_In_Expression
(Obj_Decl : Node_Id;
Expr : Node_Id;
@@ -255,9 +250,25 @@ package body Exp_Ch4 is
-- object when the enclosing context is elaborated or evaluated. Obj_Decl
-- denotes the declaration of the transient object, which is usually the
-- result of a controlled function call. Expr denotes the expression with
- -- actions, if expression, or case expression node. Stmts denotes the
- -- statement list which contains Decl, either at the top level or within a
- -- nested construct.
+ -- actions, if expression, or case expression node. Stmts denotes one of
+ -- the actions list of Expr, which contains Decl.
+
+ procedure Process_Transients_In_Expression
+ (Expr : Node_Id;
+ Stmts : List_Id);
+ -- Subsidiary routine to the expansion of expression_with_actions, if and
+ -- case expressions. Inspect and process actions list Stmts of expression
+ -- Expr for transient objects. If such objects are found, the routine will
+ -- generate code to finalize them when the enclosing context is elaborated
+ -- or evaluated.
+
+ -- This specific processing is required for these expressions because the
+ -- management of transient objects for expressions implemented in Exp_Ch7
+ -- cannot deal with nested lists of actions whose effects may outlive the
+ -- lists and affect the result of the parent expressions. In these cases,
+ -- the lifetime of temporaries created in these lists must be extended to
+ -- match that of the enclosing context of the parent expressions and, in
+ -- particular, their finalization must be deferred to this context.
procedure Rewrite_Comparison (N : Node_Id);
-- If N is the node for a comparison whose outcome can be determined at
@@ -5411,14 +5422,10 @@ package body Exp_Ch4 is
Statements => Stmts));
-- Finalize any transient objects on exit from the alternative.
- -- This needs to be done only when the case expression is _not_
- -- later converted into an expression with actions, which already
- -- contains this form of processing, and after Stmts is attached
+ -- Note that this needs to be done only after Stmts is attached
-- to the Alternatives list above (for Safe_To_Capture_Value).
- if Optimize_Return_Stmt or else not Is_Copy_Type (Typ) then
- Process_If_Case_Statements (N, Stmts);
- end if;
+ Process_Transients_In_Expression (N, Stmts);
end;
Next (Alt);
@@ -5482,12 +5489,6 @@ package body Exp_Ch4 is
procedure Force_Boolean_Evaluation (Expr : Node_Id);
-- Force the evaluation of Boolean expression Expr
- function Process_Action (Act : Node_Id) return Traverse_Result;
- -- Inspect and process a single action of an expression_with_actions for
- -- transient objects. If such objects are found, the routine generates
- -- code to clean them up when the context of the expression is evaluated
- -- or elaborated.
-
------------------------------
-- Force_Boolean_Evaluation --
------------------------------
@@ -5520,42 +5521,6 @@ package body Exp_Ch4 is
Analyze (Expression (N));
end Force_Boolean_Evaluation;
- --------------------
- -- Process_Action --
- --------------------
-
- function Process_Action (Act : Node_Id) return Traverse_Result is
- begin
- if Nkind (Act) = N_Object_Declaration
- and then Is_Finalizable_Transient (Act, N)
- then
- Process_Transient_In_Expression (Act, N, Acts);
- return Skip;
-
- -- Avoid processing temporary function results multiple times when
- -- dealing with nested expression_with_actions or nested blocks.
- -- Similarly, do not process temporary function results in loops.
- -- This is done by Expand_N_Loop_Statement and Build_Finalizer.
- -- Note that we used to wrongly return Abandon instead of Skip here:
- -- this is wrong since it means that we were ignoring lots of
- -- relevant subsequent statements.
-
- elsif Nkind (Act) in N_Expression_With_Actions
- | N_Block_Statement
- | N_Loop_Statement
- then
- return Skip;
- end if;
-
- return OK;
- end Process_Action;
-
- procedure Process_Single_Action is new Traverse_Proc (Process_Action);
-
- -- Local variables
-
- Act : Node_Id;
-
-- Start of processing for Expand_N_Expression_With_Actions
begin
@@ -5616,14 +5581,9 @@ package body Exp_Ch4 is
Force_Evaluation (Expression (N));
end if;
- -- Process all transient objects found within the actions of the EWA
- -- node.
+ -- Process transient objects found within the actions of the EWA node
- Act := First (Acts);
- while Present (Act) loop
- Process_Single_Action (Act);
- Next (Act);
- end loop;
+ Process_Transients_In_Expression (N, Acts);
-- Deal with case where there are no actions. In this case we simply
-- rewrite the node with its expression since we don't need the actions
@@ -5802,8 +5762,8 @@ package body Exp_Ch4 is
-- of actions. These temporaries need to be finalized after the if
-- expression is evaluated.
- Process_If_Case_Statements (N, Then_Actions (N));
- Process_If_Case_Statements (N, Else_Actions (N));
+ Process_Transients_In_Expression (N, Then_Actions (N));
+ Process_Transients_In_Expression (N, Else_Actions (N));
New_If :=
Make_Implicit_If_Statement (N,
@@ -5843,8 +5803,8 @@ package body Exp_Ch4 is
-- of actions. These temporaries need to be finalized after the if
-- expression is evaluated.
- Process_If_Case_Statements (N, Then_Actions (N));
- Process_If_Case_Statements (N, Else_Actions (N));
+ Process_Transients_In_Expression (N, Then_Actions (N));
+ Process_Transients_In_Expression (N, Else_Actions (N));
declare
Cnn : constant Entity_Id := Make_Temporary (Loc, 'C', N);
@@ -6186,13 +6146,20 @@ package body Exp_Ch4 is
or else Present (Else_Actions (N))
or else Force_Expand
then
-
-- We now wrap the actions into the appropriate expression
if Minimize_Expression_With_Actions
and then (Is_Elementary_Type (Underlying_Type (Typ))
or else Is_Constrained (Underlying_Type (Typ)))
then
+ -- When the "then" or "else" expressions involve controlled
+ -- function calls, generated temporaries are chained on the
+ -- corresponding list of actions. These temporaries need to
+ -- be finalized after the if expression is evaluated.
+
+ Process_Transients_In_Expression (N, Then_Actions (N));
+ Process_Transients_In_Expression (N, Else_Actions (N));
+
-- If we can't use N_Expression_With_Actions nodes, then we insert
-- the following sequence of actions (using Insert_Actions):
@@ -6239,6 +6206,10 @@ package body Exp_Ch4 is
-- Regular path using Expression_With_Actions
else
+ -- We do not need to call Process_Transients_In_Expression on
+ -- the list of actions in this case, because the expansion of
+ -- Expression_With_Actions will do it.
+
if Present (Then_Actions (N)) then
Rewrite (Thenx,
Make_Expression_With_Actions (Sloc (Thenx),
@@ -14938,26 +14909,6 @@ package body Exp_Ch4 is
Analyze_And_Resolve (N, Typ, Suppress => Overflow_Check);
end Optimize_Length_Comparison;
- --------------------------------
- -- Process_If_Case_Statements --
- --------------------------------
-
- procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id) is
- Decl : Node_Id;
-
- begin
- Decl := First (Stmts);
- while Present (Decl) loop
- if Nkind (Decl) = N_Object_Declaration
- and then Is_Finalizable_Transient (Decl, N)
- then
- Process_Transient_In_Expression (Decl, N, Stmts);
- end if;
-
- Next (Decl);
- end loop;
- end Process_If_Case_Statements;
-
-------------------------------------
-- Process_Transient_In_Expression --
-------------------------------------
@@ -15116,6 +15067,33 @@ package body Exp_Ch4 is
end if;
end Process_Transient_In_Expression;
+ --------------------------------------
+ -- Process_Transients_In_Expression --
+ --------------------------------------
+
+ procedure Process_Transients_In_Expression
+ (Expr : Node_Id;
+ Stmts : List_Id)
+ is
+ Decl : Node_Id;
+
+ begin
+ pragma Assert (Nkind (Expr) in N_Case_Expression
+ | N_Expression_With_Actions
+ | N_If_Expression);
+
+ Decl := First (Stmts);
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Object_Declaration
+ and then Is_Finalizable_Transient (Decl, Expr)
+ then
+ Process_Transient_In_Expression (Decl, Expr, Stmts);
+ end if;
+
+ Next (Decl);
+ end loop;
+ end Process_Transients_In_Expression;
+
------------------------
-- Rewrite_Comparison --
------------------------