3.8 Record Types
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
A record object is a composite object consisting of named components. The value of a record object is a composite value consisting of the values of the components.
Syntax
2record_type_definition
::=
[[abstract] tagged] [limited] record_definition
3/5record_definition
::=
record
component_list
end record [record_identifier
]
| null record
4component_list
::=
component_item
{component_item
}
| {component_item
} variant_part
| null;
5/1{8652/0009} component_item
::=
component_declaration
| aspect_clause
6/3component_declaration
::=
defining_identifier_list
: component_definition
[:= default_expression
]
[aspect_specification
];
6.1/5If a record_identifier
appears at the end of the record_definition
, it shall repeat the defining_identifier
of the enclosing full_type_declaration
.
Name Resolution Rules
7The expected type for the default_expression
, if any, in a component_declaration
is the type of the component.
Legality Rules
8/2This paragraph was deleted.
Each component_declaration
declares a component of the record type. Besides components declared by component_declaration
s, the components of a record type include any components declared by discriminant_specification
s of the record type declaration. [The identifiers of all components of a record type shall be distinct.]
Within a type_declaration
, a name
that denotes a component, protected subprogram, or entry of the type is allowed only in the following cases:
- A
name
that denotes any component, protected subprogram, or entry is allowed within anaspect_specification
, an operational item, or a representation item that occurs within the declaration of the composite type. 12/3 - A
name
that denotes a noninherited discriminant is allowed within the declaration of the type, but not within thediscriminant_part
. If the discriminant is used to define the constraint of a component, the bounds of an entry family, or the constraint of the parent subtype in aderived_type_definition
, then its name shall appear alone as adirect_name
(not as part of a larger expression or expanded name). A discriminant shall not be used to define the constraint of a scalar component.
default_expression
cannot depend on the value of another one. They also prevent circularities. aspect_specification
s and representation items. However, the discriminant_selector_name
of the parent subtype_indication
is allowed to denote a discriminant of the parent. If the name of the current instance of a type (see 8.6) is used to define the constraint of a component, then it shall appear as a direct_name
that is the prefix
of an attribute_reference
whose result is of an access type, and the attribute_reference
shall appear alone.
Static Semantics
13.1/3If a record_type_definition
includes the reserved word limited, the type is called an explicitly limited record type.
The component_definition
of a component_declaration
defines the (nominal) subtype of the component. If the reserved word aliased appears in the component_definition
, then the component is aliased (see 3.10).
If the component_list
of a record type is defined by the reserved word null and there are no discriminants, then the record type has no components and all records of the type are null records. A record_definition
of null record is equivalent to record null; end record.
Dynamic Semantics
16The elaboration of a record_type_definition
creates the record type and its first subtype, and consists of the elaboration of the record_definition
. The elaboration of a record_definition
consists of the elaboration of its component_list
, if any.
The elaboration of a component_list
consists of the elaboration of the component_item
s and variant_part
, if any, in the order in which they appear. The elaboration of a component_declaration
consists of the elaboration of the component_definition
.
defining_identifier_list
has more than one defining_identifier
, we presume here that the transformation explained in 3.3.1 has already taken place. Alternatively, we could say that the component_definition
is elaborated once for each defining_identifier
in the list. {8652/0002} Within the definition of a composite type, if a component_definition
or discrete_subtype_definition
(see 9.5.2) includes a name
that denotes a discriminant of the type, or that is an attribute_reference
whose prefix
denotes the current instance of the type, the expression containing the name
is called a per-object expression, and the constraint
or range
being defined is called a per-object constraint. For the elaboration of a component_definition
of a component_declaration
or the discrete_subtype_definition
of an entry_declaration
for an entry family (see 9.5.2), if the component subtype is defined by an access_definition
or if the constraint
or range
of the subtype_indication
or discrete_subtype_definition
is not a per-object constraint, then the access_definition
, subtype_indication
, or discrete_subtype_definition
is elaborated. On the other hand, if the constraint
or range
is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant.
{8652/0002} When a per-object constraint is elaborated [(as part of creating an object)], each per-object expression of the constraint is evaluated. For other expressions, the values determined during the elaboration of the component_definition
or entry_declaration
are used. Any checks associated with the enclosing subtype_indication
or discrete_subtype_definition
are performed[, including the subtype compatibility check (see 3.2.2),] and the associated subtype is created.
component_definition
s and discrete_subtype_definition
s is performed when the type definition is elaborated. The evaluation of expressions that appear as default_expression
s is postponed until an object is created. Expressions in representation items that appear within a composite type definition are evaluated according to the rules of the particular representation item. component_declaration
with several identifiers is equivalent to a sequence of single component_declaration
s, as explained in 3.3.1.default_expression
of a record component is only evaluated upon the creation of a default-initialized object of the record type (presuming the object has the component, if it is in a variant_part
— see 3.3.1).variant_part
, then the same components are present in all values of the type.selected_component
. A value of a record can be specified with a record_aggregate
.Examples
26Examples of record type declarations:
type Date is
record
Day : Integer range 1 .. 31;
Month : Month_Name; -- see 3.5.1
Year : Integer range 0 .. 4000;
end record;
28/5type Complex is
record
Re : Real := 0.0;
Im : Real := 0.0;
end record Complex;
29Examples of record variables:
Tomorrow, Yesterday : Date;
A, B, C : Complex;
31-- both components of A, B, and C are implicitly initialized to zero
Extensions to Ada 83
component_declaration
is modified to use component_definition
(instead of component_subtype_definition
). The effect of this change is to allow the reserved word aliased before the component_subtype_definition
.record_type_definition
is modified to allow the reserved words tagged and limited. Tagging is new. Limitedness is now orthogonal to privateness. In Ada 83 the syntax implied that limited private was sort of more private than private. However, limitedness really has nothing to do with privateness; limitedness simply indicates the lack of assignment capabilities, and makes perfect sense for nonprivate types such as record types. Wording Changes from Ada 83
aspect_clause
s to appear in a record_definition
. This is not a language extension, because Legality Rules prevent all language-defined representation clauses from appearing there. However, an implementation-defined attribute_definition_clause
could appear there. The reason for this change is to allow the rules for aspect_clause
s and representation pragmas to be as similar as possible. Extensions to Ada 95
aggregate
or function_call
). Wording Changes from Ada 95
Extensions to Ada 2005
aspect_specification
can be used in a component_declaration
. This is described in 13.1.1. Extensions to Ada 2012
3.8.1 Variant Parts and Discrete Choices
1A record type with a variant_part
specifies alternative lists of components. Each variant
defines the components for the value or values of the discriminant covered by its discrete_choice_list
.
Discrete_choice_list
s and discrete_choice
s are said to cover values as defined below; which discrete_choice_list
covers a value determines which of various alternatives is chosen. These are used in variant_part
s, array_aggregate
s, and case_statement
s. Language Design Principles
Syntax
2variant_part
::=
case discriminant_direct_name
is
variant
{variant
}
end case;
3variant
::=
when discrete_choice_list
=>
component_list
4/5discrete_choice_list
::=
discrete_choice
{'|' discrete_choice
}
5/3discrete_choice
::=
choice_expression
| discrete_subtype_indication
| range
| others
Name Resolution Rules
6The discriminant_direct_name
shall resolve to denote a discriminant (called the discriminant of the variant_part
) specified in the known_discriminant_part
of the full_type_declaration
that contains the variant_part
. The expected type for each discrete_choice
in a variant
is the type of the discriminant of the variant_part
.
full_type_declaration
with a variant_part
has to have a (new) known_discriminant_part
; the discriminant of the variant_part
cannot be an inherited discriminant. Legality Rules
7The discriminant of the variant_part
shall be of a discrete type.
The choice_expression
s, subtype_indication
s, and range
s given as discrete_choice
s in a variant_part
shall be static. The discrete_choice
others shall appear alone in a discrete_choice_list
, and such a discrete_choice_list
, if it appears, shall be the last one in the enclosing construct.
A discrete_choice
is defined to cover a value in the following cases:
- A
discrete_choice
that is achoice_expression
covers a value if the value equals the value of thechoice_expression
converted to the expected type. 10.1/4 - A
discrete_choice
that is asubtype_indication
covers all values (possibly none) that belong to the subtype and that satisfy the static predicates of the subtype (see 3.2.4).
variant
s, case_statement
s, and case_expression
s, a subtype with a dynamic predicate isn't static and thus isn't allowed in a discrete_choice
, and for a choice in an array_aggregate
, a dynamic predicate is explicitly disallowed — see 3.2.4). - A
discrete_choice
that is arange
covers all values (possibly none) that belong to the range. 12 - The
discrete_choice
others covers all values of its expected type that are not covered by previousdiscrete_choice_list
s of the same construct.
case_statement
s, this includes values outside the range of the static subtype (if any) to be covered by the choices. It even includes values outside the base range of the case expression's type, since values of numeric types (and undefined values of any scalar type?) can be outside their base range. A discrete_choice_list
covers a value if one of its discrete_choice
s covers the value.
The possible values of the discriminant of a variant_part
shall be covered as follows:
- If the discriminant is of a static constrained scalar subtype then, except within an instance of a generic unit, each non-others
discrete_choice
shall cover only values in that subtype that satisfy its predicates, and each value of that subtype that satisfies its predicates shall be covered by somediscrete_choice
[(either explicitly or by others)];
generic
type T is new Integer;
package G is
type Rec (Discrim : T) is record
case Discrim is
when -10 .. -1 =>
Foo : Float;
when others =>
null;
end case;
end record;
end G;
15.c/3package I is new G (Natural); -- Legal
- If the type of the discriminant is a descendant of a generic formal scalar type, then the
variant_part
shall have an othersdiscrete_choice
;
- Otherwise, each value of the base range of the type of the discriminant shall be covered [(either explicitly or by others)].
Two distinct discrete_choice
s of a variant_part
shall not cover the same value.
Static Semantics
19If the component_list
of a variant
is specified by null, the variant has no components.
The discriminant of a variant_part
is said to govern the variant_part
and its variant
s. In addition, the discriminant of a derived type governs a variant_part
and its variant
s if it corresponds (see 3.7) to the discriminant of the variant_part
.
Dynamic Semantics
21A record value contains the values of the components of a particular variant
only if the value of the discriminant governing the variant
is covered by the discrete_choice_list
of the variant
. This rule applies in turn to any further variant
that is, itself, included in the component_list
of the given variant
.
When an object of a discriminated type T is initialized by default, Constraint_Error is raised if no discrete_choice_list
of any variant
of a variant_part
of T covers the value of the discriminant that governs the variant_part
. When a variant_part
appears in the component_list
of another variant
V, this test is only applied if the value of the discriminant governing V is covered by the discrete_choice_list
of V.
variant_part
which lacks a when others choice.variant_part
which lacks a when others choice. But execution is erroneous if a range check that would have failed is suppressed (see 11.5), so an implementation does not have to generate code to check this case. (An unchecked failed predicate does not cause erroneous execution, so the test is required in that case.)subtype_indication
. The elaboration of a variant_part
consists of the elaboration of the component_list
of each variant
in the order in which they appear.
Examples
23Example of record type with a variant part:
type Device is (Printer, Disk, Drum);
type State is (Open, Closed);
25type Peripheral(Unit : Device := Disk) is
record
Status : State;
case Unit is
when Printer =>
Line_Count : Integer range 1 .. Page_Size;
when others =>
Cylinder : Cylinder_Index;
Track : Track_Number;
end case;
end record;
26Examples of record subtypes:
subtype Drum_Unit is Peripheral(Drum);
subtype Disk_Unit is Peripheral(Disk);
Examples of constrained record variables:
Writer : Peripheral(Unit => Printer);
Archive : Disk_Unit;
Extensions to Ada 83
variant_part
is not allowed to be of a generic formal type. This restriction is removed in Ada 95; an others discrete_choice
is required in this case. Wording Changes from Ada 83
choice
is removed. The syntax rules for variant
, array_aggregate
, and case_statement
now use discrete_choice_list
or discrete_choice
instead. The syntax rule for record_aggregate
now defines its own syntax for named associations.Incompatibilities With Ada 2005
discrete_choice
, in order that those tests can be expanded to allow multiple tests in a single expression without ambiguity. Since a membership test has a boolean type, they are very unlikely to be used as a discrete_choice
. Extensions to Ada 2005
discrete_choice
s, and the coverage rules are modified to respect the predicates.case_expression
s. Wording Changes from Ada 2005
variant
covers the value of a discriminant that governs a variant_part
. This is similar to the test that some case limb covers the value of the Selecting_expression
of a case_statement
. This test cannot change the behavior of any nonerroneous Ada 2005 program, so it is not an inconsistency.