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