[multiple changes]

2010-10-22  Robert Dewar  <dewar@adacore.com>

	* sem_util.ads, sem_util.adb, sem_aux.ads, sem_aux.adb
	(Is_Generic_Formal): Moved from Sem_Util to Sem_Aux.

2010-10-22  Ed Schonberg  <schonberg@adacore.com>

	* exp_ch5.adb (Expand_Iterator_Loop): New subprogram, implements new
	iterator forms over arrays and containers, in loops and quantified
	expressions.
	* exp_util.adb (Insert_Actions): include N_Iterator_Specification.
	* par-ch4.adb (P_Quantified_Expression): Handle iterator specifications.
	* par-ch5.adb (P_Iterator_Specification): New subprogram. Modify
	P_Iteration_Scheme to handle both loop forms.
	* sem.adb: Handle N_Iterator_Specification.
	* sem_ch5.adb, sem_ch5.ads (Analyze_Iterator_Specification): New
	subprogram.
	* sinfo.adb, sinfo.ads: New node N_Iterator_Specification.
	N_Iteration_Scheme can now include an Iterator_Specification. Ditto
	for N_Quantified_Expression.
	* snames.ads-tmpl: Add names Cursor, Element, Element_Type, No_Element,
	and Previous, to support iterators over predefined containers.
	* sprint.adb: Handle N_Iterator_Specification.

From-SVN: r165811
This commit is contained in:
Arnaud Charlet 2010-10-22 11:36:41 +02:00
parent c3ad80f000
commit 57d62f0cb7
16 changed files with 557 additions and 35 deletions

View File

@ -1,3 +1,27 @@
2010-10-22 Robert Dewar <dewar@adacore.com>
* sem_util.ads, sem_util.adb, sem_aux.ads, sem_aux.adb
(Is_Generic_Formal): Moved from Sem_Util to Sem_Aux.
2010-10-22 Ed Schonberg <schonberg@adacore.com>
* exp_ch5.adb (Expand_Iterator_Loop): New subprogram, implements new
iterator forms over arrays and containers, in loops and quantified
expressions.
* exp_util.adb (Insert_Actions): include N_Iterator_Specification.
* par-ch4.adb (P_Quantified_Expression): Handle iterator specifications.
* par-ch5.adb (P_Iterator_Specification): New subprogram. Modify
P_Iteration_Scheme to handle both loop forms.
* sem.adb: Handle N_Iterator_Specification.
* sem_ch5.adb, sem_ch5.ads (Analyze_Iterator_Specification): New
subprogram.
* sinfo.adb, sinfo.ads: New node N_Iterator_Specification.
N_Iteration_Scheme can now include an Iterator_Specification. Ditto
for N_Quantified_Expression.
* snames.ads-tmpl: Add names Cursor, Element, Element_Type, No_Element,
and Previous, to support iterators over predefined containers.
* sprint.adb: Handle N_Iterator_Specification.
2010-10-22 Thomas Quinot <quinot@adacore.com>
* sem_prag.adb, sem_ch12.adb, sem_util.adb, sem_util.ads

View File

