Ada Conformity Assessment Authority      Home Conformity Assessment   Test Suite ARGAda Standard
 
Annotated Ada Reference ManualLegal Information
Contents   Index   References   Search   Previous   Next 

4.3.1 Record Aggregates

1
[In a record_aggregate, a value is specified for each component of the record or record extension value, using either a named or a positional association.] 

Syntax

2
record_aggregate ::= (record_component_association_list)
3
record_component_association_list ::= 
    record_component_association {, record_component_association}
  | null record
4/2
{AI95-00287-01} record_component_association ::= 
    [component_choice_list =>] expression
   | component_choice_list => <>
5
component_choice_list ::= 
     component_selector_name {| component_selector_name}
   | others
6
A record_component_association is a named component association if it has a component_choice_list; otherwise, it is a positional component association. Any positional component associations shall precede any named component associations. If there is a named association with a component_choice_list of others, it shall come last. 
6.a
Discussion: These rules were implied by the BNF in an early version of the RM9X, but it made the grammar harder to read, and was inconsistent with how we handle discriminant constraints. Note that for array aggregates we still express some of the rules in the grammar, but array aggregates are significantly different because an array aggregate is either all positional (with a possible others at the end), or all named. 
7
In the record_component_association_list for a record_aggregate, if there is only one association, it shall be a named association. 
7.a/3
Reason: {AI05-0264-1} Otherwise, the construct would be interpreted as a parenthesized expression. This is considered a syntax rule, since it is relevant to overload resolution. We choose not to express it with BNF so we can share the definition of record_component_association_list in both record_aggregate and extension_aggregate.
7.b
Ramification: The record_component_association_list of an extension_aggregate does not have such a restriction. 

Name Resolution Rules

8/2
{AI95-00287-01} The expected type for a record_aggregate shall be a single record type or record extension. 
8.a
Ramification: This rule is used to resolve whether an aggregate is an array_aggregate or a record_aggregate. The presence of a with is used to resolve between a record_aggregate and an extension_aggregate.
9
For the record_component_association_list of a record_aggregate, all components of the composite value defined by the aggregate are needed[; for the association list of an extension_aggregate, only those components not determined by the ancestor expression or subtype are needed (see 4.3.2).] Each selector_name in a record_component_association shall denote a needed component [(including possibly a discriminant)].
9.a
Ramification: For the association list of a record_aggregate, “needed components” includes every component of the composite value, but does not include those in unchosen variants (see AI83-309). If there are variants, then the value specified for the discriminant that governs them determines which variant is chosen, and hence which components are needed.
9.b
If an extension defines a new known_discriminant_part, then all of its discriminants are needed in the component association list of an extension aggregate for that type, even if the discriminants have the same names and types as discriminants of the type of the ancestor expression. This is necessary to ensure that the positions in the record_component_association_list are well defined, and that discriminants that govern variant_parts can be given by static expressions. 
10
The expected type for the expression of a record_component_association is the type of the associated component(s); the associated component(s) are as follows: 
11
For a positional association, the component [(including possibly a discriminant)] in the corresponding relative position (in the declarative region of the type), counting only the needed components;
11.a
Ramification: This means that for an association list of an extension_aggregate, only noninherited components are counted to determine the position.
11.b/3
{AI05-0005-1} For a derived type (including type extensions), the order of declaration is defined in 3.4, “Derived Types and Classes”. In particular, all discriminants come first, regardless of whether they are defined for the parent type or are newly added to the derived type. 
12
For a named association with one or more component_selector_names, the named component(s);
13
For a named association with the reserved word others, all needed components that are not associated with some previous association. 

Legality Rules

14
If the type of a record_aggregate is a record extension, then it shall be a descendant of a record type, through one or more record extensions (and no private extensions).
15/3
 {AI05-0016-1} The reserved words null record may appear only if there are no components needed in a given record_component_association_list.
15.a
Ramification: For example, "(null record)" is a record_aggregate for a null record type. Similarly, "(T'(A) with null record)" is an extension_aggregate for a type defined as a null record extension of T.
15.b/3
{AI05-0016-1} If no components are needed and null record is not used, the record_component_association must necessarily be others => <>, as that is the only record_component_association that does not require an associated component. 
16/4
 {AI95-00287-01} {AI05-0199-1} {AI12-0046-1} Each record_component_association other than an others choice with a <> shall have at least one associated component, and each needed component shall be associated with exactly one record_component_association. If a record_component_association with an expression has two or more associated components, all of them shall be of the same type, or all of them shall be of anonymous access types whose subtypes statically match. In addition, Legality Rules are enforced separately for each associated component.
16.a/2
Ramification: {AI95-00287-01} These rules apply to an association with an others choice with an expression. An others choice with a <> can match zero components or several components with different types. 
16.b/2
Reason: {AI95-00287-01} Without these rules, there would be no way to know what was the expected type for the expression of the association. Note that some of the rules do not apply to <> associations, as we do not need to resolve anything. We allow others => <> to match no components as this is similar to array aggregates. That means that (others => <>) always represents a default-initialized record or array value. 
16.c/4
Discussion: {AI12-0046-1} AI83-00244 also requires that the expression shall be legal for each associated component. Ada 95 omitted this wording, as it was thought that all cases of difference had been eliminated. That probably was true, but Ada 2005 reintroduced cases where the types match but the legality differs. For example: This is because even though two components have the same type, they might have different subtypes. Therefore, the legality of the expression, particularly if it is an array aggregate, might differ depending on the associated component's subtype. However, we have relaxed the rules on array aggregates slightly for Ada 95, so the staticness of an applicable index constraint has no effect on the legality of the array aggregate to which it applies. See 4.3.3. This was the only case (that we know of) where a subtype provided by context affected the legality of an expression.
16.c.1/4
type Rec (D : access Integer) is record
          F : access Integer;
