If the range of iteration in an Ada2012 iterator is a function call returning
a container, finalization actions will in general be created because the
predefined containers are controlled. The finalization actions must be taken
into account when rewriting the iteration as a while-loop.

Compiling and executing the following in Ada2012 mode must yield:

 12345

---
with Ada.Containers.Ordered_Sets;
with Text_IO; use Text_IO;
procedure T is
   function Hash (X : integer) return integer is begin return X / 2; end;
   package Integer_Sets is
      new Ada.Containers.Ordered_Sets (Element_Type => Integer);
   function P  return Integer_Sets.Set;

   function P  return Integer_Sets.Set is
      use Integer_Sets;
      result : Set := Empty_Set;
   begin
      Result.Insert (12345);
      return Result;
   end P;

begin
   for Element of P loop
      Put_Line (Integer'Image (Element));
   end loop;
end T;

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

2011-08-02  Ed Schonberg  <schonb...@adacore.com>

        * sem_ch5.adb (Analyze_Iteration_Scheme): For an Ada2012 iterator with
        "of", pre-analyze expression in case it is a function call with
        finalization actions that must be placed ahead of the loop.
        * exp_ch5.adb (Expand_Iterator_Loop): If condition_actions are present
        on an Ada2012 iterator, insert them ahead of the rewritten loop.

Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 177130)
+++ exp_ch5.adb (working copy)
@@ -2952,6 +2952,15 @@
                 Make_Iteration_Scheme (Loc, Condition => Cond),
               Statements       => Stats,
               End_Label        => Empty);
+
+            --  If the range of iteration is given by a function call that
+            --  returns a container, the finalization actions have been saved
+            --  in the Condition_Actions of the iterator. Insert them now at
+            --  the head of the loop.
+
+            if Present (Condition_Actions (Isc)) then
+               Insert_List_Before (N, Condition_Actions (Isc));
+            end if;
          end;
       end if;
 
@@ -3158,6 +3167,7 @@
 
       elsif Present (Isc)
         and then Present (Condition_Actions (Isc))
+        and then Present (Condition (Isc))
       then
          declare
             ES : Node_Id;
Index: sem_ch5.adb
===================================================================
--- sem_ch5.adb (revision 177145)
+++ sem_ch5.adb (working copy)
@@ -1919,7 +1919,11 @@
             Set_Current_Value_Condition (N);
             return;
 
+         --  For an iterator specification with "of", pre-analyze range to
+         --  capture function calls that may require finalization actions.
+
          elsif Present (Iterator_Specification (N)) then
+            Pre_Analyze_Range (Name (Iterator_Specification (N)));
             Analyze_Iterator_Specification (Iterator_Specification (N));
 
          --  Else we have a FOR loop
@@ -1974,7 +1978,7 @@
                then
                   Process_Bounds (DS);
 
-               --  Expander not active or else domain of iteration is a subtype
+               --  expander not active or else range of iteration is a subtype
                --  indication, an entity, or a function call that yields an
                --  aggregate or a container.
 
@@ -1989,7 +1993,8 @@
                         and then not Is_Type (Entity (D_Copy)))
                   then
                      --  This is an iterator specification. Rewrite as such
-                     --  and analyze.
+                     --  and analyze, to capture function calls that may
+                     --  require finalization actions.
 
                      declare
                         I_Spec : constant Node_Id :=
@@ -1997,8 +2002,7 @@
                                      Defining_Identifier =>
                                        Relocate_Node (Id),
                                      Name                => D_Copy,
-                                     Subtype_Indication  =>
-                                       Empty,
+                                     Subtype_Indication  => Empty,
                                      Reverse_Present     =>
                                        Reverse_Present (LP));
                      begin

Reply via email to