Annotated Ada Reference Manual (Ada 202y Draft 1)Legal Information
Contents   Index   References   Search   Previous   Next 

4.3 Aggregates

1
[ An aggregate combines component values into a composite value of an array type, record type, or record extension.]
1.a/5
Term entry: aggregate — construct used to define a value of a composite type by specifying the values of the components of the type

Syntax

2/5
{AI12-0127-1} {AI12-0212-1} aggregate ::= 
    record_aggregate | extension_aggregate | array_aggregate
  | delta_aggregate | container_aggregate

Name Resolution Rules

3/5
{AI95-00287-01} {AI12-0127-1} {AI12-0212-1} {AI12-0307-1} The expected type for an aggregate shall be a single array type, a single type with the Aggregate aspect specified, or a single descendant of a record type or of a record extension.
3.a
Discussion: See 8.6, “The Context of Overload Resolution” for the meaning of “shall be a single ... type”. 
3.b/3
Ramification: {AI05-0005-1} There are additional rules for each kind of aggregate. These aggregate rules are additive; a legal expression needs to satisfy all of the applicable rules. That means the rule given here must be satisfied even when it is syntactically possible to tell which specific kind of aggregate is being used. 
3.c/5
Reason: {AI12-0005-1} {AI12-0127-1} {AI12-0212-1} {AI12-0307-1} Generally, we don't want to look in aggregates to resolve them. For instance, Ada 95 allowed array types to match extension_aggregates, even though those have to be record types. Thus, we allow any record type with any visible (nondiscriminant) components to match an aggregate, even though only delta_aggregates allow private types or private extensions. Similarly, we allow any container type to match an aggregate, even though only container_aggregates allow container types. 

Legality Rules

4/6
{AI12-0127-1} {AI22-0032-1} A record_aggregate, or extension_aggregate, or container_aggregate shall not be of a class-wide type. 
4.a
Ramification: When the expected type in some context is class-wide, an aggregate has to be explicitly qualified by the specific type of value to be created, so that the expected type for the aggregate itself is specific. 
4.b
Discussion: We used to disallow aggregates of a type with unknown discriminants. However, that was unnecessarily restrictive in the case of an extension aggregate, and irrelevant to a record aggregate (since a type that is legal for a record aggregate could not possibly have unknown discriminants) and to an array aggregate (the only specific types that can have unknown discriminants are private types, private extensions, and types derived from them). 
4.c/5
Reason: {AI12-0127-1} We don't mention delta_aggregates, as those can get the specific type from the object represented by the base_expression (possibly at run time). We don't mention array_aggregates, as those cannot even be of a tagged type, so being class-wide is impossible.

Dynamic Semantics

5
For the evaluation of an aggregate, an anonymous object is created and values for the components or ancestor part are obtained (as described in the subsequent subclause for each kind of the aggregate) and assigned into the corresponding components or ancestor part of the anonymous object. Obtaining the values and the assignments occur in an arbitrary order. The value of the aggregate is the value of this object. 
5.a
Discussion: The ancestor part is the set of components inherited from the ancestor type. The syntactic category ancestor_part is the expression or subtype_mark that specifies how the ancestor part of the anonymous object should be initialized. 
5.b
Ramification: The assignment operations do the necessary value adjustment, as described in 7.6. Note that the value as a whole is not adjusted — just the subcomponents (and ancestor part, if any). 7.6 also describes when this anonymous object is finalized.
5.c
If the ancestor_part is a subtype_mark the Initialize procedure for the ancestor type is applied to the ancestor part after default-initializing it, unless the procedure is abstract, as described in 7.6. The Adjust procedure for the ancestor type is not called in this case, since there is no assignment to the ancestor part as a whole. 
6/6
{AI22-0007-1} If an aggregate is of a tagged type, a check is made that its value belongs to the first subtype of the type. Constraint_Error is raised if this check fails. Any discriminant check is performed before the initialization of any nondiscriminant component of the aggregate object. 
6.a
Ramification: This check ensures that no values of a tagged type are ever outside the first subtype, as required for inherited dispatching operations to work properly (see 3.4). This check will always succeed if the first subtype is unconstrained. This check is not extended to untagged types to preserve upward compatibility.
6.b/6
Reason: {AI22-0007-1} The order of checks and initializations is generally unspecified. However, we need to do discriminant checks before initializing any discriminant-dependent components, in order to avoid creating components that the ultimate subtype does not have. Most such problems are prevented by the rules about needed components for an aggregate (see 4.3.1), but not those that result from deriving from a constrained subtype. 

Extensions to Ada 83

6.c
We now allow extension_aggregates.

Wording Changes from Ada 83

6.d
We have adopted new wording for expressing the rule that the type of an aggregate shall be determinable from the outside, though using the fact that it is nonlimited record (extension) or array.
6.e
An aggregate now creates an anonymous object. This is necessary so that controlled types will work (see 7.6). 

Incompatibilities With Ada 95

6.f/2
{AI95-00287-01} In Ada 95, a limited type is not considered when resolving an aggregate. Since Ada 2005 now allows limited aggregates, we can have incompatibilities. For example: 
6.g/2
type Lim is limited
   record
      Comp: Integer;
   end record;
6.h/2
type Not_Lim is
   record
      Comp: Integer;
   end record;
6.i/2
procedure P(X: Lim);
procedure P(X: Not_Lim);
6.j/2
P((Comp => 123)); -- Illegal in Ada 2005, legal in Ada 95
6.k/2
The call to P is ambiguous in Ada 2005, while it would not be ambiguous in Ada 95 as the aggregate could not have a limited type. Qualifying the aggregate will eliminate any ambiguity. This construction would be rather confusing to a maintenance programmer, so it should be avoided, and thus we expect it to be rare. 

Extensions to Ada 95

6.l/2
{AI95-00287-01} Aggregates can be of a limited type. 

Incompatibilities With Ada 2012

6.m/5
{AI12-0005-1} {AI12-0127-1} {AI12-0212-1} We now allow types with the Aggregate aspect specified ("container types"), as well as private types and extensions descended from a record type or extension, to match all forms of aggregate. These types are only allowed for new types of aggregate (container_aggregates for the Aggregate aspect, and delta_aggregates for private types), but, consistent with other forms of aggregate, we do not look at the form of the aggregate to determine resolution. This can be incompatible in usually unlikely cases, where overloading of a container or private type with a type that was previously allowed in aggregates makes an existing call ambiguous. Unfortunately, Ada.Containers.Vectors has a number of such overloadings for Insert, Append, Prepend, and "&", so the problem may appear for any element type of a Vector that allows aggregates. For instance, if My_Vector is an instance of Ada.Containers.Vectors with an element type of Not_Lim as defined above, and V is an object of My_Vector.Vector, then My_Vector.Append (V, (Comp => 123)); will be illegal in Ada 2022 and legal in Ada 2012. This can easily be fixed by qualifying the aggregate with the correct type. 

Wording Changes from Ada 2022

6.n/6
{AI22-0007-1} Corrigendum: Clarified that discriminant always occur before creating any non-discriminant components (in particular, discriminant-dependent components). This is specifying unspecified behavior, so it does not represent an inconsistency, but the possibility exists that an unusual program where initialization (or lack thereof) of some component has a side-effect that affects later execution would change behavior. 
6.o/6
{AI22-0032-1} Corrigendum: Corrected the omission of container_aggregates from the list of aggregates that cannot be class-wide. This could be considered an incompatibility, but since no static or dynamic semantics are defined for such an aggregate, it is unlikely that any implementation would usefully allow such a thing. As such, it is highly unlikely to occur in any code. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe