Skip to main content

3.3 Objects and Named Numbers

danger

This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue

1

[Objects are created at run time and contain a value of a given type. An object can be created and initialized as part of elaborating a declaration, evaluating an allocator, aggregate, or function_call, or passing a parameter by copy. Prior to reclaiming the storage for an object, it is finalized if necessary (see 7.6.1).]

Static Semantics

2

All of the following are objects:

2.a/5

Term entry: object — entity that contains a value, and is either a constant or a variable
object_declaration or by an allocator. A formal parameter is (a view of) an object. A subcomponent of an object is an object.

3 13/3

An object is either a constant object or a variable object. Similarly, a view of an object is either a constant or a variable. All views of a constant elementary object are constant. All views of a constant composite object are constant, except for parts that are of controlled or immutably limited types; variable views of those parts and their subcomponents may exist. In this sense, objects of controlled and immutably limited types are inherently mutable. A constant view of an object cannot be used to modify its value. The terms constant and variable by themselves refer to constant and variable views of objects.

13.a/5
ramification

If some part of an object has a variable view, then the object as a whole has a variable view, and not all views of the object are constant. That's true even if only a subcomponent has a variable view.

13.1/5

A constant object is known to have no variable views if it does not have a part that is immutably limited, or of a controlled type, private type, or private extension.

13.b/5
reason

This definition can be used in Legality Rules as it respects privacy. It is an assume-the-worst rule, as all private types and private extensions might have a controlled component.

14

The value of an object is read when the value of any part of the object is evaluated, or when the value of an enclosing object is evaluated. The value of a variable is updated when an assignment is performed to any part of the variable, or when an assignment is performed to an enclosing object.

14.a
ramification

Reading and updating are intended to include read/write references of any kind, even if they are not associated with the evaluation of a particular construct. Consider, for example, the expression “X.all(F)”, where X is an access-to-array object, and F is a function. The implementation is allowed to first evaluate “X.all” and then F. Finally, a read is performed to get the value of the F'th component of the array. Note that the array is not necessarily read as part of the evaluation of “X.all”. This is important, because if F were to free X using Unchecked_Deallocation, we want the execution of the final read to be erroneous.

15/5

Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent variables:

16/5
16.a/2

To be honest: We mean the word constant as defined by the grammar for object_declaration, not some random word constant. Thus,

16.b/2

X : access constant T;

16.c/2

is not a constant.

17/5
  • a formal parameter of mode in out or out;
  • 17.1/5
  • a generic formal object of mode in out;
  • 18/5
  • a non-discriminant component of a variable;
18.a/5
ramification

This includes both selected_components and indexed_components.

18.1/5
  • a slice of a variable;
  • 18.2/5
  • a loop parameter that is specified to be a variable for a generalized loop (see 5.5.2);
  • 19/5
  • a view conversion of a variable;
  • 20/5
  • a dereference of an access-to-variable value;
  • 20.1/5
  • the return object declared by an extended_return_statement without the reserved word constant;
  • 21/5
  • the current instance of a type other than a protected type[, if the current instance is an object and not a value (see 8.6)];
21.a/5
reason

We exclude current instances of protected types as they are protected units and the next bullet applies.

21.b/5
proof

This list of bullets only applies to views of objects, so current instances that are not objects are not considered here.

21.1/5
  • This paragraph was deleted.
  • 21.2/5
  • the current instance of a protected unit except within the body of a protected function of that protected unit, or within a function declared immediately within the body of the protected unit;
  • 22/5
  • an attribute_reference where the attribute is defined to denote a variable (for example, the Storage_Pool attribute – see 13.11).
22.a/5
ramification

In particular, this implies that the following are not variables:

22.b/5
22.g/5

This list of constructs that yield constant views is not exhaustive.

23/5

At the place where a view of an object is defined, a nominal subtype is associated with the view. The nominal type of a view is the type of the nominal subtype of the view. The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is more restrictive if the nominal subtype is an indefinite subtype. A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults (see 3.7); otherwise, the subtype is a definite subtype [(all elementary subtypes are definite subtypes)]. [A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional constraint or explicit initialization expression is necessary (see 3.3.1). A component cannot have an indefinite nominal subtype.]