@ -103,6 +103,10 @@ package body Exp_Ch5 is
-- clause (this last case is required because holes in the tagged type
-- might be filled with components from child types).
procedure Expand_Iterator_Loop (N : Node_Id);
-- Expand loops over arrays and containers that use the form "for X of C"
-- with an optional subtype mark, and "for Y in C".
function Make_Tag_Ctrl_Assignment (N : Node_Id) return List_Id;
-- Generate the necessary code for controlled and tagged assignment, that
-- is to say, finalization of the target before, adjustment of the target
@ -2747,6 +2751,201 @@ package body Exp_Ch5 is
end if;
end Expand_N_If_Statement;
--------------------------
-- Expand_Iterator_Loop --
--------------------------
procedure Expand_Iterator_Loop (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Isc : constant Node_Id := Iteration_Scheme (N);
I_Spec : constant Node_Id := Iterator_Specification (Isc);
Id : constant Entity_Id := Defining_Identifier (I_Spec);
Container : constant Entity_Id := Entity (Name (I_Spec));
Typ : constant Entity_Id := Etype (Container);
Cursor : Entity_Id;
New_Loop : Node_Id;
Stats : List_Id;
begin
if Is_Array_Type (Typ) then
if Of_Present (I_Spec) then
Cursor := Make_Temporary (Loc, 'C');
-- For Elem of Arr loop ..
declare
Decl : constant Node_Id :=
Make_Object_Renaming_Declaration (Loc,
Defining_Identifier => Id,
Subtype_Mark =>
New_Occurrence_Of (Component_Type (Typ), Loc),
Name => Make_Indexed_Component (Loc,
Prefix => New_Occurrence_Of (Container, Loc),
Expressions =>
New_List (New_Occurrence_Of (Cursor, Loc))));
begin
Stats := Statements (N);
Prepend (Decl, Stats);
New_Loop := Make_Loop_Statement (Loc,
Iteration_Scheme =>
Make_Iteration_Scheme (Loc,
Loop_Parameter_Specification =>
Make_Loop_Parameter_Specification (Loc,
Defining_Identifier => Cursor,
Discrete_Subtype_Definition =>
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Container, Loc),
Attribute_Name => Name_Range),
Reverse_Present => Reverse_Present (I_Spec))),
Statements => Stats,
End_Label => Empty);
end;
else
-- For Index in Array loop
--
-- The cursor (index into the array) is the source Id.
Cursor := Id;
New_Loop := Make_Loop_Statement (Loc,
Iteration_Scheme =>
Make_Iteration_Scheme (Loc,
Loop_Parameter_Specification =>
Make_Loop_Parameter_Specification (Loc,
Defining_Identifier => Cursor,
Discrete_Subtype_Definition =>
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Container, Loc),
Attribute_Name => Name_Range),
Reverse_Present => Reverse_Present (I_Spec))),
Statements => Statements (N),
End_Label => Empty);
end if;
else
-- Iterators over containers. In both cases these require a
-- cursor of the proper type.
-- Cursor : P.Cursor_Type := Container.First;
-- while Cursor /= P.No_Element loop
-- -- for the "of" form, the element name renames
-- -- the element denoted by the cursor.
-- Obj : P.Element_Type renames Element (Cursor);
-- Statements;
-- P.Next (Cursor);
-- end loop;
--
-- with the obvious replacements if "reverse" is specified.
declare
Element_Type : constant Entity_Id := Etype (Id);
Pack : constant Entity_Id := Scope (Etype (Container));
Name_Init : Name_Id;
Name_Step : Name_Id;
Cond : Node_Id;
Cursor_Decl : Node_Id;
Renaming_Decl : Node_Id;
begin
Stats := Statements (N);
if Of_Present (I_Spec) then
Cursor := Make_Temporary (Loc, 'C');
else
Cursor := Id;
end if;
if Reverse_Present (I_Spec) then
-- Must verify that the container has a reverse iterator ???
Name_Init := Name_Last;
Name_Step := Name_Previous;
else
Name_Init := Name_First;
Name_Step := Name_Next;
end if;
-- C : Cursor_Type := Container.First;
Cursor_Decl := Make_Object_Declaration (Loc,
Defining_Identifier => Cursor,
Object_Definition =>
Make_Selected_Component (Loc,
Prefix => New_Occurrence_Of (Pack, Loc),
Selector_Name =>
Make_Identifier (Loc, Name_Cursor)),
Expression =>
Make_Selected_Component (Loc,
Prefix => New_Occurrence_Of (Container, Loc),
Selector_Name => Make_Identifier (Loc, Name_Init)));
Insert_Action (N, Cursor_Decl);
-- while C /= No_Element loop
Cond := Make_Op_Ne (Loc,
Left_Opnd => New_Occurrence_Of (Cursor, Loc),
Right_Opnd => Make_Selected_Component (Loc,
Prefix => New_Occurrence_Of (Pack, Loc),
Selector_Name => Make_Identifier (Loc,
Chars => Name_No_Element)));
if Of_Present (I_Spec) then
-- Id : Element_Type renames Pack.Element (Cursor);
Renaming_Decl :=
Make_Object_Renaming_Declaration (Loc,
Defining_Identifier => Id,
Subtype_Mark => New_Occurrence_Of (Element_Type, Loc),
Name => Make_Indexed_Component (Loc,
Prefix =>
Make_Selected_Component (Loc,
Prefix => New_Occurrence_Of (Pack, Loc),
Selector_Name =>
Make_Identifier (Loc, Chars => Name_Element)),
Expressions =>
New_List (New_Occurrence_Of (Cursor, Loc))));
Prepend (Renaming_Decl, Stats);
end if;
-- For both iterator forms, add call to Next to advance cursor.
Append_To (Stats,
Make_Procedure_Call_Statement (Loc,
Name => Make_Selected_Component (Loc,
Prefix => New_Occurrence_Of (Pack, Loc),
Selector_Name => Make_Identifier (Loc, Name_Step)),
Parameter_Associations =>
New_List (New_Occurrence_Of (Cursor, Loc))));
New_Loop := Make_Loop_Statement (Loc,
Iteration_Scheme =>
Make_Iteration_Scheme (Loc,
Condition => Cond),
Statements => Stats,
End_Label => Empty);
end;
end if;
-- Set_Analyzed (I_Spec);
Rewrite (N, New_Loop);
Analyze (N);
end Expand_Iterator_Loop;
-----------------------------
-- Expand_N_Loop_Statement --
-----------------------------
@ -2755,7 +2954,8 @@ package body Exp_Ch5 is
-- 2. Deal with while condition for C/Fortran boolean
-- 3. Deal with loops with a non-standard enumeration type range
-- 4. Deal with while loops where Condition_Actions is set
-- 5. Insert polling call if required
-- 5. Deal with loops with iterators over arrays and containers
-- 6. Insert polling call if required
procedure Expand_N_Loop_Statement (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
@ -2955,6 +3155,11 @@ package body Exp_Ch5 is
Analyze (N);
end;
elsif Present (Isc)
and then Present (Iterator_Specification (Isc))
then
Expand_Iterator_Loop (N);
end if;
end Expand_N_Loop_Statement;

View File

@ -2828,6 +2828,7 @@ package body Exp_Util is
N_Index_Or_Discriminant_Constraint |
N_Indexed_Component |
N_Integer_Literal |
N_Iterator_Specification |
N_Itype_Reference |
N_Label |
N_Loop_Parameter_Specification |

View File

@ -2514,7 +2514,8 @@ package body Ch4 is
-- for QUANTIFIER ITERATOR_SPECIFICATION => PREDICATE
function P_Quantified_Expression return Node_Id is
Node1 : Node_Id;
I_Spec : Node_Id;
Node1 : Node_Id;
begin
Scan; -- past FOR
@ -2536,7 +2537,13 @@ package body Ch4 is
end if;
Scan;
Set_Loop_Parameter_Specification (Node1, P_Loop_Parameter_Specification);
I_Spec := P_Loop_Parameter_Specification;
if Nkind (I_Spec) = N_Loop_Parameter_Specification then
Set_Loop_Parameter_Specification (Node1, I_Spec);
else
Set_Iterator_Specification (Node1, I_Spec);
end if;
if Token = Tok_Arrow then
Scan;

View File

@ -60,6 +60,11 @@ package body Ch5 is
-- the N_Identifier node for the label on the loop. If Loop_Name is
-- Empty on entry (the default), then the for statement is unlabeled.
function P_Iterator_Specification (Def_Id : Node_Id) return Node_Id;
-- Parse an iterator specification. The defining identifier has already
-- been scanned, as it is the common prefix between loop and iterator
-- specification.
function P_Loop_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
-- Parse loop statement. If Loop_Name is non-Empty on entry, it is
-- the N_Identifier node for the label on the loop. If Loop_Name is
@ -1552,6 +1557,7 @@ package body Ch5 is
Iter_Scheme_Node : Node_Id;
Loop_For_Flag : Boolean;
Created_Name : Node_Id;
Spec : Node_Id;
begin
Push_Scope_Stack;
@ -1563,8 +1569,13 @@ package body Ch5 is
Loop_For_Flag := (Prev_Token = Tok_Loop);
Scan; -- past FOR
Iter_Scheme_Node := New_Node (N_Iteration_Scheme, Token_Ptr);
Set_Loop_Parameter_Specification
(Iter_Scheme_Node, P_Loop_Parameter_Specification);
Spec := P_Loop_Parameter_Specification;
if Nkind (Spec) = N_Loop_Parameter_Specification then
Set_Loop_Parameter_Specification
(Iter_Scheme_Node, Spec);
else
Set_Iterator_Specification (Iter_Scheme_Node, Spec);
end if;
-- The following is a special test so that a miswritten for loop such
-- as "loop for I in 1..10;" is handled nicely, without making an extra
@ -1686,11 +1697,27 @@ package body Ch5 is
Scan_State : Saved_Scan_State;
begin
Loop_Param_Specification_Node :=
New_Node (N_Loop_Parameter_Specification, Token_Ptr);
Save_Scan_State (Scan_State);
ID_Node := P_Defining_Identifier (C_In);
-- If the next token is OF it indicates the Ada2012 iterator. If the
-- next token is a colon, the iterator includes a subtype indication
-- for the bound variable of the iteration. Otherwise we parse the
-- construct as a loop parameter specification. Note that the form:
-- "for A in B" is ambiguous, and must be resolved semantically: if B
-- is a discrete subtype this is a loop specification, but if it is an
-- expression it is an iterator specification. Ambiguity is resolved
-- during analysis of the loop parameter specification.
if Token = Tok_Of
or else Token = Tok_Colon
then
return P_Iterator_Specification (ID_Node);
end if;
Loop_Param_Specification_Node :=
New_Node (N_Loop_Parameter_Specification, Token_Ptr);
Set_Defining_Identifier (Loop_Param_Specification_Node, ID_Node);
if Token = Tok_Left_Paren then
@ -1720,6 +1747,40 @@ package body Ch5 is
return Error;
end P_Loop_Parameter_Specification;
----------------------------------
-- 5.5.1 Iterator_Specification --
----------------------------------
function P_Iterator_Specification (Def_Id : Node_Id) return Node_Id is
Node1 : Node_Id;
begin
Node1 := New_Node (N_Iterator_Specification, Token_Ptr);
Set_Defining_Identifier (Node1, Def_Id);
if Token = Tok_Colon then
Scan; -- past :
Set_Subtype_Indication (Node1, P_Subtype_Indication);
end if;
if Token = Tok_Of then
Set_Of_Present (Node1);
Scan; -- past OF
elsif Token = Tok_In then
Scan; -- past IN
else
return Error;
end if;
if Token = Tok_Reverse then
Scan; -- past REVERSE
Set_Reverse_Present (Node1, True);
end if;
Set_Name (Node1, P_Name);
return Node1;
end P_Iterator_Specification;
--------------------------
-- 5.6 Block Statement --
--------------------------

View File

@ -302,6 +302,9 @@ package body Sem is
when N_Integer_Literal =>
Analyze_Integer_Literal (N);
when N_Iterator_Specification =>
Analyze_Iterator_Specification (N);
when N_Itype_Reference =>
Analyze_Itype_Reference (N);

View File

@ -537,6 +537,25 @@ package body Sem_Aux is
end if;
end Is_Derived_Type;
-----------------------
-- Is_Generic_Formal --
-----------------------
function Is_Generic_Formal (E : Entity_Id) return Boolean is
Kind : Node_Kind;
begin
if No (E) then
return False;
else
Kind := Nkind (Parent (E));
return
Nkind_In (Kind, N_Formal_Object_Declaration,
N_Formal_Package_Declaration,
N_Formal_Type_Declaration)
or else Is_Formal_Subprogram (E);
end if;
end Is_Generic_Formal;
---------------------------
-- Is_Indefinite_Subtype --
---------------------------

View File

@ -159,6 +159,11 @@ package Sem_Aux is
-- Determines if the given entity Ent is a derived type. Result is always
-- false if argument is not a type.
function Is_Generic_Formal (E : Entity_Id) return Boolean;
-- Determine whether E is a generic formal parameter. In particular this is
-- used to set the visibility of generic formals of a generic package
-- declared with a box or with partial parametrization.
function Is_Indefinite_Subtype (Ent : Entity_Id) return Boolean;
-- Ent is any entity. Determines if given entity is an unconstrained array
-- type or subtype, a discriminated record type or subtype with no initial

View File

@ -1734,6 +1734,10 @@ package body Sem_Ch5 is
-- Start of processing for Analyze_Iteration_Scheme
begin
if Analyzed (N) then
return;
end if;
-- For an infinite loop, there is no iteration scheme
if No (N) then
@ -1753,6 +1757,9 @@ package body Sem_Ch5 is
Set_Current_Value_Condition (N);
return;
elsif Present (Iterator_Specification (N)) then
Analyze_Iterator_Specification (Iterator_Specification (N));
-- Else we have a FOR loop
else
@ -1795,6 +1802,31 @@ package body Sem_Ch5 is
Process_Bounds (DS);
else
Analyze (DS);
if Nkind (DS) = N_Function_Call
or else
(Is_Entity_Name (DS)
and then not Is_Type (Entity (DS)))
then
-- this is an iterator specification. Rewrite as
-- such and analyze.
declare
I_Spec : constant Node_Id :=
Make_Iterator_Specification (Sloc (LP),
Defining_Identifier => Relocate_Node (Id),
Name => Relocate_Node (DS),
Subtype_Indication => Empty,
Reverse_Present => Reverse_Present (LP));
begin
Set_Iterator_Specification (N, I_Spec);
Set_Loop_Parameter_Specification (N, Empty);
Analyze_Iterator_Specification (I_Spec);
return;
end;
end if;
end if;
if DS = Error then
@ -1938,6 +1970,73 @@ package body Sem_Ch5 is
end if;
end Analyze_Iteration_Scheme;
-------------------------------------
-- Analyze_Iterator_Specification --
-------------------------------------
procedure Analyze_Iterator_Specification (N : Node_Id) is
Def_Id : constant Node_Id := Defining_Identifier (N);
Subt : constant Node_Id := Subtype_Indication (N);
Container : constant Node_Id := Name (N);
Ent : Entity_Id;
Typ : Entity_Id;
begin
Enter_Name (Def_Id);
Set_Ekind (Def_Id, E_Variable);
if Present (Subt) then
Analyze (Subt);
end if;
Analyze_And_Resolve (Container);
Typ := Etype (Container);
if Is_Array_Type (Typ) then
if Of_Present (N) then
Set_Etype (Def_Id, Component_Type (Typ));
else
Set_Etype (Def_Id, Etype (First_Index (Typ)));
end if;
else
-- Iteration over a container.
Set_Ekind (Def_Id, E_Loop_Parameter);
if Of_Present (N) then
-- Find the Element_Type in the package instance that defines
-- the container type.
Ent := First_Entity (Scope (Typ));
while Present (Ent) loop
if Chars (Ent) = Name_Element_Type then
Set_Etype (Def_Id, Ent);
exit;
end if;
Next_Entity (Ent);
end loop;
else
-- Find the Cursor type in similar fashion.
Ent := First_Entity (Scope (Typ));
while Present (Ent) loop
if Chars (Ent) = Name_Cursor then
Set_Etype (Def_Id, Ent);
exit;
end if;
Next_Entity (Ent);
end loop;
end if;
end if;
end Analyze_Iterator_Specification;
-------------------
-- Analyze_Label --
-------------------

View File

@ -34,6 +34,7 @@ package Sem_Ch5 is
procedure Analyze_Goto_Statement (N : Node_Id);
procedure Analyze_If_Statement (N : Node_Id);
procedure Analyze_Implicit_Label_Declaration (N : Node_Id);
procedure Analyze_Iterator_Specification (N : Node_Id);
procedure Analyze_Iteration_Scheme (N : Node_Id);
procedure Analyze_Label (N : Node_Id);
procedure Analyze_Loop_Statement (N : Node_Id);

View File

@ -6559,25 +6559,6 @@ package body Sem_Util is
end if;
end Is_Fully_Initialized_Variant;
-----------------------
-- Is_Generic_Formal --
-----------------------
function Is_Generic_Formal (E : Entity_Id) return Boolean is
Kind : Node_Kind;
begin
if No (E) then
return False;
else
Kind := Nkind (Parent (E));
return
Nkind_In (Kind, N_Formal_Object_Declaration,
N_Formal_Package_Declaration,
N_Formal_Type_Declaration)
or else Is_Formal_Subprogram (E);
end if;
end Is_Generic_Formal;
------------
-- Is_LHS --
------------

View File

@ -733,11 +733,6 @@ package Sem_Util is
-- means that the result returned is not crucial, but should err on the
-- side of thinking things are fully initialized if it does not know.
function Is_Generic_Formal (E : Entity_Id) return Boolean;
-- Determine whether E is a generic formal parameter. In particular this is
-- used to set the visibility of generic formals of a generic package
-- declared with a box or with partial parametrization.
function Is_Inherited_Operation (E : Entity_Id) return Boolean;
-- E is a subprogram. Return True is E is an implicit operation inherited
-- by a derived type declarations.

View File

@ -744,6 +744,7 @@ package body Sinfo is
or else NT (N).Nkind = N_Full_Type_Declaration
or else NT (N).Nkind = N_Implicit_Label_Declaration
or else NT (N).Nkind = N_Incomplete_Type_Declaration
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Loop_Parameter_Specification
or else NT (N).Nkind = N_Number_Declaration
or else NT (N).Nkind = N_Object_Declaration
@ -1866,6 +1867,15 @@ package body Sinfo is
return Node2 (N);
end Iteration_Scheme;
function Iterator_Specification
(N : Node_Id) return Node_Id is
begin
pragma Assert (False
or else NT (N).Nkind = N_Iteration_Scheme
or else NT (N).Nkind = N_Quantified_Expression);
return Node2 (N);
end Iterator_Specification;
function Itype
(N : Node_Id) return Node_Id is
begin
@ -2086,6 +2096,7 @@ package body Sinfo is
or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
or else NT (N).Nkind = N_Goto_Statement
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Object_Renaming_Declaration
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Package_Renaming_Declaration
@ -2270,6 +2281,14 @@ package body Sinfo is
return Node4 (N);
end Object_Definition;
function Of_Present
(N : Node_Id) return Boolean is
begin
pragma Assert (False
or else NT (N).Nkind = N_Iterator_Specification);
return Flag16 (N);
end Of_Present;
function Original_Discriminant
(N : Node_Id) return Node_Id is
begin
@ -2630,6 +2649,7 @@ package body Sinfo is
(N : Node_Id) return Boolean is
begin
pragma Assert (False
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Loop_Parameter_Specification);
return Flag15 (N);
end Reverse_Present;
@ -2825,6 +2845,7 @@ package body Sinfo is
or else NT (N).Nkind = N_Access_To_Object_Definition
or else NT (N).Nkind = N_Component_Definition
or else NT (N).Nkind = N_Derived_Type_Definition
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Private_Extension_Declaration
or else NT (N).Nkind = N_Subtype_Declaration);
return Node5 (N);
@ -3742,6 +3763,7 @@ package body Sinfo is
or else NT (N).Nkind = N_Full_Type_Declaration
or else NT (N).Nkind = N_Implicit_Label_Declaration
or else NT (N).Nkind = N_Incomplete_Type_Declaration
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Loop_Parameter_Specification
or else NT (N).Nkind = N_Number_Declaration
or else NT (N).Nkind = N_Object_Declaration
@ -4856,6 +4878,15 @@ package body Sinfo is
Set_Node2_With_Parent (N, Val);
end Set_Iteration_Scheme;
procedure Set_Iterator_Specification
(N : Node_Id; Val : Node_Id) is
begin
pragma Assert (False
or else NT (N).Nkind = N_Iteration_Scheme
or else NT (N).Nkind = N_Quantified_Expression);
Set_Node2_With_Parent (N, Val);
end Set_Iterator_Specification;
procedure Set_Itype
(N : Node_Id; Val : Entity_Id) is
begin
@ -5076,6 +5107,7 @@ package body Sinfo is
or else NT (N).Nkind = N_Generic_Package_Renaming_Declaration
or else NT (N).Nkind = N_Generic_Procedure_Renaming_Declaration
or else NT (N).Nkind = N_Goto_Statement
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Object_Renaming_Declaration
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Package_Renaming_Declaration
@ -5260,6 +5292,14 @@ package body Sinfo is
Set_Node4_With_Parent (N, Val);
end Set_Object_Definition;
procedure Set_Of_Present
(N : Node_Id; Val : Boolean := True) is
begin
pragma Assert (False
or else NT (N).Nkind = N_Iterator_Specification);
Set_Flag16 (N, Val);
end Set_Of_Present;
procedure Set_Original_Discriminant
(N : Node_Id; Val : Node_Id) is
begin
@ -5620,6 +5660,7 @@ package body Sinfo is
(N : Node_Id; Val : Boolean := True) is
begin
pragma Assert (False
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Loop_Parameter_Specification);
Set_Flag15 (N, Val);
end Set_Reverse_Present;
@ -5815,6 +5856,7 @@ package body Sinfo is
or else NT (N).Nkind = N_Access_To_Object_Definition
or else NT (N).Nkind = N_Component_Definition
or else NT (N).Nkind = N_Derived_Type_Definition
or else NT (N).Nkind = N_Iterator_Specification
or else NT (N).Nkind = N_Private_Extension_Declaration
or else NT (N).Nkind = N_Subtype_Declaration);
Set_Node5_With_Parent (N, Val);

