From 82c1b037959d06a76309e4d371aba020b010d9fa Mon Sep 17 00:00:00 2001
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Wed, 27 Nov 2024 13:03:08 +0100
Subject: ada: Fix dangling reference with user-defined indexing of function
 call

This happens with a noncontrolled type because the user-defined indexing is
expanded into a function call that binds the lifetime of the original call
to its return value.  The temporary must be created explicitly in this case,
so that the front-end can control its lifetime.

gcc/ada/ChangeLog:

	* exp_ch6.adb (Expand_Call_Helper): Also create a temporary in the
	case of a noncontrolled user-defined indexing.
---
 gcc/ada/exp_ch6.adb | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

(limited to 'gcc')

diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 20ce7a5..945f446 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -5314,6 +5314,42 @@ package body Exp_Ch6 is
             Establish_Transient_Scope
               (Call_Node, Needs_Secondary_Stack (Etype (Call_Node)));
          end if;
+
+      --  Functions returning noncontrolled objects that may be subject to
+      --  user-defined indexing also need special attention. The problem
+      --  is that, when a call to such a function is directly passed as an
+      --  actual in a call to the Constant_Indexing function, the latter
+      --  call effectively binds the lifetime of the actual to that of its
+      --  return value, thus extending it beyond the call. This cannot be
+      --  directly supported by code generators, for which the lifetime of
+      --  temporaries created for actuals ends immediately after the call.
+      --  Therefore we force the creation of a temporary in this case, as
+      --  the above code would have done in the controlled case; note that,
+      --  in this latter case, the temporary cannot be finalized just after
+      --  the call as would naturally be done, and Is_Finalizable_Transient
+      --  also has a special processing for it (see Is_Indexed_Container).
+
+      elsif Nkind (Call_Node) = N_Function_Call
+        and then Nkind (Parent (Call_Node)) = N_Function_Call
+      then
+         declare
+            Aspect : constant Node_Id :=
+              Find_Value_Of_Aspect
+                (Etype (Call_Node), Aspect_Constant_Indexing);
+
+         begin
+            if Present (Aspect)
+              and then Is_Entity_Name (Name (Parent (Call_Node)))
+              and then Entity (Name (Parent (Call_Node))) = Entity (Aspect)
+            then
+               --  Resolution is now finished, make sure we don't start
+               --  analysis again because of the duplication.
+
+               Set_Analyzed (Call_Node);
+
+               Remove_Side_Effects (Call_Node);
+            end if;
+         end;
       end if;
    end Expand_Call_Helper;
 
-- 
cgit v1.1