23.a/5

Term entry: nominal subtype — subtype specified when a view of an object is defined

23.1/3

A view of a composite object is known to be constrained if:

23.2/5
  • its nominal subtype is constrained and not an untagged partial view, and it is neither a value conversion nor a qualified_expression; or
  • 23.3/3
  • its nominal subtype is indefinite; or
  • 23.4/3
  • its type is immutably limited (see 7.5); or
  • 23.5/3
  • it is part of a stand-alone constant (including a generic formal object of mode in); or
  • 23.6/3
  • it is part of a formal parameter of mode in; or
  • 23.7/3
  • it is part of the object denoted by a function_call or aggregate; or
  • 23.8/5
  • it is a value conversion or qualified_expression where the operand denotes a view of a composite object that is known to be constrained; or
  • 23.9/5
  • it is part of a constant return object of an extended_return_statement; or
  • 23.10/5
  • it is a dereference of a pool-specific access type, and there is no ancestor of its type that has a constrained partial view.
23.b/3
discussion

We do not include dereferences of general access types because they might denote stand-alone aliased unconstrained variables. That's true even for access-to-constant types (the denoted object does not have to be a constant).

23.c/5

We don't mention view conversions as there are no mutable tagged types (discriminant defaults are allowed only if the type is immutably limited), so all tagged view conversions are either of an indefinite type (if it has discriminants without defaults), an immutably limited type (if the discriminants do have defaults), or constrained (if there are no discriminants). This matches the first three bullets here, so all tagged view conversions are known to be constrained without needing to mention them explicitly. Untagged view conversions only can occur in parameter passing (as actuals to in out or out parameters), and "known to be constrained" is not used there.

23.d/5

We don't need to mention the current instance of a (sub)type, either. If a current instance of a type or subtype appears in an aspect specification, it represents a value, so whether or not it is known to be constrained is irrelevant (the term is only defined for composite objects). Otherwise, the current instance of a type can only be used in an immutably limited type, so all such instances are known to be constrained by the third bullet.

23.11/5

For the purposes of determining within a generic body whether an object is known to be constrained:

23.12/5
  • if a subtype is a descendant of an untagged generic formal private or derived type, and the subtype is not an unconstrained array subtype, it is not considered indefinite and is considered to have a constrained partial view;
  • 23.13/5
  • if a subtype is a descendant of a formal access type, it is not considered pool-specific.
24

A named number provides a name for a numeric value known at compile time. It is declared by a number_declaration.

25

NOTE 1 A constant cannot be the target of an assignment operation, nor be passed as an in out or out parameter, between its initialization and finalization, if any.

25.1/3

NOTE 2 The value of a constant object cannot be changed after its initialization, except in some cases where the object has a controlled or immutably limited part (see 7.5, 7.6, and 13.9.1).

26/3

NOTE 3 The nominal and actual subtypes of an elementary object are always the same. For a discriminated or array object, if the nominal subtype is constrained, then so is the actual subtype.

Extensions to Ada 83

26.a

There are additional kinds of objects (choice parameters and entry indices of entry bodies).

26.b

The result of a function and of evaluating an aggregate are considered (constant) objects. This is necessary to explain the action of finalization on such things. Because a function_call is also syntactically a name (see 4.1), the result of a function_call can be renamed, thereby allowing repeated use of the result without calling the function again.

Wording Changes from Ada 83

26.c/3

This subclause now follows the subclauses on types and subtypes, to cut down on the number of forward references.

26.d

The term nominal subtype is new. It is used to distinguish what is known at compile time about an object's constraint, versus what its "true" run-time constraint is.

26.e

The terms definite and indefinite (which apply to subtypes) are new. They are used to aid in the description of generic formal type matching, and to specify when an explicit initial value is required in an object_declaration.

26.f

We have moved the syntax for object_declaration and number_declaration down into their respective subclauses, to keep the syntax close to the description of the associated semantics.

26.g

We talk about variables and constants here, since the discussion is not specific to object_declarations, and it seems better to have the list of the kinds of constants juxtaposed with the kinds of objects.

26.h

