-- The package in which the iterator interface is instantiated. This is
-- typically an instance within the container package.
- Pack : Entity_Id;
- -- The package in which the container type is declared
-
begin
if Present (Iterator_Filter (I_Spec)) then
pragma Assert (Ada_Version >= Ada_2022);
-- package Vector_Iterator_Interfaces is new
-- Ada.Iterator_Interfaces (Cursor, Has_Element);
- -- If the container type is a derived type, the cursor type is found in
- -- the package of the ultimate ancestor type.
-
- if Is_Derived_Type (Container_Typ) then
- Pack := Scope (Root_Type (Container_Typ));
- else
- Pack := Scope (Container_Typ);
- end if;
-
if Of_Present (I_Spec) then
Handle_Of : declare
Container_Arg : Node_Id;
Default_Iter : Entity_Id;
Ent : Entity_Id;
+ Cont_Type_Pack : Entity_Id;
+ -- The package in which the container type is declared
+
Reference_Control_Type : Entity_Id := Empty;
Pseudo_Reference : Entity_Id := Empty;
Iter_Type := Etype (Default_Iter);
- -- The iterator type, which is a class-wide type, may itself be
- -- derived locally, so the desired instantiation is the scope of
- -- the root type of the iterator type.
+ -- If the container type is a derived type, the cursor type is
+ -- found in the package of the ultimate ancestor type.
- Iter_Pack := Scope (Root_Type (Etype (Iter_Type)));
+ if Is_Derived_Type (Container_Typ) then
+ Cont_Type_Pack := Scope (Root_Type (Container_Typ));
+ else
+ Cont_Type_Pack := Scope (Container_Typ);
+ end if;
-- Find declarations needed for "for ... of" optimization.
-- These declarations come from GNAT sources or sources
-- Note that we use _Next or _Previous to avoid picking up
-- some arbitrary user-defined Next or Previous.
- Ent := First_Entity (Pack);
+ Ent := First_Entity (Cont_Type_Pack);
while Present (Ent) loop
-- Get_Element_Access function with one parameter called
-- Position.
Analyze_And_Resolve (Name (I_Spec));
+ -- The desired instantiation is the scope of an iterator interface
+ -- type that is an ancestor of the iterator type.
+
+ Iter_Pack := Scope (Iterator_Interface_Ancestor (Iter_Type));
+
-- Find cursor type in proper iterator package, which is an
-- instantiation of Iterator_Interfaces.
else
Iter_Type := Etype (Name (I_Spec));
- -- The iterator type, which is a class-wide type, may itself be
- -- derived locally, so the desired instantiation is the scope of
- -- the root type of the iterator type, as in the "of" case.
+ -- The instantiation in which to locate the Has_Element function
+ -- is the scope containing an iterator interface type that is
+ -- an ancestor of the iterator type.
+
+ Iter_Pack := Scope (Iterator_Interface_Ancestor (Iter_Type));
- Iter_Pack := Scope (Root_Type (Etype (Iter_Type)));
Cursor := Id;
end if;
Ent : Entity_Id;
begin
- -- If iterator type is derived, the cursor is declared in the scope
- -- of the parent type.
+ -- If the iterator type is derived and it has an iterator interface
+ -- type as an ancestor, then the cursor type is declared in the scope
+ -- of that interface type.
if Is_Derived_Type (Typ) then
- Ent := First_Entity (Scope (Etype (Typ)));
+ declare
+ Iter_Iface : constant Entity_Id :=
+ Iterator_Interface_Ancestor (Typ);
+
+ begin
+ if Present (Iter_Iface) then
+ Ent := First_Entity (Scope (Iter_Iface));
+
+ -- If there's not an iterator interface, then retrieve the
+ -- scope associated with the parent type and start from its
+ -- first entity.
+
+ else
+ Ent := First_Entity (Scope (Etype (Typ)));
+ end if;
+ end;
+
else
Ent := First_Entity (Scope (Typ));
end if;
pragma Assert (No (Actual));
end Iterate_Call_Parameters;
+ --------------------------------
+ -- Iterate_Interface_Ancestor --
+ --------------------------------
+
+ function Iterator_Interface_Ancestor (Typ : Entity_Id) return Entity_Id is
+ begin
+ if Has_Interfaces (Typ) then
+ declare
+ Iface_Elmt : Elmt_Id;
+ Ifaces : Elist_Id;
+ Root_Iface : Entity_Id;
+
+ begin
+ Collect_Interfaces (Typ, Ifaces);
+
+ Iface_Elmt := First_Elmt (Ifaces);
+ while Present (Iface_Elmt) loop
+ Root_Iface := Root_Type (Node (Iface_Elmt));
+
+ if Chars (Root_Iface)
+ in Name_Forward_Iterator | Name_Reversible_Iterator
+ and then In_Predefined_Unit (Root_Iface)
+ then
+ return Root_Iface;
+ end if;
+
+ Next_Elmt (Iface_Elmt);
+ end loop;
+ end;
+ end if;
+
+ return Empty;
+ end Iterator_Interface_Ancestor;
+
-------------------------
-- Kill_Current_Values --
-------------------------
-- Calls Handle_Parameter for each pair of formal and actual parameters of
-- a function, procedure, or entry call.
+ function Iterator_Interface_Ancestor (Typ : Entity_Id) return Entity_Id;
+ -- If Typ has an ancestor that is an iterator interface type declared in
+ -- an instance of Ada.Iterator_Interfaces, then returns that interface
+ -- type. Otherwise returns Empty. (It's not clear what it means if there
+ -- is more than one such ancestor, perhaps coming from multiple instances,
+ -- but this function returns the first such ancestor it finds. ???)
+
procedure Kill_Current_Values (Last_Assignment_Only : Boolean := False);
-- This procedure is called to clear all constant indications from all
-- entities in the current scope and in any parent scopes if the current