diff mbox

[Ada] Loops over containers without variable indexing

Message ID 20140204145010.GA13886@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Feb. 4, 2014, 2:50 p.m. UTC
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  <schonberg@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.
diff mbox

Patch

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.