We no longer talk about indirect updating due to parameter passing. Parameter passing is handled in 6.2 and 6.4.1 in a way that there is no need to mention it here in the definition of read and update. Reading and updating now includes the case of evaluating or assigning to an enclosing object.

Wording Changes from Ada 95

26.i/2

Clarified that the return object is the object created by a function call.

Extensions to Ada 2005

26.j/3

Added wording to allow return objects to be declared as constants, and corrected the definition of return objects as objects.

Wording Changes from Ada 2005

26.k/3
correction

Added a definition of known to be constrained, for use in other rules.

26.l/3
correction

We now recognize the fact that not all declared constant objects are immutable; for those that a variable view can be constructed, they can be changed via that view.

26.m/3
correction

Added the current instance of a protected object to the list of constant views; since the list claims to include all possibilities, it had better include that one.

26.n/3

The result of a qualified_expression is defined to be a constant view and is defined to be an object if the operand of the qualified_expression is an object. These definitions, combined with some grammar changes, allow qualified_expressions to be used in more places. See 4.1 for details.

Incompatibilities With Ada 2012

26.o/5
correction

Corrected the definition of “known to be constrained” so that the status of the operand of value conversions and qualified_expressions is always used to determine whether the property exists. As the rules are ored together, a value conversion or qualified_expression with a constrained nominal subtype would have always met the requirements in Ada 2012, regardless of the operand. This change will mean that some conversions or qualifications (mostly of variables) will no longer be considered “known to be constrained” and therefore 'Access and renaming of such prefixes will now be illegal. This is necessary to meet the design goal that subsequent execution cannot cause a renaming or 'Access to cause erroneous execution.

Extensions to Ada 2012

26.p/5
correction

A qualified_expression of an object that is known to be constrained is now also known to be constrained. This allows qualification to be used to disambiguate a function call used as a prefix in a renaming_declaration without making the renaming_declaration illegal.

26.q/5

A value conversion of an object is an object; this makes value conversions consistent with qualified expressions.

Wording Changes from Ada 2012

26.r/5
correction

Changed from a list of constants to a list of variables. This makes the default to be a constant, which is the more common case, and eliminates issues caused by omissions from the list (such as parenthesized expressions).

26.s/5

Added the term “known to have no variable views” in order to have a definition that can be used in Legality Rules without breaking privacy.

3.3.1 Object Declarations

1/3

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, access, task, or protected object, the object_declaration may include the definition of the (anonymous) type of the object.

Syntax

2/3

object_declaration ::=
defining_identifier_list : [aliased] [constant] subtype_indication [:= expression]
[aspect_specification];
| defining_identifier_list : [aliased] [constant] access_definition [:= expression]
[aspect_specification];
| defining_identifier_list : [aliased] [constant] array_type_definition [:= expression]
[aspect_specification];
| 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/2

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.

Static Semantics

6/5

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 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 Reference Manual relies on this equivalence; explanations are given for declarations with a single defining_identifier.

8/2

The subtype_indication, access_definition, 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/2
discussion

The phrase “full type definition” here includes the case of an anonymous array, access, task, or protected type.

8.1/5

A component of an object is said to require late initialization if:

8.2/5
  • it has an access discriminant value constrained by a per-object expression; or
  • 8.3/5
  • it has an initialization expression that includes a name denoting an access discriminant; or
  • 8.4/5
  • it has an initialization expression that includes a reference to the current instance of the type either by name or implicitly as the target object of a call.
8.b/2
reason

Such components can depend on the values of other components of the object. We want to initialize them as late and as reproducibly as possible.

Dynamic Semantics

9/2

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 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. 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.
  • 11.1/5
  • The implicit initial value for a scalar subtype that has the Default_Value aspect specified is the value of that aspect converted to the nominal subtype (which can raise Constraint_Error — see 4.6, “Type Conversions”);
11.a.1/3
ramification

This is a Dynamic Semantics rule, so the visibility of the aspect_specification is not relevant — if the full type for a private type has the Default_Value aspect specified, partial views of the type also have this implicit initial value.

12
  • The implicit initial (and only) value for each discriminant of a constrained discriminated subtype is defined by the subtype.
  • 13/5
  • 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 can raise Constraint_Error), 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, if the composite subtype has the Default_Component_Value aspect specified, the implicit initial value is the value of that aspect converted to the component's nominal subtype; otherwise, 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/2

