From: Eric Botcazou <ebotca...@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(-) diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index c7730ca754a..2031d042fa5 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -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 diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index f952005ed75..50c3cd430ce 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -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 -- 2.45.2