[COMMITTED] ada: Fix fallout of recent fix for missing finalization

Message ID 20230530072057.2500051-1-poulhies@adacore.com
State Committed
Commit 9dbf6adb3e0f849d0622a59b6c722f0d868e6c25
Headers
Series [COMMITTED] ada: Fix fallout of recent fix for missing finalization |

Commit Message

Marc Poulhiès May 30, 2023, 7:20 a.m. UTC
  From: Eric Botcazou <ebotcazou@adacore.com>

The original fix makes it possible to create transient scopes around return
statements in more cases, but it overlooks that transient scopes are reused
and, in particular, that they can be promoted to secondary stack management.

gcc/ada/

	* exp_ch7.adb (Find_Enclosing_Transient_Scope): Return the index in
	the scope table instead of the scope's entity.
	(Establish_Transient_Scope): If an enclosing scope already exists,
	do not set the Uses_Sec_Stack flag on it if the node to be wrapped
	is a return statement which requires secondary stack management.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_ch7.adb | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)
  

Patch

diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 520bb099d33..42b41e5cf6b 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -4476,10 +4476,10 @@  package body Exp_Ch7 is
       function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean;
       --  Determine whether arbitrary Id denotes a package or subprogram [body]
 
-      function Find_Enclosing_Transient_Scope return Entity_Id;
+      function Find_Enclosing_Transient_Scope return Int;
       --  Examine the scope stack looking for the nearest enclosing transient
       --  scope within the innermost enclosing package or subprogram. Return
-      --  Empty if no such scope exists.
+      --  its index in the table or else -1 if no such scope exists.
 
       function Find_Transient_Context (N : Node_Id) return Node_Id;
       --  Locate a suitable context for arbitrary node N which may need to be
@@ -4605,7 +4605,7 @@  package body Exp_Ch7 is
       -- Find_Enclosing_Transient_Scope --
       ------------------------------------
 
-      function Find_Enclosing_Transient_Scope return Entity_Id is
+      function Find_Enclosing_Transient_Scope return Int is
       begin
          for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop
             declare
@@ -4620,12 +4620,12 @@  package body Exp_Ch7 is
                   exit;
 
                elsif Scope.Is_Transient then
-                  return Scope.Entity;
+                  return Index;
                end if;
             end;
          end loop;
 
-         return Empty;
+         return -1;
       end Find_Enclosing_Transient_Scope;
 
       ----------------------------
@@ -4822,8 +4822,8 @@  package body Exp_Ch7 is
 
       --  Local variables
 
-      Trans_Id : constant Entity_Id := Find_Enclosing_Transient_Scope;
-      Context  : Node_Id;
+      Trans_Idx : constant Int := Find_Enclosing_Transient_Scope;
+      Context   : Node_Id;
 
    --  Start of processing for Establish_Transient_Scope
 
@@ -4831,13 +4831,29 @@  package body Exp_Ch7 is
       --  Do not create a new transient scope if there is already an enclosing
       --  transient scope within the innermost enclosing package or subprogram.
 
-      if Present (Trans_Id) then
+      if Trans_Idx >= 0 then
 
          --  If the transient scope was requested for purposes of managing the
-         --  secondary stack, then the existing scope must perform this task.
+         --  secondary stack, then the existing scope must perform this task,
+         --  unless the node to be wrapped is a return statement of a function
+         --  that requires secondary stack management, because the function's
+         --  result would be reclaimed too early (see Find_Transient_Context).
 
          if Manage_Sec_Stack then
-            Set_Uses_Sec_Stack (Trans_Id);
+            declare
+               SE : Scope_Stack_Entry renames Scope_Stack.Table (Trans_Idx);
+
+            begin
+               if Nkind (SE.Node_To_Be_Wrapped) /= N_Simple_Return_Statement
+                 or else not
+                   Needs_Secondary_Stack
+                     (Etype
+                       (Return_Applies_To
+                         (Return_Statement_Entity (SE.Node_To_Be_Wrapped))))
+               then
+                  Set_Uses_Sec_Stack (SE.Entity);
+               end if;
+            end;
          end if;
 
          return;