[Ada] Ongoing work for AI12-0212: container aggregates

2021-05-05 Thread Pierre-Marie de Rodat
Add legality checks for indexed aggregates with component associations.

RN 4.3.5 (28/5 - 30/5) specifies validity rules for indexed aggregates,
intended to simplify implementation as well as the computation of the
expected size of an indexed aggregate, such for an aggregaate of a
vector type.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

* sem_aggr.adb (Resolve_Indexed_Aggregate): For indexed
aggregates with component associations verify that if there is
more than one component association then all the choices are
static, that the set of choices define a continuous sequence of
values, and that if loop specfications appear, they do not
include iterator filters or key expressions.diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -2980,9 +2980,12 @@ package body Sem_Aggr is
 Index_Type : constant Entity_Id := Etype (Next_Formal (Container));
 Comp_Type  : constant Entity_Id :=
  Etype (Next_Formal (Next_Formal (Container)));
-Comp   : Node_Id;
-Choice : Node_Id;
+Comp: Node_Id;
+Choice  : Node_Id;
+Num_Choices : Nat := 0;
 
+Hi_Val : Uint;
+Lo_Val : Uint;
  begin
 if Present (Expressions (N)) then
Comp := First (Expressions (N));
@@ -2999,7 +3002,7 @@ package body Sem_Aggr is
   return;
end if;
 
-   Comp := First (Expressions (N));
+   Comp := First (Component_Associations (N));
 
while Present (Comp) loop
   if Nkind (Comp) = N_Component_Association then
@@ -3007,6 +3010,7 @@ package body Sem_Aggr is
 
  while Present (Choice) loop
 Analyze_And_Resolve (Choice, Index_Type);
+Num_Choices := Num_Choices + 1;
 Next (Choice);
  end loop;
 
@@ -3018,10 +3022,107 @@ package body Sem_Aggr is
   then
  Resolve_Iterated_Association
(Comp, Index_Type, Comp_Type);
+ Num_Choices := Num_Choices + 1;
   end if;
 
   Next (Comp);
end loop;
+
+   --  The component associations in an indexed aggregate
+   --  must denote a contiguous set of static values. We
+   --  build a table of values/ranges and sort it, as is done
+   --  elsewhere for case statements and array aggregates.
+   --  If the aggregate has a single iterated association it
+   --  is allowed to be nonstatic and there is nothing to check.
+
+   if Num_Choices > 1 then
+  declare
+ Table : Case_Table_Type (1 .. Num_Choices);
+ No_Choice : Pos := 1;
+ Lo, Hi: Node_Id;
+
+  --  Traverse aggregate to determine size of needed table.
+  --  Verify that bounds are static and that loops have no
+  --  filters or key expressions.
+
+  begin
+ Comp := First (Component_Associations (N));
+ while Present (Comp) loop
+if Nkind (Comp) = N_Iterated_Element_Association then
+   if Present
+ (Loop_Parameter_Specification (Comp))
+   then
+  if Present (Iterator_Filter
+(Loop_Parameter_Specification (Comp)))
+  then
+ Error_Msg_N
+   ("iterator filter not allowed " &
+ "in indexed aggregate", Comp);
+ return;
+
+  elsif Present (Key_Expression
+(Loop_Parameter_Specification (Comp)))
+  then
+ Error_Msg_N
+   ("key expression not allowed " &
+ "in indexed aggregate", Comp);
+ return;
+  end if;
+   end if;
+else
+   Choice := First (Choices (Comp));
+
+   while Present (Choice) loop
+  Get_Index_Bounds (Choice, Lo, Hi);
+  Table (No_Choice).Choice := Choice;
+  Table (No_Choice).Lo := Lo;
+  Table (No_Choice).Hi := Hi;
+
+  --  Verify staticness of value or range
+
+   

[Ada] Ongoing work for AI12-0212: container aggregates

2021-05-04 Thread Pierre-Marie de Rodat
This patch refines the handling of container aggregates with non-static
sizes given with iterated component associations and iterated element
associations. When necessary we construct an expression to be evaluated
dynamically to guide the allocation of the container, prior to inserting
elements.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

