Unlike when the key expression is not present, Resolve_Iterated_Association 
analyzes instead of preanalyzes the iterator specification, which causes the 
expander to be invoked on an orphaned copy of the iterator expression.

Tested on x86-64/Linux, applied on the mainline and 15 branch.


2026-01-30  Eric Botcazou  <[email protected]>

        PR ada/123371
        * sem_aggr.adb (Resolve_Iterated_Association): Call Preanalyze
        instead of Analyze consistently, as well as Copy_Separate_Tree
        instead of New_Copy_Tree.


2026-01-30  Eric Botcazou  <[email protected]>

        * gnat.dg/specs/aggr10.ads: New test.

-- 
Eric Botcazou
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 729835053ed..928f4f7bbc4 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -3853,10 +3853,9 @@ package body Sem_Aggr is
          --  is present.
 
          if Nkind (Comp) = N_Iterated_Element_Association then
-
             --  Create a temporary scope to avoid some modifications from
-            --  escaping the Analyze call below. The original Tree will be
-            --  reanalyzed later.
+            --  escaping the Preanalyze call below. The original tree will
+            --  be reanalyzed later.
 
             Ent := New_Internal_Entity
                      (E_Loop, Current_Scope, Sloc (Comp), 'L');
@@ -3868,8 +3867,7 @@ package body Sem_Aggr is
                Copy := Copy_Separate_Tree (Comp);
                Set_Parent (Copy, Parent (Comp));
 
-               Analyze
-                 (Loop_Parameter_Specification (Copy));
+               Preanalyze (Loop_Parameter_Specification (Copy));
 
                if Present (Iterator_Specification (Copy)) then
                   Loop_Param_Id :=
@@ -3880,9 +3878,11 @@ package body Sem_Aggr is
                end if;
 
                Id_Name := Chars (Loop_Param_Id);
+
             else
                Copy := Copy_Separate_Tree (Iterator_Specification (Comp));
-               Analyze (Copy);
+
+               Preanalyze (Copy);
 
                Loop_Param_Id := Defining_Identifier (Copy);
 
@@ -3903,17 +3903,19 @@ package body Sem_Aggr is
                        & "(RM22 4.3.5(24))",
                      Comp);
                else
-                  Preanalyze_And_Resolve (New_Copy_Tree (Key_Expr), Key_Type);
+                  Preanalyze_And_Resolve
+                    (Copy_Separate_Tree (Key_Expr), Key_Type);
                end if;
             end if;
+
             End_Scope;
 
             Typ := Etype (Loop_Param_Id);
 
          elsif Present (Iterator_Specification (Comp)) then
             --  Create a temporary scope to avoid some modifications from
-            --  escaping the Analyze call below. The original Tree will be
-            --  reanalyzed later.
+            --  escaping the Preanalyze call below. The original tree will
+            --  be reanalyzed later.
 
             Ent := New_Internal_Entity
                      (E_Loop, Current_Scope, Sloc (Comp), 'L');
-- PR ada/123371
-- { dg-do compile }
-- { dg-options "-gnat2022" }

with Ada.Containers.Ordered_Maps;

package Aggr10 is

  package Maps is new Ada.Containers.Ordered_Maps (Integer, Integer);

  function F return Maps.Map is ([]);

  A : Maps.Map := [for I of Maps.Map'[] => 1]; --  Works
  B : Maps.Map := [for I of A => 1]; --  Works
  C : Maps.Map := [for I of B use 1 => 1]; --  Works
  D : Maps.Map := [for I of F => 1]; --  Works

  X : Maps.Map := [for I of Maps.Map'[] use 1 => 1]; --  Infinite loop
  Y : Maps.Map := [for I of F use 1 => 1]; --  Infinite loop

end Aggr10;

Reply via email to