https://gcc.gnu.org/g:6a64f6c3ebb88a30ee1f36803c48573731018e0c

commit r15-10648-g6a64f6c3ebb88a30ee1f36803c48573731018e0c
Author: Eric Botcazou <[email protected]>
Date:   Sat Jan 3 11:47:35 2026 +0100

    Ada: Fix infinite loop on iterated element association with iterator and key
    
    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.
    
    gcc/ada/
            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.
    
    gcc/testsuite/
            * gnat.dg/specs/aggr10.ads: New test.

Diff:
---
 gcc/ada/sem_aggr.adb                   | 20 +++++++++++---------
 gcc/testsuite/gnat.dg/specs/aggr10.ads | 21 +++++++++++++++++++++
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index c78bed006ec2..736ff2c1fc9d 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -3826,10 +3826,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');
@@ -3841,8 +3840,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 :=
@@ -3853,9 +3851,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);
 
@@ -3876,17 +3876,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');
diff --git a/gcc/testsuite/gnat.dg/specs/aggr10.ads 
b/gcc/testsuite/gnat.dg/specs/aggr10.ads
new file mode 100644
index 000000000000..caa42ff1caad
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/aggr10.ads
@@ -0,0 +1,21 @@
+-- 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