* exp_aggr.adb (Build_Siz_Exp): new function, subsidiary of
Expand_Container_Aggregate, to create an expression to be used
in the dynamic allocation of a container with a single container
element association.
(Add_Range): Handle static bounds of ranges over enumerations.
(Expand_Container_Aggregate): Add declaration for size
expression when needed, and use it in container object
declaration for container.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6982,11 +6982,24 @@ package body Exp_Aggr is
   Init_Stat : Node_Id;
   Siz   : Int;
 
+  --  The following are used when the size of the aggregate is not
+  --  static and requires a dynamic evaluation.
+  Siz_Decl   : Node_Id;
+  Siz_Exp: Node_Id := Empty;
+  Count_Type : Entity_Id;
+
   function Aggregate_Size return Int;
   --  Compute number of entries in aggregate, including choices
-  --  that cover a range, as well as iterated constructs.
+  --  that cover a range or subtype, as well as iterated constructs.
   --  Return -1 if the size is not known statically, in which case
-  --  we allocate a default size for the aggregate.
+  --  allocate a default size for the aggregate, or build an expression
+  --  to estimate the size dynamically.
+
+  function Build_Siz_Exp (Comp : Node_Id) return Int;
+  --  When the aggregate contains a single Iterated_Component_Association
+  --  or Element_Association with non-static bounds, build an expression
+  --  to be used as the allocated size of the container. This may be an
+  --  overestimate if a filter is present, but is a safe approximation.
 
   procedure Expand_Iterated_Component (Comp : Node_Id);
   --  Handle iterated_component_association and iterated_Element
@@ -7005,34 +7018,54 @@ package body Exp_Aggr is
  Siz : Int := 0;
 
  procedure Add_Range_Size;
- --  Compute size of component association given by
- --  range or subtype name.
+ --  Compute number of components specified by a component association
+ --  given by a range or subtype name.
+
+ 
+ -- Add_Range_Size --
+ 
 
  procedure Add_Range_Size is
  begin
+--  The bounds of the discrete range are integers or enumeration
+--  literals
+
 if Nkind (Lo) = N_Integer_Literal then
Siz := Siz + UI_To_Int (Intval (Hi))
- - UI_To_Int (Intval (Lo)) + 1;
+  - UI_To_Int (Intval (Lo)) + 1;
+else
+   Siz := Siz + UI_To_Int (Enumeration_Pos (Hi))
+  - UI_To_Int (Enumeration_Pos (Lo)) + 1;
 end if;
  end Add_Range_Size;
 
   begin
+ --  Aggregate is either all positional or all named.
+
  if Present (Expressions (N)) then
 Siz := List_Length (Expressions (N));
  end if;
 
  if Present (Component_Associations (N)) then
 Comp := First (Component_Associations (N));
-
---  If the component is an Iterated_Element_Association
---  it includes an iterator or a loop parameter, possibly
---  with a filter, so we do not attempt to compute its
---  size. Room for future optimization ???
-
-if Nkind (Comp) = N_Iterated_Element_Association then
-   return -1;
+--  If there is a single component association it can be
+--  an iterated component with dynamic bounds or an element
+--  iterator over an iterable object. If it is an array
+--  we can use the attribute Length to get its size;
+--  for a predefined container the function Length plays
+--  the same role. There is no available mechanism for
+--  user-defined containers. For now we treat all of these
+--  as dynamic.
+
+if List_Length (Component_Associations (N)) = 1
+  and then Nkind (Comp) in N_Iterated_Component_Association |
+   N_Iterated_Element_Association
+then
+   return Build_Siz_Exp (Comp);
 end if;
 
+--  Otherwise all associations must specify static sizes.
+
 while Present (Comp) loop
Choice := First (Choice_List (Comp));
 
@@ -7042,26 +7075,14 @@ package body Exp_Aggr is

[Ada] Ongoing work for AI12-0212 : container aggregates

2020-07-16 Thread Pierre-Marie de Rodat
This patch adds support for indexed aggregates with both positional
components and component associations that include multiple choices and
range specifications. For indexed aggregates the expansion uses a
separate pass, as suggested in AI12-0212, to compute the size of the
resulting object and preallocate that size before expanding the
aggregate into individual indexed assignments.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

