This patch enforces the same semantics for the handling of loop parameters
in element iterators over formal containers, os those over formal containers:
the loop parameter cannot be assigned to in user code.

Compiling formal_test.adb must yield:

   formal_test.adb:15:07: assignment to loop parameter not allowed

---
with Ada.Containers.Formal_Doubly_Linked_Lists;
procedure Formal_Test is
   type E is range 1 .. 1000;
   package My_List is new Ada.Containers.Formal_Doubly_Linked_Lists (E);
   use My_List;
   Thing : My_List.List (10);
   C : Cursor;
begin
   for I in 1 .. 10 loop
      Append (Thing, E (I));
   end loop;

   for Element of Thing loop
      null;
      Element := Element * 3;  --  ERROR
   end loop;
end;

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

2014-10-10  Ed Schonberg  <schonb...@adacore.com>

        * exp_ch5.adb (Expand_Formal_Container_Element_Loop): Analyze
        declaration for loop parameter before rest of loop, and set
        entity kind to prevent assignments to it in the user code.
        * sem_ch3.adb (Analyze_Object_Contract): No contracts apply to the
        loop parameter in an element iteration over o formal container.

Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 216063)
+++ exp_ch5.adb (working copy)
@@ -2889,7 +2889,17 @@
               Statements =>  New_List (New_Loop)));
 
       Rewrite (N, New_Loop);
-      Analyze (New_Loop);
+
+      --  The loop parameter is declared by an object declaration, but within
+      --  the loop we must prevent user assignments to it, so we analyze the
+      --  declaration and reset the entity kind, before analyzing the rest of
+      --  the loop;
+
+      Analyze (Elmt_Decl);
+      Set_Ekind (Defining_Identifier (Elmt_Decl), E_Loop_Parameter);
+      Set_Assignment_OK (Name (Elmt_Ref));
+
+      Analyze (N);
    end Expand_Formal_Container_Element_Loop;
 
    -----------------------------
Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb (revision 216063)
+++ sem_ch3.adb (working copy)
@@ -3062,6 +3062,12 @@
             Error_Msg_N ("constant cannot be volatile", Obj_Id);
          end if;
 
+      --  The loop parameter in an element iterator over a formal container
+      --  is declared with an object declaration but no contracts apply.
+
+      elsif Ekind (Obj_Id) = E_Loop_Parameter then
+         null;
+
       else pragma Assert (Ekind (Obj_Id) = E_Variable);
 
          --  The following checks are only relevant when SPARK_Mode is on as

Reply via email to