Contents Index Previous Next
3.3.1 Object Declarations
1
An
object_declaration declares a
stand-alone
object with a given nominal subtype and, optionally, an explicit initial
value given by an initialization expression.
For
an array, task, or protected object, the
object_declaration
may include the definition of the (anonymous) type of the object.
Syntax
2
object_declaration
::=
defining_identifier_list : [
aliased] [
constant]
subtype_indication [:=
expression];
|
defining_identifier_list : [
aliased] [
constant]
array_type_definition [:=
expression];
|
single_task_declaration
|
single_protected_declaration
3
defining_identifier_list
::=
defining_identifier {,
defining_identifier}
Name Resolution Rules
4
For an
object_declaration
with an
expression following the
compound delimiter :=, the type expected for the
expression
is that of the object.
This
expression
is called the
initialization expression.
Legality Rules
5
An object_declaration
without the reserved word constant declares a variable object.
If it has a subtype_indication or
an array_type_definition that defines
an indefinite subtype, then there shall be an initialization expression.
An initialization expression shall not be given if the object is of a
limited type.
Static Semantics
6
An
object_declaration
with the reserved word
constant declares a constant object.
If
it has an initialization expression, then it is called a
full constant
declaration.
Otherwise it is called a
deferred
constant declaration. The rules for deferred constant declarations
are given in clause
7.4. The rules for full
constant declarations are given in this subclause.
7
Any declaration that includes a defining_identifier_list
with more than one defining_identifier
is equivalent to a series of declarations each containing one defining_identifier
from the list, with the rest of the text of the declaration copied for
each declaration in the series, in the same order as the list. The remainder
of this International Standard relies on this equivalence; explanations
are given for declarations with a single defining_identifier.
8
The
subtype_indication
or full type definition of an
object_declaration
defines the nominal subtype of the object. The
object_declaration
declares an object of the type of the nominal subtype.
8.a
Discussion: The phrase
``full type definition'' here includes the case of an anonymous array,
task, or protected type.
Dynamic Semantics
9
If a composite object declared
by an
object_declaration has an
unconstrained nominal subtype, then if this subtype is indefinite or
the object is constant or aliased (see
3.10)
the actual subtype of this object is constrained. The constraint is determined
by the bounds or discriminants (if any) of its initial value;
the
object is said to be
constrained by its initial value.
[In
the case of an aliased object, this initial value may be either explicit
or implicit; in the other cases, an explicit initial value is required.]
When not constrained by its initial value, the actual and nominal subtypes
of the object are the same.
If
its actual subtype is constrained, the object is called a
constrained
object.
10
For
an
object_declaration without an
initialization expression, any initial values for the object or its subcomponents
are determined by the
implicit initial values defined for its
nominal subtype, as follows:
11
- The implicit initial value for an access subtype is the
null value of the access type.
12
- The implicit initial (and only) value for each discriminant
of a constrained discriminated subtype is defined by the subtype.
13
- For a (definite) composite subtype, the implicit initial
value of each component with a default_expression
is obtained by evaluation of this expression and conversion to the component's
nominal subtype (which might raise Constraint_Error -- see 4.6,
``Type Conversions''), unless the component
is a discriminant of a constrained subtype (the previous case), or is
in an excluded variant (see 3.8.1).
For each component that does not have a default_expression,
any implicit initial values are those determined by the component's nominal
subtype.
14
- For a protected or task subtype, there is an implicit component
(an entry queue) corresponding to each entry, with its implicit initial
value being an empty queue.
14.a
Implementation Note: The
implementation may add implicit components for its own use, which might
have implicit initial values. For a task subtype, such components might
represent the state of the associated thread of control. For a type with
dynamic-sized components, such implicit components might be used to hold
the offset to some explicit component.
15
The
elaboration of an
object_declaration
proceeds in the following sequence of steps:
16
- 1.
-
The subtype_indication, array_type_definition,
single_task_declaration, or single_protected_declaration
is first elaborated. This creates the nominal subtype (and the anonymous
type in the latter three cases).
17
- 2.
-
If the object_declaration includes
an initialization expression, the (explicit) initial value is obtained
by evaluating the expression and converting it to the nominal subtype
(which might raise Constraint_Error -- see 4.6).
18/1
- 3.
-
{8652/0002} The object is
created, and, if there is not an initialization expression, any per-object
expressions (see 3.8) are elaborated
evaluated
and any implicit initial values for the object or for its subcomponents
are obtained as determined by the nominal subtype.
18.a
Discussion: For a per-object
constraint that contains some per-object expressions and some non-per-object
expressions, the values used for the constraint consist of the values
of the non-per-object expressions evaluated at the point of the type_declaration,
and the values of the per-object expressions evaluated at the point of
the creation of the object.
18.b
The elaboration of per-object
constraints was presumably performed as part of the dependent compatibility
check in Ada 83. If the object is of a limited type with an access discriminant,
the access_definition is elaborated
at this time (see 3.7).
18.c
Reason: The reason we say
that evaluating an explicit initialization expression happens before
creating the object is that in some cases it is impossible to know the
size of the object being created until its initial value is known, as
in ``X: String := Func_Call(...);''. The implementation can create the
object early in the common case where the size can be known early, since
this optimization is semantically neutral.
19
- 4.
-
Any initial values (whether explicit
or implicit) are assigned to the object or to the corresponding subcomponents.
As described in 5.2 and 7.6,
Initialize and Adjust procedures can be called.
19.a
Ramification: Since the
initial values have already been converted to the appropriate nominal
subtype, the only Constraint_Errors that might occur as part of these
assignments are for values outside their base range that are used to
initialize unconstrained numeric subcomponents. See 3.5.
20
For the third step above, the object creation
and any elaborations and evaluations are performed in an arbitrary order,
except that if the default_expression
for a discriminant is evaluated to obtain its initial value, then this
evaluation is performed before that of the default_expression
for any component that depends on the discriminant, and also before that
of any default_expression that includes
the name of the discriminant. The evaluations of the third step and the
assignments of the fourth step are performed in an arbitrary order, except
that each evaluation is performed before the resulting value is assigned.
20.a
Reason:
For example:
20.b
type R(D : Integer := F) is
record
S : String(1..D) := (others => G);
end record;
20.c
X : R;
20.d
For the elaboration of the declaration
of X, it is important that F be evaluated before the aggregate.
21
[There is no implicit initial value defined for
a scalar subtype.]
In the absence of an explicit
initialization, a newly created scalar object might have a value that
does not belong to its subtype (see
13.9.1
and
H.1).
21.a
To be honest: It could
even be represented by a bit pattern that doesn't actually represent
any value of the type at all, such as an invalid internal code for an
enumeration type, or a NaN for a floating point type. It is a generally
a bounded error to reference scalar objects with such ``invalid representations'',
as explained in 13.9.1, ``Data
Validity''.
21.b
Ramification: There is
no requirement that two objects of the same scalar subtype have the same
implicit initial ``value'' (or representation). It might even be the
case that two elaborations of the same object_declaration
produce two different initial values. However, any particular uninitialized
object is default-initialized to a single value (or invalid representation).
Thus, multiple reads of such an uninitialized object will produce the
same value each time (if the implementation chooses not to detect the
error).
22
7 Implicit initial values
are not defined for an indefinite subtype, because if an object's nominal
subtype is indefinite, an explicit initial value is required.
23
8 As
indicated above, a stand-alone object is an object declared by an object_declaration.
Similar definitions apply to ``stand-alone constant'' and ``stand-alone
variable.'' A subcomponent of an object is not a stand-alone object,
nor is an object that is created by an allocator.
An object declared by a loop_parameter_specification,
parameter_specification, entry_index_specification,
choice_parameter_specification,
or a formal_object_declaration is
not called a stand-alone object.
24
9 The type of a stand-alone
object cannot be abstract (see 3.9.3).
Examples
25
Example of a
multiple object declaration:
26
-- the multiple object declaration
27
John, Paul : Person_Name := new Person(Sex => M); -- see 3.10.1
28
-- is equivalent to the two single object declarations in the order given
29
John : Person_Name := new Person(Sex => M);
Paul : Person_Name := new Person(Sex => M);
30
Examples of variable
declarations:
31
Count, Sum : Integer;
Size : Integer range 0 .. 10_000 := 0;
Sorted : Boolean := False;
Color_Table : array(1 .. Max) of Color;
Option : Bit_Vector(1 .. 10) := (others => True);
Hello : constant String := "Hi, world.";
32
Examples of constant
declarations:
33
Limit : constant Integer := 10_000;
Low_Limit : constant Integer := Limit/10;
Tolerance : constant Real := Dispersion(1.15);
Extensions to Ada 83
33.a
The syntax
rule for object_declaration is modified
to allow the aliased reserved word.
33.b
A variable declared by an object_declaration
can be constrained by its initial value; that is, a variable of a nominally
unconstrained array subtype, or discriminated type without defaults,
can be declared so long as it has an explicit initial value. In Ada 83,
this was permitted for constants, and for variables created by allocators,
but not for variables declared by object_declarations.
This is particularly important for tagged class-wide types, since there
is no way to constrain them explicitly, and so an initial value is the
only way to provide a constraint. It is also important for generic formal
private types with unknown discriminants.
33.c
We now allow an unconstrained_array_definition
in an object_declaration. This allows
an object of an anonymous array type to have its bounds determined by
its initial value. This is for uniformity: If one can write ``X: constant
array(Integer range 1..10) of Integer := ...;''
then it makes sense to also allow ``X: constant array(Integer
range <>) of Integer := ...;''. (Note that if anonymous
array types are ever sensible, a common situation is for a table implemented
as an array. Tables are often constant, and for constants, there's usually
no point in forcing the user to count the number of elements in the value.)
Wording Changes from Ada 83
33.d
We have moved the syntax for object_declarations
into this subclause.
33.e
Deferred constants no longer have
a separate syntax rule, but rather are incorporated in object_declaration
as constants declared without an initialization expression.
Contents Index Previous Next Legal