To iterate over a user-defined container, it must have a primitive operation
that returns an iterator type, that is to say a type that implements one of the
iterfaces declared in an instance of Ada.Iterator_Interfaces. Has_Element is
a formal of this package. In the expansion of the iterator loop, Has_Element
renames some function of an unrelated name, declared in the package that
declares the container. Therefore the actual subprogram must be obtained from
the declaration in the instance, and not from the container package itself.
Tested on x86_64-pc-linux-gnu, committed on trunk
2011-12-21 Ed Schonberg <[email protected]>
* exp_ch5.adb (Expand_Iterator_Loop): The cursor operation
Has_Element is the formal of Iterator_Interfaces, and within
the instantion of this package it is a renaming of some local
function with an unrelated name. Retrieve the operation from
the instance itself, not from the container package.
Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 182572)
+++ exp_ch5.adb (working copy)
@@ -3049,10 +3049,6 @@
Iter_Type := Etype (Name (I_Spec));
- if Is_Iterator (Iter_Type) then
- Pack := Scope (Pack);
- end if;
-
-- The "of" case uses an internally generated cursor whose type
-- is found in the container package. The domain of iteration
-- is expanded into a call to the default Iterator function, but
@@ -3074,42 +3070,42 @@
begin
Cursor := Make_Temporary (Loc, 'I');
- if Is_Iterator (Iter_Type) then
- null;
+ -- For an container element iterator, the iterator type
+ -- is obtained from the corresponding aspect.
- else
- Iter_Type := Etype (Default_Iter);
+ Iter_Type := Etype (Default_Iter);
+ Pack := Scope (Iter_Type);
- -- Rewrite domain of iteration as a call to the default
- -- iterator for the container type. If the container is
- -- a derived type and the aspect is inherited, convert
- -- container to parent type. The Cursor type is also
- -- inherited from the scope of the parent.
+ -- Rewrite domain of iteration as a call to the default
+ -- iterator for the container type. If the container is
+ -- a derived type and the aspect is inherited, convert
+ -- container to parent type. The Cursor type is also
+ -- inherited from the scope of the parent.
- if Base_Type (Etype (Container)) =
- Base_Type (Etype (First_Formal (Default_Iter)))
- then
- Container_Arg := New_Copy_Tree (Container);
+ if Base_Type (Etype (Container)) =
+ Base_Type (Etype (First_Formal (Default_Iter)))
+ then
+ Container_Arg := New_Copy_Tree (Container);
- else
- Container_Arg :=
- Make_Type_Conversion (Loc,
- Subtype_Mark =>
- New_Occurrence_Of
- (Etype (First_Formal (Default_Iter)), Loc),
- Expression => New_Copy_Tree (Container));
- end if;
-
- Rewrite (Name (I_Spec),
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Default_Iter, Loc),
- Parameter_Associations =>
- New_List (Container_Arg)));
- Analyze_And_Resolve (Name (I_Spec));
+ else
+ Container_Arg :=
+ Make_Type_Conversion (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of
+ (Etype (First_Formal (Default_Iter)), Loc),
+ Expression => New_Copy_Tree (Container));
end if;
- -- Find cursor type in proper container package.
+ Rewrite (Name (I_Spec),
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Default_Iter, Loc),
+ Parameter_Associations =>
+ New_List (Container_Arg)));
+ Analyze_And_Resolve (Name (I_Spec));
+ -- Find cursor type in proper iterator package, which
+ -- is an instantiation of Iterator_Interfaces.
+
Ent := First_Entity (Pack);
while Present (Ent) loop
if Chars (Ent) = Name_Cursor then
@@ -3145,7 +3141,7 @@
-- Generate:
-- declare
- -- Id : Element_Type := Pack.Element (curosr);
+ -- Id : Element_Type := Element (curosr);
-- begin
-- <original loop statements>
-- end;
@@ -3222,6 +3218,8 @@
-- while Iterator.Has_Element loop
-- <Stats>
-- end loop;
+ --
+ -- Has_Element is the second actual in the iterator package
New_Loop :=
Make_Loop_Statement (Loc,
@@ -3230,16 +3228,18 @@
Condition =>
Make_Function_Call (Loc,
Name =>
- Make_Selected_Component (Loc,
- Prefix => New_Occurrence_Of (Pack, Loc),
- Selector_Name =>
- Make_Identifier (Loc, Name_Has_Element)),
-
+ New_Occurrence_Of (
+ Next_Entity (First_Entity (Pack)), Loc),
Parameter_Associations =>
New_List (
New_Reference_To (Cursor, Loc)))),
+
Statements => Stats,
End_Label => Empty);
+ -- Make_Selected_Component (Loc,
+ -- Prefix => New_Reference_To (Cursor, Loc),
+ -- Selector_Name =>
+ -- Make_Identifier (Loc, Name_Has_Element))),
-- Create the declarations for Iterator and cursor and insert then
-- before the source loop. Given that the domain of iteration is
@@ -3248,7 +3248,7 @@
-- Generate:
-- I : Iterator_Type renames Container;
- -- C : Pack.Cursor_Type := Container.[First | Last];
+ -- C : Cursor_Type := Container.[First | Last];
Insert_Action (N,
Make_Object_Renaming_Declaration (Loc,