-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2016, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
Container : Node_Id;
Container_Typ : Entity_Id)
is
- Id : constant Entity_Id := Defining_Identifier (I_Spec);
- Loc : constant Source_Ptr := Sloc (N);
-
- I_Kind : constant Entity_Kind := Ekind (Id);
- Cursor : Entity_Id;
- Iterator : Entity_Id;
- New_Loop : Node_Id;
- Stats : constant List_Id := Statements (N);
+ Id : constant Entity_Id := Defining_Identifier (I_Spec);
+ Elem_Typ : constant Entity_Id := Etype (Id);
+ Id_Kind : constant Entity_Kind := Ekind (Id);
+ Loc : constant Source_Ptr := Sloc (N);
+ Stats : constant List_Id := Statements (N);
- Element_Type : constant Entity_Id := Etype (Id);
- Iter_Type : Entity_Id;
- Pack : Entity_Id;
- Decl : Node_Id;
- Name_Init : Name_Id;
- Name_Step : Name_Id;
+ Cursor : Entity_Id;
+ Decl : Node_Id;
+ Iter_Type : Entity_Id;
+ Iterator : Entity_Id;
+ Name_Init : Name_Id;
+ Name_Step : Name_Id;
+ New_Loop : Node_Id;
- Fast_Element_Access_Op, Fast_Step_Op : Entity_Id := Empty;
+ Fast_Element_Access_Op : Entity_Id := Empty;
+ Fast_Step_Op : Entity_Id := Empty;
-- Only for optimized version of "for ... of"
+ Iter_Pack : Entity_Id;
+ -- 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
-- Determine the advancement and initialization steps for the cursor.
-- Analysis of the expanded loop will verify that the container has a
Pack := Scope (Container_Typ);
end if;
- Iter_Type := Etype (Name (I_Spec));
-
if Of_Present (I_Spec) then
Handle_Of : declare
Container_Arg : Node_Id;
end if;
end Get_Default_Iterator;
+ -- Local variables
+
Default_Iter : Entity_Id;
Ent : Entity_Id;
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.
+
+ Iter_Pack := Scope (Root_Type (Etype (Iter_Type)));
+
-- Find declarations needed for "for ... of" optimization
Ent := First_Entity (Pack);
New_List (New_Copy_Tree (Container_Arg)))));
end if;
- -- 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. Currently, Pack is the
- -- container instance; this overwrites it with the iterator
- -- package.
+ -- Rewrite domain of iteration as a call to the default iterator
+ -- for the container type. The formal may be an access parameter
+ -- in which case we must build a reference to the container.
- Pack := Scope (Root_Type (Etype (Iter_Type)));
+ declare
+ Arg : Node_Id;
+ begin
+ if Is_Access_Type (Etype (First_Entity (Default_Iter))) then
+ Arg :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Container_Arg,
+ Attribute_Name => Name_Unrestricted_Access);
+ else
+ Arg := Container_Arg;
+ end if;
- -- Rewrite domain of iteration as a call to the default iterator
- -- for the container type.
+ Rewrite (Name (I_Spec),
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (Default_Iter, Loc),
+ Parameter_Associations => New_List (Arg)));
+ end;
- 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);
+ Ent := First_Entity (Iter_Pack);
while Present (Ent) loop
if Chars (Ent) = Name_Cursor then
Set_Etype (Cursor, Etype (Ent));
Make_Object_Renaming_Declaration (Loc,
Defining_Identifier => Id,
Subtype_Mark =>
- New_Occurrence_Of (Element_Type, Loc),
+ New_Occurrence_Of (Elem_Typ, Loc),
Name =>
Make_Explicit_Dereference (Loc,
Prefix =>
Make_Object_Renaming_Declaration (Loc,
Defining_Identifier => Id,
Subtype_Mark =>
- New_Occurrence_Of (Element_Type, Loc),
+ New_Occurrence_Of (Elem_Typ, Loc),
Name =>
Make_Indexed_Component (Loc,
Prefix => Relocate_Node (Container_Arg),
New_List (New_Occurrence_Of (Cursor, Loc))));
end if;
- -- The defining identifier in the iterator is user-visible
- -- and must be visible in the debugger.
+ -- The defining identifier in the iterator is user-visible and
+ -- must be visible in the debugger.
Set_Debug_Info_Needed (Id);
Prepend_To (Stats, Decl);
end Handle_Of;
- -- X in Iterate (S) : type of iterator is type of explicitly
- -- given Iterate function, and the loop variable is the cursor.
- -- It will be assigned in the loop and must be a variable.
+ -- X in Iterate (S) : type of iterator is type of explicitly given
+ -- Iterate function, and the loop variable is the cursor. It will be
+ -- assigned in the loop and must be a variable.
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.
+
+ Iter_Pack := Scope (Root_Type (Etype (Iter_Type)));
Cursor := Id;
end if;
Iterator := Make_Temporary (Loc, 'I');
- -- For both iterator forms, add a call to the step operation to
- -- advance the cursor. Generate:
+ -- For both iterator forms, add a call to the step operation to advance
+ -- the cursor. Generate:
-- Cursor := Iterator.Next (Cursor);
if Present (Fast_Element_Access_Op) and then Present (Fast_Step_Op) then
declare
- Step_Call : Node_Id;
Curs_Name : constant Node_Id := New_Occurrence_Of (Cursor, Loc);
+ Step_Call : Node_Id;
+
begin
Step_Call :=
Make_Procedure_Call_Statement (Loc,
Condition =>
Make_Function_Call (Loc,
Name =>
- New_Occurrence_Of (
- Next_Entity (First_Entity (Pack)), Loc),
- Parameter_Associations =>
- New_List (New_Occurrence_Of (Cursor, Loc)))),
+ New_Occurrence_Of
+ (Next_Entity (First_Entity (Iter_Pack)), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of (Cursor, Loc)))),
Statements => Stats,
End_Label => Empty);
- -- If present, preserve identifier of loop, which can be used in
- -- an exit statement in the body.
+ -- If present, preserve identifier of loop, which can be used in an exit
+ -- statement in the body.
if Present (Identifier (N)) then
Set_Identifier (New_Loop, Relocate_Node (Identifier (N)));
Insert_Action (N,
Make_Object_Renaming_Declaration (Loc,
Defining_Identifier => Iterator,
- Subtype_Mark => New_Occurrence_Of (Iter_Type, Loc),
- Name => Relocate_Node (Name (I_Spec))));
+ Subtype_Mark => New_Occurrence_Of (Iter_Type, Loc),
+ Name => Relocate_Node (Name (I_Spec))));
-- Create declaration for cursor
declare
Cursor_Decl : constant Node_Id :=
- Make_Object_Declaration (Loc,
- Defining_Identifier => Cursor,
- Object_Definition =>
- New_Occurrence_Of (Etype (Cursor), Loc),
- Expression =>
- Make_Selected_Component (Loc,
- Prefix => New_Occurrence_Of (Iterator, Loc),
- Selector_Name =>
- Make_Identifier (Loc, Name_Init)));
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Cursor,
+ Object_Definition =>
+ New_Occurrence_Of (Etype (Cursor), Loc),
+ Expression =>
+ Make_Selected_Component (Loc,
+ Prefix =>
+ New_Occurrence_Of (Iterator, Loc),
+ Selector_Name =>
+ Make_Identifier (Loc, Name_Init)));
begin
-- The cursor is only modified in expanded code, so it appears
Set_Assignment_OK (Cursor_Decl);
Insert_Action (N, Cursor_Decl);
- Set_Ekind (Cursor, I_Kind);
+ Set_Ekind (Cursor, Id_Kind);
end;
-- If the range of iteration is given by a function call that returns
-- Entity for argument of separate Predicate procedure when exceptions
-- are present in expression.
- FDecl : Node_Id;
- -- The function declaration.
+ FDecl : Node_Id;
+ -- The function declaration
- SId : Entity_Id;
- -- Its entity.
+ SId : Entity_Id;
+ -- Its entity
Raise_Expression_Present : Boolean := False;
-- Set True if Expr has at least one Raise_Expression
Add_Call (Atyp);
end if;
end;
+
-- Add Predicates for the current type
Add_Predicates;
Insert_Before_And_Analyze (N, FDecl);
end if;
- Insert_After_And_Analyze (N, FBody);
+ Insert_After_And_Analyze (N, FBody);
-- Static predicate functions are always side-effect free, and
-- in most cases dynamic predicate functions are as well. Mark
Loc : constant Source_Ptr := Sloc (Typ);
Object_Entity : constant Entity_Id :=
- Make_Defining_Identifier (Loc, Chars => New_Internal_Name ('I'));
+ Make_Defining_Identifier (Loc,
+ Chars => New_Internal_Name ('I'));
-- The formal parameter of the function
then
Find_Selected_Component (Parent (N));
end if;
+
return Skip;
- elsif Nkind (N) = N_Identifier and then Chars (N) /= Chars (E) then
+ elsif Nkind (N) = N_Identifier and then Chars (N) /= Chars (E) then
Find_Direct_Name (N);
Set_Entity (N, Empty);
end if;
procedure Resolve_Aspect_Expression is new Traverse_Proc (Resolve_Name);
+ -- Start of processing for Resolve_Aspect_Expressions
+
begin
ASN := First_Rep_Item (E);
while Present (ASN) loop
-- subprograms, or that may mention current instances of
-- types. These will require special handling (???TBD).
- when Aspect_Predicate |
+ when Aspect_Predicate |
Aspect_Predicate_Failure |
Aspect_Invariant =>
null;
when Aspect_Static_Predicate |
Aspect_Dynamic_Predicate =>
- -- build predicate function specification and preanalyze
+ -- Build predicate function specification and preanalyze
-- expression after type replacement.
if No (Predicate_Function (E)) then
declare
FDecl : constant Node_Id :=
- Build_Predicate_Function_Declaration (E);
+ Build_Predicate_Function_Declaration (E);
pragma Unreferenced (FDecl);
begin
Resolve_Aspect_Expression (Expr);