1.
The subtype_indication, access_definition, array_type_definition, single_task_declaration, or single_protected_declaration is first elaborated. This creates the nominal subtype (and the anonymous type in the last four cases).
17/5

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 can raise Constraint_Error — see 4.6).
18/2

3.
{8652/0002} The object is created, and, if there is not an initialization expression, the object is initialized by default. When an object is initialized by default, any per-object constraints (see 3.8) are elaborated and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype. 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.
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/2

This paragraph was deleted.
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/2

For the third step above, evaluations and assignments are performed in an arbitrary order subject to the following restrictions:

20.1/2
  • Assignment to any part of the object is preceded by the evaluation of the value that is to be assigned.
20.a.1/2
reason

Duh. But we ought to say it. Note that, like any rule in the Reference Manual, it doesn't prevent an “as-if” optimization; as long as the semantics as observed from the program are correct, the compiler can generate any code it wants.

20.2/2
  • The evaluation of a default_expression that includes the name of a discriminant is preceded by the assignment to that discriminant.
20.a.2/2
reason

Duh again. But we have to say this, too. It's odd that Ada 95 only required the default expressions to be evaluated before the discriminant is used; it says nothing about discriminant values that come from subtype_indications.

20.3/2
  • The evaluation of the default_expression for any component that depends on a discriminant is preceded by the assignment to that discriminant.
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.

20.4/3
  • The assignments to any components, including implicit components, not requiring late initialization precede the initial value evaluations for any components requiring late initialization; if two components both require late initialization, then assignments to parts of the component occurring earlier in the order of the component declarations precede the initial value evaluations of the component occurring later.
20.e/2
reason

Components that require late initialization can refer to the entire object during their initialization. We want them to be initialized as late as possible to reduce the chance that their initialization depends on uninitialized components. For instance:

20.f/2

type T (D : Natural) is limited record C1 : T1 (T'Access); C2 : Natural := F (D); C3 : String (1 .. D) := (others => ' '); end record;

20.g/2

Component C1 requires late initialization. The initialization could depend on the values of any component of T, including D, C2, or C3. Therefore, we want to it to be initialized last. Note that C2 and C3 do not require late initialization; they only have to be initialized after D.

20.h/2

It is possible for there to be more than one component that requires late initialization. In this case, the language can't prevent problems, because all of the components can't be the last one initialized. In this case, we specify the order of initialization for components requiring late initialization; by doing so, programmers can arrange their code to avoid accessing uninitialized components, and such arrangements are portable. Note that if the program accesses an uninitialized component, 13.9.1 defines the execution to be erroneous.

21/5

[There is no implicit initial value defined for a scalar subtype unless the Default_Value aspect has been specified for the type.] In the absence of an explicit initialization or the specification of the Default_Value aspect, a newly created scalar object can 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

NOTE 1 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/5

NOTE 2 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, iterator_specification, iterated_component_association, chunk_specification, parameter_specification, entry_index_specification, choice_parameter_specification, extended_return_statement, or a formal_object_declaration of mode in out is not considered a stand-alone object.

24

NOTE 3 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/2

John, Paul : not null Person_Name := new Person(Sex => M); -- see 3.10.1 28 -- is equivalent to the two single object declarations in the order given 29/2

John : not null Person_Name := new Person(Sex => M); Paul : not null Person_Name := new Person(Sex => M);

30

Examples of variable declarations:

31/5

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); -- see 3.6 Hello : aliased String := "Hi, world."; θ, φ : Float range -π .. +π;

32

Examples of constant declarations:

33/5

Limit : constant Integer := 10_000; Low_Limit : constant Integer := Limit/10; Tolerance : constant Real := Dispersion(1.15); A_String : constant String := "A"; Hello_Msg : constant access String := Hello'Access; -- see 3.10.2

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.

Inconsistencies With Ada 95

33.f/2

Unconstrained aliased objects of types with discriminants with defaults are no longer constrained by their initial values. This means that a program that raised Constraint_Error from an attempt to change the discriminants will no longer do so. The change only affects programs that depended on the raising of Constraint_Error in this case, so the inconsistency is unlikely to occur outside of the ACATS. This change may however cause compilers to implement these objects differently, possibly taking additional memory or time. This is unlikely to be worse than the differences caused by any major compiler upgrade.