* sem_aggr.adb (Resolve_Container_Aggregate): Add semantic
checks for indexed aggregates, including component associations
and iterated component associations.
* exp_aggr.adb (Expand_Iterated_Component): New subprogram,
subsidiary of Expand_Container_Aggreggate, used for positional,
named, and indexed aggregates.
(Aggregate_Size): New subprogram to precompute the size of an
indexed aggregate prior to call to allocate it.
(Expand_Range_Component): New subprogram so generate loop for a
component association given by a range or a subtype name in an
indexed aggregate.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6878,8 +6878,6 @@ package body Exp_Aggr is
   New_Indexed_Subp: Node_Id := Empty;
   Assign_Indexed_Subp : Node_Id := Empty;
 
-  procedure Expand_Iterated_Component (Comp : Node_Id);
-
   Aggr_Code : constant List_Id   := New_List;
   Temp  : constant Entity_Id := Make_Temporary (Loc, 'C', N);
 
@@ -6887,6 +6885,12 @@ package body Exp_Aggr is
   Decl  : Node_Id;
   Init_Stat : Node_Id;
 
+  procedure Expand_Iterated_Component (Comp : Node_Id);
+  --  Handle iterated_component_association and iterated_Element
+  --  association by generating a loop over the specified range,
+  --  given either by a loop parameter specification or an iterator
+  --  specification.
+
   ---
   -- Expand_Iterated_Component --
   ---
@@ -6946,6 +6950,7 @@ package body Exp_Aggr is
   Iteration_Scheme => L_Iteration_Scheme,
   Statements   => Stats);
  Append (Loop_Stat, Aggr_Code);
+
   end Expand_Iterated_Component;
 
begin
@@ -6968,11 +6973,16 @@ package body Exp_Aggr is
Name => New_Occurrence_Of (Temp, Loc),
Expression => New_Occurrence_Of (Entity (Empty_Subp), Loc));
   end if;
+
   Append (Init_Stat, Aggr_Code);
 
-  --  First case: positional aggregate
+  ---
+  --  Positional aggregate --
+  ---
 
-  if Present (Add_Unnamed_Subp) then
+  if Present (Add_Unnamed_Subp)
+and then No (Assign_Indexed_Subp)
+  then
  if Present (Expressions (N)) then
 declare
Insert : constant Entity_Id := Entity (Add_Unnamed_Subp);
@@ -6993,7 +7003,7 @@ package body Exp_Aggr is
 end;
  end if;
 
- --  iterated component associations may be present.
+ --  Iterated component associations may also be present.
 
  Comp := First (Component_Associations (N));
  while Present (Comp) loop
@@ -7001,6 +7011,10 @@ package body Exp_Aggr is
 Next (Comp);
  end loop;
 
+  -
+  -- Named_Aggregate --
+  -
+
   elsif Present (Add_Named_Subp) then
  declare
 Insert : constant Entity_Id := Entity (Add_Named_Subp);
@@ -7034,6 +7048,235 @@ package body Exp_Aggr is
Next (Comp);
 end loop;
  end;
+
+  ---
+  -- Indexed_Aggregate --
+  ---
+
+  elsif Present (Assign_Indexed_Subp) then
+ declare
+Insert : constant Entity_Id := Entity (Assign_Indexed_Subp);
+Index_Type : constant Entity_Id :=
+   Etype (Next_Formal (First_Formal (Insert)));
+
+function Aggregate_Size return Int;
+--  Compute number of entries in aggregate, including choices
+--  that cover a range, as well as iterated constructs.
+
+function  Expand_Range_Component
+  (Rng  : Node_Id;
+   Expr : Node_Id) return Node_Id;
+--  Transform a component assoication with a range into an
+--  explicit loop. If the choice is a subtype name, it is
+--  rewritten as a range with the corresponding bounds, which
+--  are known to be static.
+
+Comp   : Node_Id;
+Index  : Node_Id;
+Pos: Int := 0;
+Stat   : Node_Id;
+Key: Node_Id;
+Size   : Int := 0;
+
+-
+-- Expand_Raange_Component --
+-
+
+function 

[Ada] Ongoing work for AI12-0212: container aggregates