end record;
16.c.2/4
...
X : aliased Integer;
R : Rec := (D | F => X'Access); -- Legal for D, illegal for F
16.c.3/4
There are additional ways for this to happen; because of cases like the above we require that the Legality Rules are checked individually for each associated component.
16.d
Ramification: The rule that requires at least one associated component for each record_component_association implies that there can be no extra associations for components that don't exist in the composite value, or that are already determined by the ancestor expression or subtype of an extension_aggregate.
16.e
The second part of the first sentence ensures that no needed components are left out, nor specified twice. 
17/3
 {AI05-0220-1} The value of a discriminant that governs a variant_part P shall be given by a static expression, unless P is nested within a variant V that is not selected by the discriminant value governing the variant_part enclosing V
17.a
Ramification: This expression might either be given within the aggregate itself, or in a constraint on the parent subtype in a derived_type_definition for some ancestor of the type of the aggregate. 
17.1/2
   {AI95-00287-01} A record_component_association for a discriminant without a default_expression shall have an expression rather than <>. 
17.b/2
Reason: A discriminant must always have a defined value, but <> means uninitialized for a discrete type unless the component has a default value. 

Dynamic Semantics

18
The evaluation of a record_aggregate consists of the evaluation of the record_component_association_list.
19
For the evaluation of a record_component_association_list, any per-object constraints (see 3.8) for components specified in the association list are elaborated and any expressions are evaluated and converted to the subtype of the associated component. Any constraint elaborations and expression evaluations (and conversions) occur in an arbitrary order, except that the expression for a discriminant is evaluated (and converted) prior to the elaboration of any per-object constraint that depends on it, which in turn occurs prior to the evaluation and conversion of the expression for the component with the per-object constraint.
19.a
Ramification: The conversion in the first rule might raise Constraint_Error. 
19.b
Discussion: This check in the first rule presumably happened as part of the dependent compatibility check in Ada 83. 
19.1/2
   {AI95-00287-01} For a record_component_association with an expression, the expression defines the value for the associated component(s). For a record_component_association with <>, if the component_declaration has a default_expression, that default_expression defines the value for the associated component(s); otherwise, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see 3.3.1).
20
The expression of a record_component_association is evaluated (and converted) once for each associated component.
20.a/3
Ramification: {AI05-0005-1} We don't need similar language for <>, as we're considering the value of <> for each individual component. Each component has its own default expression or its own default initialization (they can be different for each component; the components even could have different types), and each one has to be evaluated. So there is no need to repeat that. 
NOTES
21
8  For a record_aggregate with positional associations, expressions specifying discriminant values appear first since the known_discriminant_part is given first in the declaration of the type; they have to be in the same order as in the known_discriminant_part.

Examples

22
Example of a record aggregate with positional associations: 
23
(4, July, 1776)                                       --  see 3.8 
24
Examples of record aggregates with named associations: 
25
(Day => 4, Month => July, Year => 1776)
(Month => July, Day => 4, Year => 1776)
26
(Disk, Closed, Track => 5, Cylinder => 12)            --  see 3.8.1
(Unit => Disk, Status => Closed, Cylinder => 9, Track => 1)
27/2
 {AI95-00287-01} Examples of component associations with several choices: 
28
(Value => 0, Succ|Pred => new Cell'(0, nullnull))   --  see 3.10.1
29
 --  The allocator is evaluated twice: Succ and Pred designate different cells
29.1/2
(Value => 0, Succ|Pred => <>)                         --  see 3.10.1
29.2/2
 --  Succ and Pred will be set to null
30
Examples of record aggregates for tagged types (see 3.9 and 3.9.1):
31
Expression'(null record)
Literal'(Value => 0.0)
Painted_Point'(0.0, Pi/2.0, Paint => Red)

Extensions to Ada 83

31.a
Null record aggregates may now be specified, via "(null record)". However, this syntax is more useful for null record extensions in extension aggregates.

Wording Changes from Ada 83

31.b
Various AIs have been incorporated (AI83-00189, AI83-00244, and AI83-00309). In particular, Ada 83 did not explicitly disallow extra values in a record aggregate. Now we do. 

Extensions to Ada 95

31.c/2
{AI95-00287-01} <> can be used in place of an expression in a record_aggregate, default initializing the component. 

Wording Changes from Ada 95

31.d/2
{AI95-00287-01} Limited record_aggregates are allowed (since all kinds of aggregates can now be limited, see 4.3).

Incompatibilities With Ada 2005

31.e/3
{AI05-0220-1} Correction: Corrected wording so that the rule for discriminants governing variant_parts was not effectively circular. The change makes a few aggregates where a nonstatic discriminant governs an empty variant_part illegal. However, most Ada implementations already enforce some version of the new rule and already reject these aggregates. So it is unlikely that any incompatibility will be noticed in practice.

Extensions to Ada 2005

31.f/3
{AI05-0016-1} Correction: Fixed the wording so that others => <> can be used in place of null record. This is needed to avoid a generic contract issue for generic bodies: we do not want to have to assume the worst to disallow others => <> if the record type might be a null record.
31.g/3
{AI05-0199-1} Correction: We now allow multiple components with anonymous access types to be specified with a single component association. This is to be consistent with the capabilities of a named access type. 

Wording Changes from Ada 2012

31.h/4
{AI12-0046-1} Corrigendum: We explicitly say that the Legality Rules have to be rechecked for each component individually. This seems obvious, but as the AARM note 4.3.1 (16.c) appeared to say that this was not necessary, and since we explicitly state this sort of thing for generic instances, it seemed better to be explicit. 

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