https://gcc.gnu.org/g:7b1ad03b84fdd727b695da59703debd676c93f2e

commit r15-2614-g7b1ad03b84fdd727b695da59703debd676c93f2e
Author: Eric Botcazou <ebotca...@adacore.com>
Date:   Wed Jun 26 19:55:44 2024 +0200

    ada: Fix internal error on limited aggregate in nested conditional 
expression
    
    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.

Diff:
---
 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 c7730ca754ab..2031d042fa50 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 f952005ed755..50c3cd430cef 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

Reply via email to