This completes the transition of the Resolve_Iterated_Association procedure to 
the preanalysis of the original nodes for the sake of generic instantiations.

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


2026-02-27  Eric Botcazou  <[email protected]>

        PR ada/124201
        PR ada/124282
        * exp_aggr.adb (Expand_Iterated_Component): Replace the iteration
        variable in the expression as well.
        * sem_aggr.adb (Resolve_Iterated_Component_Association): Preanalyze
        the expression directly as well.


2026-02-27  Eric Botcazou  <[email protected]>

        * gnat.dg/generic_inst18.adb: New test.

-- 
Eric Botcazou
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index d2e99f49e01..4b14043d276 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -7017,14 +7017,11 @@ package body Exp_Aggr is
       -------------------------------
 
       procedure Expand_Iterated_Component (Comp : Node_Id) is
-         Expr : constant Node_Id := Expression (Comp);
-
-         Key_Expr           : Node_Id;
-         Loop_Id            : Entity_Id;
-         L_Range            : Node_Id;
-         L_Iteration_Scheme : Node_Id;
-         Loop_Stat          : Node_Id;
-         Stats              : List_Id;
+         Key_Expr         : Node_Id;
+         Loop_Id          : Entity_Id;
+         Loop_Iter_Scheme : Node_Id;
+         Loop_Stat        : Node_Id;
+         Stats            : List_Id;
 
          procedure Replace_Iteration_Variable (N : Node_Id; Var : Entity_Id);
          --  Replace the iteration variable of N, a N_Iterator_Specification or
@@ -7062,6 +7059,9 @@ package body Exp_Aggr is
                   Set_Iterator_Filter (N,
                     New_Copy_Tree (Iterator_Filter (N), Map => Map));
                end if;
+
+               Set_Expression (Comp,
+                 New_Copy_Tree (Expression (Comp), Map => Map));
             end if;
 
             Set_Defining_Identifier (N, Var);
@@ -7079,18 +7079,18 @@ package body Exp_Aggr is
             --  Specification is present.
 
             if Present (Iterator_Specification (Comp)) then
-               L_Iteration_Scheme :=
+               Loop_Iter_Scheme :=
                  Make_Iteration_Scheme (Loc,
                    Iterator_Specification => Iterator_Specification (Comp));
                Loop_Id :=
-                  Make_Defining_Identifier (Loc,
-                    Chars => Chars (Defining_Identifier
-                               (Iterator_Specification (Comp))));
+                 Make_Defining_Identifier (Loc,
+                   Chars => Chars (Defining_Identifier
+                              (Iterator_Specification (Comp))));
                Replace_Iteration_Variable
-                 (Iterator_Specification (Comp), Loop_Id);
+                 (Iterator_Specification (Loop_Iter_Scheme), Loop_Id);
 
             else
-               L_Iteration_Scheme :=
+               Loop_Iter_Scheme :=
                  Make_Iteration_Scheme (Loc,
                    Loop_Parameter_Specification =>
                      Loop_Parameter_Specification (Comp));
@@ -7099,14 +7099,14 @@ package body Exp_Aggr is
                    Chars => Chars (Defining_Identifier
                               (Loop_Parameter_Specification (Comp))));
                Replace_Iteration_Variable
-                 (Loop_Parameter_Specification (Comp), Loop_Id);
+                 (Loop_Parameter_Specification (Loop_Iter_Scheme), Loop_Id);
             end if;
 
             Key_Expr := Key_Expression (Comp);
 
          else pragma Assert (Nkind (Comp) = N_Iterated_Component_Association);
             if Present (Iterator_Specification (Comp)) then
-               L_Iteration_Scheme :=
+               Loop_Iter_Scheme :=
                  Make_Iteration_Scheme (Loc,
                    Iterator_Specification => Iterator_Specification (Comp));
                Loop_Id :=
@@ -7114,7 +7114,7 @@ package body Exp_Aggr is
                    Chars => Chars (Defining_Identifier
                               (Iterator_Specification (Comp))));
                Replace_Iteration_Variable
-                 (Iterator_Specification (Comp), Loop_Id);
+                 (Iterator_Specification (Loop_Iter_Scheme), Loop_Id);
 
             --  Loop_Parameter_Specification is parsed with a choice list
             --  where the range is the first (and only) choice.
@@ -7123,15 +7123,16 @@ package body Exp_Aggr is
                Loop_Id :=
                  Make_Defining_Identifier (Loc,
                    Chars => Chars (Defining_Identifier (Comp)));
