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