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.

Reply via email to