When compiling iterated_component_association, the analysis, resolution
and range checking is done when expanding aggregate into assignments.
This is now mirrored in the custom expansion for GNATprove, so that the
backend sees a fully decorated (but unexpanded) AST.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

        * exp_spark.adb (Expand_SPARK_N_Aggregate,
        Expand_SPARK_Delta_Or_Update): Expand
        Iterated_Component_Association occurring within delta
        aggregates.
        (Expand_SPARK): Apply SPARK-specific expansion to ordinary
        aggregates.
diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb
--- a/gcc/ada/exp_spark.adb
+++ b/gcc/ada/exp_spark.adb
@@ -36,6 +36,7 @@ with Nlists;   use Nlists;
 with Nmake;    use Nmake;
 with Rtsfind;  use Rtsfind;
 with Sem;      use Sem;
+with Sem_Ch8;  use Sem_Ch8;
 with Sem_Prag; use Sem_Prag;
 with Sem_Res;  use Sem_Res;
 with Sem_Util; use Sem_Util;
@@ -51,6 +52,9 @@ package body Exp_SPARK is
    -- Local Subprograms --
    -----------------------
 
+   procedure Expand_SPARK_N_Aggregate (N : Node_Id);
+   --  Perform aggregate-specific expansion
+
    procedure Expand_SPARK_N_Attribute_Reference (N : Node_Id);
    --  Perform attribute-reference-specific expansion
 
@@ -101,6 +105,9 @@ package body Exp_SPARK is
          =>
             Qualify_Entity_Names (N);
 
+         when N_Aggregate =>
+            Expand_SPARK_N_Aggregate (N);
+
          --  Replace occurrences of System'To_Address by calls to
          --  System.Storage_Elements.To_Address.
 
@@ -215,11 +222,29 @@ package body Exp_SPARK is
                Expr      := Expression (Assoc);
                Comp_Type := Component_Type (Typ);
 
+               --  Analyze expression of the iterated_component_association
+               --  with its index parameter in scope.
+
+               if Nkind (Assoc) = N_Iterated_Component_Association then
+                  Push_Scope (Scope (Defining_Identifier (Assoc)));
+                  Analyze_And_Resolve (Expression (Assoc), Comp_Type);
+               end if;
+
                if Is_Scalar_Type (Comp_Type) then
                   Apply_Scalar_Range_Check (Expr, Comp_Type);
                end if;
 
-               Index     := First (Choices (Assoc));
+               --  Restore scope of the iterated_component_association
+
+               if Nkind (Assoc) = N_Iterated_Component_Association then
+                  End_Scope;
+               end if;
+
+               Index :=
+                 First
+                   (if Nkind (Assoc) = N_Iterated_Component_Association
+                    then Discrete_Choices (Assoc)
+                    else Choices (Assoc));
                Index_Typ := First_Index (Typ);
 
                while Present (Index) loop
@@ -340,6 +365,74 @@ package body Exp_SPARK is
       end if;
    end Expand_SPARK_N_Freeze_Type;
 
+   ------------------------------
+   -- Expand_SPARK_N_Aggregate --
+   ------------------------------
+
+   procedure Expand_SPARK_N_Aggregate (N : Node_Id) is
+      Assoc : Node_Id := First (Component_Associations (N));
+   begin
+      --  For compilation, frontend analyses a copy of the
+      --  iterated_component_association's expression for legality checking;
+      --  (then the expression is copied again when expanding association into
+      --  assignments for the individual choices). For SPARK we analyze the
+      --  original expression and apply range checks, if required.
+
+      while Present (Assoc) loop
+         if Nkind (Assoc) = N_Iterated_Component_Association then
+            declare
+               Typ : constant Entity_Id := Etype (N);
+
+               Comp_Type : constant Entity_Id := Component_Type (Typ);
+               Expr      : constant Node_Id := Expression (Assoc);
+               Index_Typ : constant Entity_Id := First_Index (Typ);
+
+               Index : Node_Id;
+
+            begin
+               --  Analyze expression with index parameter in scope
+
+               Push_Scope (Scope (Defining_Identifier (Assoc)));
+               Enter_Name (Defining_Identifier (Assoc));
+               Analyze_And_Resolve (Expression (Assoc), Comp_Type);
+
+               if Is_Scalar_Type (Comp_Type) then
+                  Apply_Scalar_Range_Check (Expr, Comp_Type);
+               end if;
+
+               End_Scope;
+
+               --  Analyze discrete choices
+
+               Index := First (Discrete_Choices (Assoc));
+
+               while Present (Index) loop
+
+                  --  The index denotes a range of elements where range checks
+                  --  have been already applied.
+
+                  if Nkind (Index) in N_Others_Choice
+                                    | N_Range
+                                    | N_Subtype_Indication
+                  then
+                     null;
+
+                  --  Otherwise the index denotes a single element (or a
+                  --  subtype name which doesn't require range checks).
+
+                  else pragma Assert (Nkind (Index) in N_Subexpr);
+                     Apply_Scalar_Range_Check (Index, Etype (Index_Typ));
+                  end if;
+
+                  Next (Index);
+               end loop;
+            end;
+         end if;
+
+         Next (Assoc);
+      end loop;
+   end Expand_SPARK_N_Aggregate;
+
    ----------------------------------------
    -- Expand_SPARK_N_Attribute_Reference --
    ----------------------------------------


Reply via email to