2020-07-15 Thread Pierre-Marie de Rodat
This patch modifies the parser to recognize
iterated_element_associations, which may include a key_exprewsion to be
used in a named aggregate such as a map. The new syntactic node
N_Iterated_Element_Association is recognized throughout the compiler.
The patch also extends the analysis and expansion of positional and
named aggregates that include iterated_element_associations, (for now
without key_expressions).

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

* par-ch4.adb (P_Iterated_Component_Association): Extended to
recognzize the similar Iterated_Element_Association. This node
is only generated when an explicit Key_Expression is given.
Otherwise the distinction between the two iterated forms is done
during semantic analysis.
* sinfo.ads: New node N_Iterated_Element_Association, for
Ada202x container aggregates.  New field Key_Expression.
* sinfo.adb: Subprograms for new node and newn field.
* sem_aggr.adb (Resolve_Iterated_Component_Association): Handle
the case where the Iteration_Scheme is an
Iterator_Specification.
* exp_aggr.adb (Wxpand_Iterated_Component): Handle a component
with an Iterated_Component_Association, generate proper loop
using given Iterator_Specification.
* exp_util.adb (Insert_Axtions): Handle new node as other
aggregate components.
* sem.adb, sprint.adb: Handle new node.
* tbuild.adb (Make_Implicit_Loop_Statement): Handle properly a
loop with an Iterator_ specification.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6914,13 +6914,20 @@ package body Exp_Aggr is
  Stats  : List_Id;
 
   begin
- L_Range := Relocate_Node (First (Discrete_Choices (Comp)));
- L_Iteration_Scheme :=
-   Make_Iteration_Scheme (Loc,
- Loop_Parameter_Specification =>
-   Make_Loop_Parameter_Specification (Loc,
- Defining_Identifier => Loop_Id,
- Discrete_Subtype_Definition => L_Range));
+ if Present (Iterator_Specification (Comp)) then
+L_Iteration_Scheme :=
+  Make_Iteration_Scheme (Loc,
+Iterator_Specification => Iterator_Specification (Comp));
+
+ else
+L_Range := Relocate_Node (First (Discrete_Choices (Comp)));
+L_Iteration_Scheme :=
+  Make_Iteration_Scheme (Loc,
+Loop_Parameter_Specification =>
+  Make_Loop_Parameter_Specification (Loc,
+Defining_Identifier => Loop_Id,
+Discrete_Subtype_Definition => L_Range));
+ end if;
 
  --  Build insertion statement. For a positional aggregate, only the
  --  expression is needed. For a named aggregate, the loop variable,


diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -7346,6 +7346,7 @@ package body Exp_Util is
 
 when N_Component_Association
| N_Iterated_Component_Association
+   | N_Iterated_Element_Association
 =>
if Nkind (Parent (P)) = N_Aggregate
  and then Present (Loop_Actions (P))


diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -3407,6 +3407,8 @@ package body Ch4 is
function P_Iterated_Component_Association return Node_Id is
   Assoc_Node : Node_Id;
   Id : Node_Id;
+  Iter_Spec  : Node_Id;
+  Loop_Spec  : Node_Id;
   State  : Saved_Scan_State;
 
--  Start of processing for P_Iterated_Component_Association
@@ -3423,6 +3425,9 @@ package body Ch4 is
   --  if E is a subtype indication this is a loop parameter spec,
   --  while if E a name it is an iterator_specification, and the
   --  disambiguation takes place during semantic analysis.
+  --  In addition, if "use" is present after the specification,
+  --  this is an Iterated_Element_Association that carries a
+  --  key_expression, and we generate the appropriate node.
 
   Id := P_Defining_Identifier;
   Assoc_Node :=
@@ -3432,6 +3437,22 @@ package body Ch4 is
  Set_Defining_Identifier (Assoc_Node, Id);
  T_In;
  Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List);
+
+ if Token = Tok_Use then
+
+--  Key-expression is present, rewrite node as an
+--  iterated_Element_Awwoiation.
+
+Scan;  --  past USE
+Loop_Spec :=
+  New_Node (N_Loop_Parameter_Specification, Prev_Token_Ptr);
+Set_Defining_Identifier (Loop_Spec, Id);
+Set_Discrete_Subtype_Definition (Loop_Spec,
+   First (Discrete_Choices (Assoc_Node)));
+Set_Loop_Parameter_Specification (Assoc_Node, Loop_Spec);