-               L_Range := Relocate_Node (First (Discrete_Choices (Comp)));
-
-               L_Iteration_Scheme :=
+               Loop_Iter_Scheme :=
                  Make_Iteration_Scheme (Loc,
                    Loop_Parameter_Specification =>
                      Make_Loop_Parameter_Specification (Loc,
-                       Defining_Identifier => Loop_Id,
+                       Defining_Identifier => Defining_Identifier (Comp),
                        Reverse_Present => Reverse_Present (Comp),
-                       Discrete_Subtype_Definition => L_Range));
+                       Discrete_Subtype_Definition =>
+                         Relocate_Node (First (Discrete_Choices (Comp)))));
+               Replace_Iteration_Variable
+                 (Loop_Parameter_Specification (Loop_Iter_Scheme), Loop_Id);
             end if;
 
             Key_Expr := Empty;
@@ -7149,7 +7150,7 @@ package body Exp_Aggr is
                   New_Occurrence_Of (Entity (Add_Unnamed_Subp), Loc),
                 Parameter_Associations => New_List (
                   New_Copy_Tree (Lhs),
-                  New_Copy_Tree (Expr))));
+                  Expression (Comp))));
 
          --  Named or indexed aggregate. If a Key_Expression is present, it
          --  serves as the additional parameter. Otherwise the key is given
@@ -7165,13 +7166,13 @@ package body Exp_Aggr is
                   (if Present (Key_Expr)
                    then Key_Expr
                    else New_Occurrence_Of (Loop_Id, Loc)),
-                  New_Copy_Tree (Expr))));
+                  Expression (Comp))));
          end if;
 
          Loop_Stat := Make_Implicit_Loop_Statement
                         (Node             => N,
                          Identifier       => Empty,
-                         Iteration_Scheme => L_Iteration_Scheme,
+                         Iteration_Scheme => Loop_Iter_Scheme,
                          Statements       => Stats);
 
          Append (Loop_Stat, Aggr_Code);
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 4b82a340219..4bb3cb21c21 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -3836,7 +3836,6 @@ package body Sem_Aggr is
 
          Choice        : Node_Id;
          Copy          : Node_Id;
-         Expr          : Node_Id;
          Key_Expr      : Node_Id := Empty;
          Id            : Entity_Id;
          Scop          : Entity_Id;
@@ -3983,14 +3982,12 @@ package body Sem_Aggr is
                "(RM22 4.3.5(27))", Id, Etype (Id));
          end if;
 
-         --  Analyze a copy of the expression, to verify legality. We use
-         --  a copy because the expression will be analyzed anew when the
-         --  enclosing aggregate is expanded, and the construct is rewritten
-         --  as a loop with a new index variable.
+         --  Preanalyze the expression, to verify legality. We preanalyze it
+         --  because the expression will be analyzed anew when the enclosing
+         --  aggregate is expanded, and the construct is rewritten as a loop
+         --  with a new index variable.
 
-         Expr := Copy_Separate_Tree (Expression (Comp));
-         Set_Parent (Expr, Comp);
-         Preanalyze_And_Resolve (Expr, Elmt_Type);
+         Preanalyze_And_Resolve (Expression (Comp), Elmt_Type);
          End_Scope;
       end Resolve_Iterated_Association;
 
-- { dg-do compile }
-- { dg-options "-gnat2022" }

with Ada.Containers.Indefinite_Ordered_Maps;

procedure Generic_Inst18 is

   package Nested is
      type Axis_Name is (X_Axis, Y_Axis, Z_Axis, E_Axis);

      type R (A : Axis_Name) is record
         B : Axis_Name;
      end record;

      package Status_Group_Maps is new
        Ada.Containers.Indefinite_Ordered_Maps (Axis_Name, R);

      generic
      package Modules is
         type Module is abstract tagged null record;
         function Status_Schema (This : Module) return Status_Group_Maps.Map
         is ([]);
      end Modules;

      generic
         with package My_Modules is new Modules;
      package Internal_Status_Reporter is
         type Module is new My_Modules.Module with null record;
         function Status_Schema (This : Module) return Status_Group_Maps.Map
         is ([for A in Axis_Name => (A => X_Axis, B => X_Axis)]);
      end Internal_Status_Reporter;

      generic
      package Controller is
         package My_Modules is new Modules;
         package My_Internal_Status_Reporter is new
           Internal_Status_Reporter (My_Modules);
      end Controller;
   end Nested;

   package My_Controller is new Nested.Controller;

begin
   null;
end Generic_Inst18;

Reply via email to