From: Eric Botcazou <ebotcazou@adacore.com>
This is a fallout of an earlier fix to Is_Build_In_Place_Aggregate_Return
that made it take into account intermediate conditional expressions, but
turned out to work only for a single nesting level of them.
The fix reuses the delayed expansion mechanism recently extended to deal
with conditional expressions in a straightforward way.
gcc/ada/
* exp_aggr.adb (Convert_To_Assignments): Set Expansion_Delayed on
intermediate conditional expressions for BIP aggregate returns
too.
* exp_ch4.adb (Expand_N_Case_Expression): Also deal with delayed
expansion in the return case.
(Expand_N_If_Expression): Likewise.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/exp_aggr.adb | 28 ++++++++---------
gcc/ada/exp_ch4.adb | 73 ++++++++++++++++++++++++++++++++------------
2 files changed, 66 insertions(+), 35 deletions(-)
@@ -4265,6 +4265,19 @@ package body Exp_Aggr is
or else (Nkind (Parent_Node) = N_Assignment_Statement
and then Inside_Init_Proc)
+
+ -- (Ada 2005) An inherently limited type in a return statement, which
+ -- will be handled in a build-in-place fashion, and may be rewritten
+ -- as an extended return and have its own finalization machinery.
+ -- In the case of a simple return, the aggregate needs to be delayed
+ -- until the scope for the return statement has been created, so
+ -- that any finalization chain will be associated with that scope.
+ -- For extended returns, we delay expansion to avoid the creation
+ -- of an unwanted transient scope that could result in premature
+ -- finalization of the return object (which is built in place
+ -- within the caller's scope).
+
+ or else Is_Build_In_Place_Aggregate_Return (N)
then
Node := N;
@@ -4286,21 +4299,6 @@ package body Exp_Aggr is
end loop;
return;
-
- -- (Ada 2005) An inherently limited type in a return statement, which
- -- will be handled in a build-in-place fashion, and may be rewritten
- -- as an extended return and have its own finalization machinery.
- -- In the case of a simple return, the aggregate needs to be delayed
- -- until the scope for the return statement has been created, so
- -- that any finalization chain will be associated with that scope.
- -- For extended returns, we delay expansion to avoid the creation
- -- of an unwanted transient scope that could result in premature
- -- finalization of the return object (which is built in place
- -- within the caller's scope).
-
- elsif Is_Build_In_Place_Aggregate_Return (N) then
- Set_Expansion_Delayed (N);
- return;
end if;
-- Otherwise, if a transient scope is required, create it now
@@ -5010,7 +5010,7 @@ package body Exp_Ch4 is
Target : Entity_Id := Empty;
Target_Typ : Entity_Id;
- Optimize_Assignment_Stmt : Boolean;
+ Optimize_Assignment_Stmt : Boolean := False;
-- Small optimization: when the case expression appears in the context
-- of a safe assignment statement, expand into
@@ -5029,18 +5029,22 @@ package body Exp_Ch4 is
begin
-- If the expansion of the expression has been delayed, we wait for the
- -- rewriting of its parent as an assignment statement; when that's done,
- -- we optimize the assignment (the very purpose of the manipulation).
+ -- rewriting of its parent as an assignment or return statement; when
+ -- that's done, we optimize the assignment or the return statement (the
+ -- very purpose of the manipulation).
if Expansion_Delayed (N) then
- if Nkind (Par) /= N_Assignment_Statement then
+ if Nkind (Par) = N_Assignment_Statement then
+ Optimize_Assignment_Stmt := True;
+
+ elsif Optimize_Return_Stmt then
+ null;
+
+ else
return;
end if;
- Optimize_Assignment_Stmt := True;
-
- else
- Optimize_Assignment_Stmt := False;
+ Set_Expansion_Delayed (N, False);
end if;
-- Check for MINIMIZED/ELIMINATED overflow mode
@@ -5192,6 +5196,13 @@ package body Exp_Ch4 is
Make_Simple_Return_Statement (Alt_Loc,
Expression => Alt_Expr));
+ -- If the expression is itself a conditional expression whose
+ -- expansion has been delayed, analyze it again and expand it.
+
+ if Is_Delayed_Conditional_Expression (Alt_Expr) then
+ Set_Analyzed (Alt_Expr, False);
+ end if;
+
-- Take the unrestricted access of the expression value for non-
-- scalar types. This approach avoids big copies and covers the
-- limited and unconstrained cases.
@@ -5493,7 +5504,7 @@ package body Exp_Ch4 is
New_N : Node_Id;
New_Then : Node_Id;
- Optimize_Assignment_Stmt : Boolean;
+ Optimize_Assignment_Stmt : Boolean := False;
-- Small optimization: when the if expression appears in the context of
-- a safe assignment statement, expand into
@@ -5510,18 +5521,22 @@ package body Exp_Ch4 is
begin
-- If the expansion of the expression has been delayed, we wait for the
- -- rewriting of its parent as an assignment statement; when that's done,
- -- we optimize the assignment (the very purpose of the manipulation).
+ -- rewriting of its parent as an assignment or return statement; when
+ -- that's done, we optimize the assignment or the return statement (the
+ -- very purpose of the manipulation).
if Expansion_Delayed (N) then
- if Nkind (Par) /= N_Assignment_Statement then
+ if Nkind (Par) = N_Assignment_Statement then
+ Optimize_Assignment_Stmt := True;
+
+ elsif Optimize_Return_Stmt then
+ null;
+
+ else
return;
end if;
- Optimize_Assignment_Stmt := True;
-
- else
- Optimize_Assignment_Stmt := False;
+ Set_Expansion_Delayed (N, False);
end if;
-- Deal with non-standard booleans
@@ -5652,15 +5667,33 @@ package body Exp_Ch4 is
Process_Transients_In_Expression (N, Then_Actions (N));
Process_Transients_In_Expression (N, Else_Actions (N));
+ New_Then := Relocate_Node (Thenx);
+
+ -- If the expression is itself a conditional expression whose
+ -- expansion has been delayed, analyze it again and expand it.
+
+ if Is_Delayed_Conditional_Expression (New_Then) then
+ Set_Analyzed (New_Then, False);
+ end if;
+
+ New_Else := Relocate_Node (Elsex);
+
+ -- If the expression is itself a conditional expression whose
+ -- expansion has been delayed, analyze it again and expand it.
+
+ if Is_Delayed_Conditional_Expression (New_Else) then
+ Set_Analyzed (New_Else, False);
+ end if;
+
New_If :=
Make_Implicit_If_Statement (N,
Condition => Relocate_Node (Cond),
Then_Statements => New_List (
- Make_Simple_Return_Statement (Sloc (Thenx),
- Expression => Relocate_Node (Thenx))),
+ Make_Simple_Return_Statement (Sloc (New_Then),
+ Expression => New_Then)),
Else_Statements => New_List (
- Make_Simple_Return_Statement (Sloc (Elsex),
- Expression => Relocate_Node (Elsex))));
+ Make_Simple_Return_Statement (Sloc (New_Else),
+ Expression => New_Else)));
-- Preserve the original context for which the if statement is
-- being generated. This is needed by the finalization machinery