===================================================================
@@ -1678,11 +1678,17 @@
Set_Etype (Ent, Standard_Void_Type);
Set_Parent (Ent, Parent (N));
- Enter_Name (Id);
- Set_Etype (Id, Index_Typ);
- Set_Ekind (Id, E_Variable);
- Set_Scope (Id, Ent);
+ -- Decorate the index variable in the current scope. The association
+ -- may have several choices, each one leading to a loop, so we create
+ -- this variable only once to prevent homonyms in this scope.
+ if No (Scope (Id)) then
+ Enter_Name (Id);
+ Set_Etype (Id, Index_Typ);
+ Set_Ekind (Id, E_Variable);
+ Set_Scope (Id, Ent);
+ end if;
+
Push_Scope (Ent);
Dummy := Resolve_Aggr_Expr (Expression (N), False);
End_Scope;
@@ -2082,6 +2088,9 @@
return Failure;
end if;
+ elsif Nkind (Assoc) = N_Iterated_Component_Association then
+ null; -- handled above, in a loop context.
+
elsif not Resolve_Aggr_Expr
(Expression (Assoc), Single_Elmt => Single_Choice)
then
@@ -2726,6 +2735,143 @@
return Success;
end Resolve_Array_Aggregate;
+ -----------------------------
+ -- Resolve_Delta_Aggregate --
+ -----------------------------
+
+ procedure Resolve_Delta_Aggregate (N : Node_Id; Typ : Entity_Id) is
+ Base : constant Node_Id := Expression (N);
+ Deltas : constant List_Id := Component_Associations (N);
+ Assoc : Node_Id;
+ Choice : Node_Id;
+ Comp_Type : Entity_Id;
+ Index_Type : Entity_Id;
+
+ function Get_Component_Type (Nam : Node_Id) return Entity_Id;
+
+ ------------------------
+ -- Get_Component_Type --
+ ------------------------
+
+ function Get_Component_Type (Nam : Node_Id) return Entity_Id is
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Entity (Typ);
+
+ while Present (Comp) loop
+ if Chars (Comp) = Chars (Nam) then
+ if Ekind (Comp) = E_Discriminant then
+ Error_Msg_N ("delta cannot apply to discriminant", Nam);
+ end if;
+
+ return Etype (Comp);
+ end if;
+
+ Comp := Next_Entity (Comp);
+ end loop;
+
+ Error_Msg_NE ("type& has no component with this name", Nam, Typ);
+ return Any_Type;
+ end Get_Component_Type;
+
+ begin
+ if not Is_Composite_Type (Typ) then
+ Error_Msg_N ("not a composite type", N);
+ end if;
+
+ Analyze_And_Resolve (Base, Typ);
+ if Is_Array_Type (Typ) then
+ Index_Type := Etype (First_Index (Typ));
+ Assoc := First (Deltas);
+ while Present (Assoc) loop
+ if Nkind (Assoc) = N_Iterated_Component_Association then
+ Choice := First (Choice_List (Assoc));
+ while Present (Choice) loop
+ if Nkind (Choice) = N_Others_Choice then
+ Error_Msg_N
+ ("others not allowed in delta aggregate", Choice);
+
+ else
+ Analyze_And_Resolve (Choice, Index_Type);
+ end if;
+
+ Next (Choice);
+ end loop;
+
+ declare
+ Id : constant Entity_Id := Defining_Identifier (Assoc);
+ Ent : constant Entity_Id :=
+ New_Internal_Entity
+ (E_Loop, Current_Scope, Sloc (Assoc), 'L');
+
+ begin
+ Set_Etype (Ent, Standard_Void_Type);
+ Set_Parent (Ent, Assoc);
+
+ if No (Scope (Id)) then
+ Enter_Name (Id);
+ Set_Etype (Id, Index_Type);
+ Set_Ekind (Id, E_Variable);
+ Set_Scope (Id, Ent);
+ end if;
+
+ Push_Scope (Ent);
+ Analyze_And_Resolve
+ (New_Copy_Tree (Expression (Assoc)), Component_Type (Typ));
+ End_Scope;
+ end;
+
+ else
+ Choice := First (Choice_List (Assoc));
+ while Present (Choice) loop
+ if Nkind (Choice) = N_Others_Choice then
+ Error_Msg_N
+ ("others not allowed in delta aggregate", Choice);
+
+ else
+ Analyze (Choice);
+ if Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ then
+ -- Choice covers a range of values.
+ if Base_Type (Entity (Choice)) /=
+ Base_Type (Index_Type)
+ then
+ Error_Msg_NE ("choice does mat match index type of",
+ Choice, Typ);
+ end if;
+ else
+ Resolve (Choice, Index_Type);
+ end if;
+ end if;
+
+ Next (Choice);
+ end loop;
+
+ Analyze_And_Resolve (Expression (Assoc), Component_Type (Typ));
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ else
+ Assoc := First (Deltas);
+ while Present (Assoc) loop
+ Choice := First (Choice_List (Assoc));
+ while Present (Choice) loop
+ Comp_Type := Get_Component_Type (Choice);
+ Next (Choice);
+ end loop;
+
+ Analyze_And_Resolve (Expression (Assoc), Comp_Type);
+ Next (Assoc);
+ end loop;
+ end if;
+
+ Set_Etype (N, Typ);
+ end Resolve_Delta_Aggregate;
+
---------------------------------
-- Resolve_Extension_Aggregate --
---------------------------------
===================================================================
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
+-- 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- --
@@ -30,6 +30,7 @@
package Sem_Aggr is
+ procedure Resolve_Delta_Aggregate (N : Node_Id; Typ : Entity_Id);
procedure Resolve_Aggregate (N : Node_Id; Typ : Entity_Id);
procedure Resolve_Extension_Aggregate (N : Node_Id; Typ : Entity_Id);
===================================================================
@@ -5831,6 +5831,7 @@
| N_Defining_Operator_Symbol
| N_Defining_Program_Unit_Name
| N_Delay_Alternative
+ | N_Delta_Aggregate
| N_Delta_Constraint
| N_Derived_Type_Definition
| N_Designator
===================================================================
@@ -466,6 +466,7 @@
begin
pragma Assert (False
or else NT (N).Nkind = N_Aggregate
+ or else NT (N).Nkind = N_Delta_Aggregate
or else NT (N).Nkind = N_Extension_Aggregate);
return List2 (N);
end Component_Associations;
@@ -1265,6 +1266,7 @@
or else NT (N).Nkind = N_Component_Declaration
or else NT (N).Nkind = N_Delay_Relative_Statement
or else NT (N).Nkind = N_Delay_Until_Statement
+ or else NT (N).Nkind = N_Delta_Aggregate
or else NT (N).Nkind = N_Discriminant_Association
or else NT (N).Nkind = N_Discriminant_Specification
or else NT (N).Nkind = N_Exception_Declaration
@@ -3775,6 +3777,7 @@
begin
pragma Assert (False
or else NT (N).Nkind = N_Aggregate
+ or else NT (N).Nkind = N_Delta_Aggregate
or else NT (N).Nkind = N_Extension_Aggregate);
Set_List2_With_Parent (N, Val);
end Set_Component_Associations;
@@ -4565,6 +4568,7 @@
or else NT (N).Nkind = N_Component_Declaration
or else NT (N).Nkind = N_Delay_Relative_Statement
or else NT (N).Nkind = N_Delay_Until_Statement
+ or else NT (N).Nkind = N_Delta_Aggregate
or else NT (N).Nkind = N_Discriminant_Association
or else NT (N).Nkind = N_Discriminant_Specification
or else NT (N).Nkind = N_Exception_Declaration
===================================================================
@@ -4133,6 +4133,15 @@
-- Note that Box_Present is always False, but it is intentionally added
-- for completeness.
+ ----------------------------
+ -- 4.3.4 Delta Aggregate --
+ ----------------------------
+
+ -- N_Delta_Aggregate
+ -- Sloc points to left parenthesis
+ -- Expression (Node3)
+ -- Component_Associations (List2)
+
--------------------------------------------------
-- 4.4 Expression/Relation/Term/Factor/Primary --
--------------------------------------------------
@@ -8475,6 +8484,7 @@
N_Aggregate,
N_Allocator,
N_Case_Expression,
+ N_Delta_Aggregate,
N_Extension_Aggregate,
N_Raise_Expression,
N_Range,
@@ -11524,6 +11534,13 @@
4 => True, -- Discrete_Choices (List4)
5 => False), -- unused
+ N_Delta_Aggregate =>
+ (1 => False, -- Expressions (List1)
+ 2 => True, -- Component_Associations (List2)
+ 3 => True, -- Expression (Node3)
+ 4 => False, -- Unused
+ 5 => False), -- Etype (Node5-Sem)
+
N_Extension_Aggregate =>
(1 => True, -- Expressions (List1)
2 => True, -- Component_Associations (List2)
===================================================================
@@ -1613,7 +1613,7 @@
when '@' =>
if Ada_Version < Ada_2020 then
- Error_Illegal_Character;
+ Error_Msg ("target_name is an Ada2020 feature", Scan_Ptr);
Scan_Ptr := Scan_Ptr + 1;
else
===================================================================
@@ -196,6 +196,9 @@
when N_Delay_Relative_Statement =>
Analyze_Delay_Relative (N);
+ when N_Delta_Aggregate =>
+ Analyze_Aggregate (N);
+
when N_Delay_Until_Statement =>
Analyze_Delay_Until (N);
===================================================================
@@ -1381,7 +1381,7 @@
Expr_Node := P_Expression_Or_Range_Attribute_If_OK;
end if;
- -- Extension aggregate
+ -- Extension or Delta aggregate
if Token = Tok_With then
if Nkind (Expr_Node) = N_Attribute_Reference
@@ -1395,10 +1395,19 @@
Error_Msg_SC ("(Ada 83) extension aggregate not allowed");
end if;
- Aggregate_Node := New_Node (N_Extension_Aggregate, Lparen_Sloc);
- Set_Ancestor_Part (Aggregate_Node, Expr_Node);
Scan; -- past WITH
+ if Token = Tok_Delta then
+ Scan; -- past DELTA
+ Aggregate_Node := New_Node (N_Delta_Aggregate, Lparen_Sloc);
+ Set_Expression (Aggregate_Node, Expr_Node);
+ Expr_Node := Empty;
+ goto Aggregate;
+ else
+ Aggregate_Node := New_Node (N_Extension_Aggregate, Lparen_Sloc);
+ Set_Ancestor_Part (Aggregate_Node, Expr_Node);
+ end if;
+
-- Deal with WITH NULL RECORD case
if Token = Tok_Null then
@@ -1586,7 +1595,11 @@
-- All component associations (positional and named) have been scanned
T_Right_Paren;
- Set_Expressions (Aggregate_Node, Expr_List);
+
+ if Nkind (Aggregate_Node) /= N_Delta_Aggregate then
+ Set_Expressions (Aggregate_Node, Expr_List);
+ end if;
+
Set_Component_Associations (Aggregate_Node, Assoc_List);
return Aggregate_Node;
end P_Aggregate_Or_Paren_Expr;
@@ -1622,6 +1635,10 @@
Assoc_Node : Node_Id;
begin
+ if Token = Tok_For then
+ return P_Iterated_Component_Association;
+ end if;
+
Assoc_Node := New_Node (N_Component_Association, Token_Ptr);
Set_Choices (Assoc_Node, P_Discrete_Choice_List);
Set_Sloc (Assoc_Node, Token_Ptr);
===================================================================
@@ -2870,6 +2870,9 @@
when N_Character_Literal =>
Resolve_Character_Literal (N, Ctx_Type);
+ when N_Delta_Aggregate =>
+ Resolve_Delta_Aggregate (N, Ctx_Type);
+
when N_Expanded_Name =>
Resolve_Entity_Name (N, Ctx_Type);
===================================================================
@@ -84,6 +84,9 @@
-- expression with actions, which becomes the Initialization_Statements for
-- Obj.
+ procedure Expand_Delta_Array_Aggregate (N : Node_Id; Deltas : List_Id);
+ procedure Expand_Delta_Record_Aggregate (N : Node_Id; Deltas : List_Id);
+
function Has_Default_Init_Comps (N : Node_Id) return Boolean;
-- N is an aggregate (record or array). Checks the presence of default
-- initialization (<>) in any component (Ada 2005: AI-287).
@@ -6436,7 +6439,152 @@
return;
end Expand_N_Aggregate;
+ ------------------------------
+ -- Expand_N_Delta_Aggregate --
+ ------------------------------
+
+ procedure Expand_N_Delta_Aggregate (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Temp : constant Entity_Id := Make_Temporary (Loc, 'T');
+ Typ : constant Entity_Id := Etype (N);
+ Decl : Node_Id;
+
+ begin
+ Decl := Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => New_Copy_Tree (Expression (N)));
+
+ if Is_Array_Type (Etype (N)) then
+ Expand_Delta_Array_Aggregate (N, New_List (Decl));
+ else
+ Expand_Delta_Record_Aggregate (N, New_List (Decl));
+ end if;
+ end Expand_N_Delta_Aggregate;
+
----------------------------------
+ -- Expand_Delta_Array_Aggregate --
+ ----------------------------------
+
+ procedure Expand_Delta_Array_Aggregate (N : Node_Id; Deltas : List_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Temp : constant Entity_Id := Defining_Identifier (First (Deltas));
+ Assoc : Node_Id;
+ Choice : Node_Id;
+ function Generate_Loop (C : Node_Id) return Node_Id;
+ -- Generate a loop containing individual component assignments for
+ -- choices that are ranges, subtype indications, subtype names, and
+ -- iterated component associations.
+
+ function Generate_Loop (C : Node_Id) return Node_Id is
+ Sl : constant Source_Ptr := Sloc (C);
+ Ix : Entity_Id;
+
+ begin
+ if Nkind (Parent (C)) = N_Iterated_Component_Association then
+ Ix :=
+ Make_Defining_Identifier (Loc,
+ Chars => (Chars (Defining_Identifier (Parent (C)))));
+ else
+ Ix := Make_Temporary (Sl, 'I');
+ end if;
+
+ return
+ Make_Loop_Statement (Loc,
+ Iteration_Scheme => Make_Iteration_Scheme (Sl,
+ Loop_Parameter_Specification =>
+ Make_Loop_Parameter_Specification (Sl,
+ Defining_Identifier => Ix,
+ Discrete_Subtype_Definition => New_Copy_Tree (C))),
+ End_Label => Empty,
+ Statements =>
+ New_List (
+ Make_Assignment_Statement (Sl,
+ Name => Make_Indexed_Component (Sl,
+ Prefix => New_Occurrence_Of (Temp, Sl),
+ Expressions => New_List (New_Occurrence_Of (Ix, Sl))),
+ Expression => New_Copy_Tree (Expression (Assoc)))));
+ end Generate_Loop;
+
+ begin
+ Assoc := First (Component_Associations (N));
+ while Present (Assoc) loop
+ Choice := First (Choice_List (Assoc));
+ if Nkind (Assoc) = N_Iterated_Component_Association then
+ while Present (Choice) loop
+ Append_To (Deltas, Generate_Loop (Choice));
+ Next (Choice);
+ end loop;
+
+ else
+ while Present (Choice) loop
+
+ -- Choice can be given by a range, a subtype indication, a
+ -- subtype name, a scalar value, or an entity.
+
+ if Nkind (Choice) = N_Range
+ or else (Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice)))
+ then
+ Append_To (Deltas, Generate_Loop (Choice));
+
+ elsif Nkind (Choice) = N_Subtype_Indication then
+ Append_To (Deltas,
+ Generate_Loop (Range_Expression (Constraint (Choice))));
+
+ else
+ Append_To (Deltas,
+ Make_Assignment_Statement (Sloc (Choice),
+ Name => Make_Indexed_Component (Sloc (Choice),
+ Prefix => New_Occurrence_Of (Temp, Loc),
+ Expressions => New_List (New_Copy_Tree (Choice))),
+ Expression => New_Copy_Tree (Expression (Assoc))));
+ end if;
+
+ Next (Choice);
+ end loop;
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ Insert_Actions (N, Deltas);
+ Rewrite (N, New_Occurrence_Of (Temp, Loc));
+ end Expand_Delta_Array_Aggregate;
+
+ -----------------------------------
+ -- Expand_Delta_Record_Aggregate --
+ -----------------------------------
+
+ procedure Expand_Delta_Record_Aggregate (N : Node_Id; Deltas : List_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Temp : constant Entity_Id := Defining_Identifier (First (Deltas));
+ Assoc : Node_Id;
+ Choice : Node_Id;
+
+ begin
+ Assoc := First (Component_Associations (N));
+
+ while Present (Assoc) loop
+ Choice := First (Choice_List (Assoc));
+ while Present (Choice) loop
+ Append_To (Deltas,
+ Make_Assignment_Statement (Sloc (Choice),
+ Name => Make_Selected_Component (Sloc (Choice),
+ Prefix => New_Occurrence_Of (Temp, Loc),
+ Selector_Name => Make_Identifier (Loc, Chars (Choice))),
+ Expression => New_Copy_Tree (Expression (Assoc))));
+ Next (Choice);
+ end loop;
+
+ Next (Assoc);
+ end loop;
+
+ Insert_Actions (N, Deltas);
+ Rewrite (N, New_Occurrence_Of (Temp, Loc));
+ end Expand_Delta_Record_Aggregate;
+
+ ----------------------------------
-- Expand_N_Extension_Aggregate --
----------------------------------
===================================================================
@@ -28,6 +28,7 @@
package Exp_Aggr is
procedure Expand_N_Aggregate (N : Node_Id);
+ procedure Expand_N_Delta_Aggregate (N : Node_Id);
procedure Expand_N_Extension_Aggregate (N : Node_Id);
function Is_Delayed_Aggregate (N : Node_Id) return Boolean;
===================================================================
@@ -1775,6 +1775,13 @@
Write_Indent_Str (";");
end if;
+ when N_Delta_Aggregate =>
+ Write_Str_With_Col_Check_Sloc ("(");
+ Sprint_Node (Expression (Node));
+ Write_Str_With_Col_Check (" with delta ");
+ Sprint_Comma_List (Component_Associations (Node));
+ Write_Char (')');
+
when N_Extension_Aggregate =>
Write_Str_With_Col_Check_Sloc ("(");
Sprint_Node (Ancestor_Part (Node));