This patch adds a legality check that in a loop over a container that only has a constant indexing aspect, elements are constant within the loop, and attempts to modify them are appripriately rejected.
Compiling p.adb must yield: p.adb:15:07: left hand side of assignment must be a variable --- with Ada.Containers.Hashed_Sets; use Ada.Containers; procedure P is function Hash (N : Natural) return Hash_Type is begin return Hash_Type (N); end; package Sets is new Ada.Containers.Hashed_Sets (Natural, Hash, "="); S : Sets.Set; begin S.Insert (1); for NConst of S loop NConst := 0; -- Should not be allowed end loop; end; Tested on x86_64-pc-linux-gnu, committed on trunk 2014-02-04 Ed Schonberg <schonb...@adacore.com> * exp_ch5.adb (Expand_Iterator_Loop): For a container element iterator, indicate that the element is a constant if the container type does not have a variable indexing aspect. * sem_ch8.adb (Analyze_Object_Renaming): If the entity is already marked as constant, do not reset its Ekind, to ensure that container elements in an element loop are not modified if the container (e.g. a hashed set) only has a constant indexing aspect.
Index: exp_ch5.adb =================================================================== --- exp_ch5.adb (revision 207465) +++ exp_ch5.adb (working copy) @@ -3128,6 +3128,15 @@ Set_Debug_Info_Needed (Id); + -- If the container does not have a variable indexing aspect, + -- the element is a constant in the loop. + + if No (Find_Value_Of_Aspect + (Container_Typ, Aspect_Variable_Indexing)) + then + Set_Ekind (Id, E_Constant); + end if; + -- If the container holds controlled objects, wrap the loop -- statements and element renaming declaration with a block. -- This ensures that the result of Element (Cusor) is Index: sem_ch8.adb =================================================================== --- sem_ch8.adb (revision 207465) +++ sem_ch8.adb (working copy) @@ -1193,8 +1193,14 @@ end; end if; - Set_Ekind (Id, E_Variable); + -- Set the Ekind of the entity, unless it has been set already, as is + -- the case for the iteration object over a container with no variable + -- indexing. + if Ekind (Id) /= E_Constant then + Set_Ekind (Id, E_Variable); + end if; + -- Initialize the object size and alignment. Note that we used to call -- Init_Size_Align here, but that's wrong for objects which have only -- an Esize, not an RM_Size field.