[COMMITTED] ada: Fix memory leak in expression function returning Big_Integer

Message ID 20230529082956.2411313-1-poulhies@adacore.com
State Committed
Headers
Series [COMMITTED] ada: Fix memory leak in expression function returning Big_Integer |

Commit Message

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

We fail to establish a transient scope around the return statement because
the function returns a controlled type, but this is no longer problematic
because controlled types are no longer returned on the secondary stack.

gcc/ada/

	* exp_ch7.adb (Establish_Transient_Scope.Find_Transient_Context):
	Bail out for a simple return statement only if the transient scope
	and the function both require secondary stack management, or else
	if the function is a thunk.
	* sem_res.adb (Resolve_Call): Do not create a transient scope when
	the call is the expression of a simple return statement.

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

---
 gcc/ada/exp_ch7.adb | 32 ++++++++++++++++++++------------
 gcc/ada/sem_res.adb | 12 ++++++++----
 2 files changed, 28 insertions(+), 16 deletions(-)
  

Patch

diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 1586e8fbfca..520bb099d33 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -4717,21 +4717,29 @@  package body Exp_Ch7 is
                   return Curr;
 
                when N_Simple_Return_Statement =>
+                  declare
+                     Fun_Id : constant Entity_Id :=
+                       Return_Applies_To (Return_Statement_Entity (Curr));
 
-                  --  A return statement is not a valid transient context when
-                  --  the function itself requires transient scope management
-                  --  because the result will be reclaimed too early.
-
-                  if Requires_Transient_Scope (Etype
-                       (Return_Applies_To (Return_Statement_Entity (Curr))))
-                  then
-                     return Empty;
+                  begin
+                     --  A transient context that must manage the secondary
+                     --  stack cannot be a return statement of a function that
+                     --  itself requires secondary stack management, because
+                     --  the function's result would be reclaimed too early.
+                     --  And returns of thunks never require transient scopes.
+
+                     if (Manage_Sec_Stack
+                          and then Needs_Secondary_Stack (Etype (Fun_Id)))
+                       or else Is_Thunk (Fun_Id)
+                     then
+                        return Empty;
 
-                  --  General case for return statements
+                     --  General case for return statements
 
-                  else
-                     return Curr;
-                  end if;
+                     else
+                        return Curr;
+                     end if;
+                  end;
 
                --  Special
 
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 899b5b5c522..b16e48917f2 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -6960,6 +6960,12 @@  package body Sem_Res is
       --  want to create a transient scope (this could occur in the case of a
       --  static string-returning call).
 
+      --  h) If the subprogram is an ignored ghost entity, because it does not
+      --  return anything.
+
+      --  i) If the call is the expression of a simple return statement, since
+      --  it will be handled as a tail call by Expand_Simple_Function_Return.
+
       if Is_Inlined (Nam)
         and then Has_Pragma_Inline (Nam)
         and then Nkind (Unit_Declaration_Node (Nam)) = N_Subprogram_Declaration
@@ -6972,16 +6978,14 @@  package body Sem_Res is
         or else Is_Intrinsic_Subprogram (Nam)
         or else Is_Inlinable_Expression_Function (Nam)
         or else Is_Static_Function_Call (N)
+        or else Is_Ignored_Ghost_Entity (Nam)
+        or else Nkind (Parent (N)) = N_Simple_Return_Statement
       then
          null;
 
-      --  A return statement from an ignored Ghost function does not use the
-      --  secondary stack (or any other one).
-
       elsif Expander_Active
         and then Ekind (Nam) in E_Function | E_Subprogram_Type
         and then Requires_Transient_Scope (Etype (Nam))
-        and then not Is_Ignored_Ghost_Entity (Nam)
       then
          Establish_Transient_Scope (N, Needs_Secondary_Stack (Etype (Nam)));