View File

@ -1544,6 +1544,10 @@ package Sinfo is
-- is used for properly setting out of range values for use by pragmas
-- Initialize_Scalars and Normalize_Scalars.
-- Of_Present (Flag16)
-- Present in N_Iterastor_Specification nodes, to mark the Ada2012 iterator
-- form over arrays and containers.
-- Original_Discriminant (Node2-Sem)
-- Present in identifiers. Used in references to discriminants that
-- appear in generic units. Because the names of the discriminants may be
@ -3829,6 +3833,7 @@ package Sinfo is
-- N_Quantified_Expression
-- Sloc points to FOR
-- Iterator_Specification (Node2) (set to Empty if not Present)
-- Loop_Parameter_Specification (Node4)
-- Condition (Node1)
-- All_Present (Flag15)
@ -4164,7 +4169,11 @@ package Sinfo is
--------------------------
-- ITERATION_SCHEME ::=
-- while CONDITION | for LOOP_PARAMETER_SPECIFICATION
-- while CONDITION | for LOOP_PARAMETER_SPECIFICATION |
-- for ITERATOR_SPECIFICATION
-- Only one of (Iterator_Specification, Loop_Parameter_Specification)
-- is present at a time, the other one is empty.
-- Gigi restriction: This expander ensures that the type of the
-- Condition field is always Standard.Boolean, even if the type
@ -4174,6 +4183,7 @@ package Sinfo is
-- Sloc points to WHILE or FOR
-- Condition (Node1) (set to Empty if FOR case)
-- Condition_Actions (List3-Sem)
-- Iterator_Specification (Node2) (set to Empty if not Present)
-- Loop_Parameter_Specification (Node4) (set to Empty if WHILE case)
---------------------------------------
@ -4189,6 +4199,22 @@ package Sinfo is
-- Reverse_Present (Flag15)
-- Discrete_Subtype_Definition (Node4)
----------------------------------
-- 5.5.1 Iterator specification --
----------------------------------
-- ITERATOR_SPECIFICATION ::=
-- DEFINING_IDENTIFIER in [reverse] NAME
-- DEFINING_IDENTIFIER [: SUBTYPE_INDICATION] of [reverse] NAME
-- N_Iterator_Specification
-- Sloc points to defining identifier
-- Defining_Identifier (Node1)
-- Name (Node2)
-- Reverse_Present (Flag15)
-- Of_Present (Flag16)
-- Subtype_Indication (Node5)
--------------------------
-- 5.6 Block Statement --
--------------------------
@ -7500,6 +7526,7 @@ package Sinfo is
N_Formal_Type_Declaration,
N_Full_Type_Declaration,
N_Incomplete_Type_Declaration,
N_Iterator_Specification,
N_Loop_Parameter_Specification,
N_Object_Declaration,
N_Parameterized_Expression,
@ -8492,6 +8519,9 @@ package Sinfo is
function Iteration_Scheme
(N : Node_Id) return Node_Id; -- Node2
function Iterator_Specification
(N : Node_Id) return Node_Id; -- Node2
function Itype
(N : Node_Id) return Entity_Id; -- Node1
@ -8612,6 +8642,9 @@ package Sinfo is
function Object_Definition
(N : Node_Id) return Node_Id; -- Node4
function Of_Present
(N : Node_Id) return Boolean; -- Flag16
function Original_Discriminant
(N : Node_Id) return Node_Id; -- Node2
@ -9446,6 +9479,9 @@ package Sinfo is
procedure Set_Iteration_Scheme
(N : Node_Id; Val : Node_Id); -- Node2
procedure Set_Iterator_Specification
(N : Node_Id; Val : Node_Id); -- Node2
procedure Set_Itype
(N : Node_Id; Val : Entity_Id); -- Node1
@ -9566,6 +9602,9 @@ package Sinfo is
procedure Set_Object_Definition
(N : Node_Id; Val : Node_Id); -- Node4
procedure Set_Of_Present
(N : Node_Id; Val : Boolean := True); -- Flag16
procedure Set_Original_Discriminant
(N : Node_Id; Val : Node_Id); -- Node2
@ -10492,7 +10531,7 @@ package Sinfo is
N_Quantified_Expression =>
(1 => True, -- Condition (Node1)
2 => False, -- unused
2 => True, -- Iterator_Specification
3 => False, -- unused
4 => True, -- Loop_Parameter_Specification (Node4)
5 => False), -- Etype (Node5-Sem)
@ -10576,7 +10615,7 @@ package Sinfo is
N_Iteration_Scheme =>
(1 => True, -- Condition (Node1)
2 => False, -- unused
2 => True, -- Iterator_Specification (Node2)
3 => False, -- Condition_Actions (List3-Sem)
4 => True, -- Loop_Parameter_Specification (Node4)
5 => False), -- unused
@ -10588,6 +10627,13 @@ package Sinfo is
4 => True, -- Discrete_Subtype_Definition (Node4)
5 => False), -- unused
N_Iterator_Specification =>
(1 => True, -- Defining_Identifier (Node1)
2 => True, -- Name (Node2)
3 => False, -- Unused
4 => False, -- Unused
5 => True), -- Subtype_Indication (Node5)
N_Block_Statement =>
(1 => True, -- Identifier (Node1)
2 => True, -- Declarations (List2)

View File

@ -1198,6 +1198,14 @@ package Snames is
Name_Unaligned_Valid : constant Name_Id := N + $;
-- Names used to implement iterators over predefined containers.
Name_Cursor : constant Name_Id := N + $;
Name_Element : constant Name_Id := N + $;
Name_Element_Type : constant Name_Id := N + $;
Name_No_Element : constant Name_Id := N + $;
Name_Previous : constant Name_Id := N + $;
-- Ada 05 reserved words
First_2005_Reserved_Word : constant Name_Id := N + $;

View File

@ -1995,11 +1995,36 @@ package body Sprint is
Sprint_Node (Condition (Node));
else
Write_Str_With_Col_Check_Sloc ("for ");
Sprint_Node (Loop_Parameter_Specification (Node));
if Present (Iterator_Specification (Node)) then
Sprint_Node (Iterator_Specification (Node));
else
Sprint_Node (Loop_Parameter_Specification (Node));
end if;
end if;
Write_Char (' ');
when N_Iterator_Specification =>
Set_Debug_Sloc;
Write_Id (Defining_Identifier (Node));
if Present (Subtype_Indication (Node)) then
Write_Str_With_Col_Check (" : ");
Sprint_Node (Subtype_Indication (Node));
end if;
if Of_Present (Node) then
Write_Str_With_Col_Check (" of ");
else
Write_Str_With_Col_Check (" in ");
end if;
if Reverse_Present (Node) then
Write_Str_With_Col_Check ("reverse ");
end if;
Sprint_Node (Name (Node));
when N_Itype_Reference =>
Write_Indent_Str_Sloc ("reference ");
Write_Id (Itype (Node));