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 <[email protected]>
* 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