Extensions to Ada 95

33.g/2

A constant may have a limited type; the initialization expression has to be built-in-place (see 7.5).

33.h/2

A stand-alone object may have an anonymous access type.

Wording Changes from Ada 95

33.i/2

{8652/0002} Corrigendum: Corrected wording to say that per-object constraints are elaborated (not evaluated).

33.j/2

The rules for evaluating default initialization have been tightened. In particular, components whose default initialization can refer to the rest of the object are required to be initialized last.

33.k/2

Added examples of various new constructs.

Extensions to Ada 2005

33.l/3

An optional aspect_specification can be used in an object_declaration. This is described in 13.1.1.

Wording Changes from Ada 2005

33.m/3

Implicit initial values can now be given for scalar types and for scalar array components, using the Default_Value (see 3.5) and Default_Component_Value (see 3.6) aspects; the extension is documented there.

Inconsistencies With Ada 2012

33.n/5
correction

Components of a protected type require late initialization if their initialization includes (implicitly) the current instance of the type. This means that the components could end up being initialized in a different order. In most cases, this will have no visible effect, or will even fix bugs. Most code for which this is an issue depends on the (unspecified) order of initialization, so it is at risk of failing with a new compiler version regardless of Ada rule changes. However, there do exist very unlikely cases where legal, portable Ada 2012 code would become erroneous. (See the discussion section of for an example.) These are so unlikely that it is expected that they only exist in the minds of Ada lawyers.

3.3.2 Number Declarations

1

A number_declaration declares a named number.

1.a/5
discussion

If a value or other property of a construct is required to be static that means it is required to be determined prior to execution. A static expression is an expression whose value is computed at compile time and is usable in contexts where the actual value might affect the legality of the construct. This is fully defined in 4.9.

Syntax

2

number_declaration ::=
defining_identifier_list : constant := static_expression;

Name Resolution Rules

3

The static_expression given for a number_declaration is expected to be of any numeric type.

3.1/5

A name that denotes a number_declaration is interpreted as a value of a universal type, unless the expected type for the name is a non-numeric type with an Integer_Literal or Real_Literal aspect, in which case it is interpreted to be of its expected type.

3.a/5

To be honest: This is only a Name Resolution Rule; all named numbers are values of a universal type (see the Static Semantics below). We need this rule so that named numbers can match types with user-defined literals; we need the other rules so the value of the named number is well-defined in all cases.

Legality Rules

4/5

The static_expression given for a number declaration shall be a static expression, as defined by 4.9.

Static Semantics

5

The named number denotes a value of type universal_integer if the type of the static_expression is an integer type. The named number denotes a value of type universal_real if the type of the static_expression is a real type.

6

The value denoted by the named number is the value of the static_expression, converted to the corresponding universal type.

Dynamic Semantics

7

The elaboration of a number_declaration has no effect.

7.a
proof

Since the static_expression was evaluated at compile time.

Examples

8

Examples of number declarations:

9

Two_Pi : constant := 2.0*Ada.Numerics.Pi; -- a real number (see A.5) 10/2

Max : constant := 500; -- an integer number Max_Line_Size : constant := Max/6; -- the integer 83 Power_16 : constant := 2**16; -- the integer 65_536 One, Un, Eins : constant := 1; -- three different names for 1

Extensions to Ada 83

10.a

We now allow a static expression of any numeric type to initialize a named number. For integer types, it was possible in Ada 83 to use 'Pos to define a named number, but there was no way to use a static expression of some nonuniversal real type to define a named number. This change is upward compatible because of the preference rule for the operators of the root numeric types.

Wording Changes from Ada 83

10.b

We have moved the syntax rule into this subclause.

10.c

AI83-00263 describes the elaboration of a number declaration in words similar to that of an object_declaration. However, since there is no expression to be evaluated and no object to be created, it seems simpler to say that the elaboration has no effect.

Extensions to Ada 2012

10.d/5

Named numbers now can be used with (non-numeric) types that define user-defined literals (see 4.2.1).