Skip to main content

4.1 Names

danger

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

1

[Names can denote declared entities, whether declared explicitly or implicitly (see 3.1). Names can also denote objects or subprograms designated by access values; the results of type_conversions or function_calls; subcomponents and slices of objects and values; protected subprograms, single entries, entry families, and entries in families of entries. Finally, names can denote attributes of any of the foregoing.]

Syntax

2/5

name ::=
direct_name | explicit_dereference
| indexed_component | slice
| selected_component | attribute_reference
| type_conversion | function_call
| character_literal | qualified_expression
| generalized_reference | generalized_indexing
| target_name

3

direct_name ::= identifier | operator_symbol

3.a/2
discussion

character_literal is no longer a direct_name. character_literals are usable even when the corresponding enumeration type declaration is not visible. See 4.2.

4

prefix ::= name | implicit_dereference

5

explicit_dereference ::= name.all

6
implicit_dereference ::= name
7/3

[Certain forms of name (indexed_components, selected_components, slices, and attribute_references) include a prefix that is either itself a name that denotes some related entity, or an implicit_dereference of an access value that designates some related entity.]

Name Resolution Rules

8

The name in a dereference (either an implicit_dereference or an explicit_dereference) is expected to be of any access type.

Static Semantics

9/3

If the type of the name in a dereference is some access-to-object type T, then the dereference denotes a view of an object, the nominal subtype of the view being the designated subtype of T. If the designated subtype has unconstrained discriminants, the (actual) subtype of the view is constrained by the values of the discriminants of the designated object, except when there is a partial view of the type of the designated subtype that does not have discriminants, in which case the dereference is not constrained by its discriminant values.

9.a
ramification

If the value of the name is the result of an access type conversion, the dereference denotes a view created as part of the conversion. The nominal subtype of the view is not necessarily the same as that used to create the designated object. See 4.6.

9.b

To be honest: We sometimes refer to the nominal subtype of a particular kind of name rather than the nominal subtype of the view denoted by the name (presuming the name denotes a view of an object). These two uses of nominal subtype are intended to mean the same thing.

9.c/3
reason

The last sentence was not present in Ada 95; it is necessary in Ada 2005 because general access types can designate unconstrained objects, which was not possible in Ada 95. Thus, the rules that had this effect in Ada 95 (the object being constrained by its initial value) don't work in Ada 2005 and we have to say this explicitly.

9.d/3

The “except” part of the last sentence prevents privacy “breaking”, so that if a private type has discriminants only in the full view, they don't interfere with freely interassigning values between objects of the type, even when the objects live in the heap.

9.e/3
implementation note

Since we don't depend on whether the designated object is constrained, it is not necessary to include a constrained bit in every object that could be designated by a general access type.

10

If the type of the name in a dereference is some access-to-subprogram type S, then the dereference denotes a view of a subprogram, the profile of the view being the designated profile of S.

10.a
ramification

This means that the formal parameter names and default expressions to be used in a call whose name or prefix is a dereference are those of the designated profile, which need not be the same as those of the subprogram designated by the access value, since 'Access requires only subtype conformance, not full conformance.

Dynamic Semantics

11/2

The evaluation of a name determines the entity denoted by the name. This evaluation has no other effect for a name that is a direct_name or a character_literal.

12

[The evaluation of a name that has a prefix includes the evaluation of the prefix.] The evaluation of a prefix consists of the evaluation of the name or the implicit_dereference. The prefix denotes the entity denoted by the name or the implicit_dereference.

13

The evaluation of a dereference consists of the evaluation of the name and the determination of the object or subprogram that is designated by the value of the name. A check is made that the value of the name is not the null access value. Constraint_Error is raised if this check fails. The dereference denotes the object or subprogram designated by the value of the name.

Examples

14

Examples of direct names:

15

Pi -- the direct name of a number (see 3.3.2) Limit -- the direct name of a constant (see 3.3.1) Count -- the direct name of a scalar variable (see 3.3.1) Board -- the direct name of an array variable (see 3.6.1) Matrix -- the direct name of a type (see 3.6) Random -- the direct name of a function (see 6.1) Error -- the direct name of an exception (see 11.1)

16

Examples of dereferences:

17

Next_Car.all -- explicit dereference denoting the object designated -- by the access variable Next_Car (see 3.10.1) Next_Car.Owner -- selected component with implicit dereference; -- same as Next_Car.all.Owner

Extensions to Ada 83

17.a

Type conversions and function calls are now considered names that denote the result of the operation. In the case of a type conversion used as an actual parameter or that is of a tagged type, the type conversion is considered a variable if the operand is a variable. This simplifies the description of "parameters of the form of a type conversion" as well as better supporting an important OOP paradigm that requires the combination of a conversion from a class-wide type to some specific type followed immediately by component selection. Function calls are considered names so that a type conversion of a function call and the function call itself are treated equivalently in the grammar. A function call is considered the name of a constant, and can be used anywhere such a name is permitted. See 6.5.

17.b/1

Type conversions of a tagged type are permitted anywhere their operand is permitted. That is, if the operand is a variable, then the type conversion can appear on the left-hand side of an assignment_statement. If the operand is an object, then the type conversion can appear in an object renaming or as a prefix. See 4.6.

Wording Changes from Ada 83

17.c/2

Everything of the general syntactic form name(...) is now syntactically a name. In any realistic parser, this would be a necessity since distinguishing among the various name(...) constructs inevitably requires name resolution. In cases where the construct yields a value rather than an object, the name denotes a value rather than an object. Names already denote values in Ada 83 with named numbers, components of the result of a function call, etc. This is partly just a wording change, and partly an extension of functionality (see Extensions heading above).

17.d

The syntax rule for direct_name is new. It is used in places where direct visibility is required. It's kind of like Ada 83's simple_name, but simple_name applied to both direct visibility and visibility by selection, and furthermore, it didn't work right for operator_symbols. The syntax rule for simple_name is removed, since its use is covered by a combination of direct_name and selector_name. The syntactic categories direct_name and selector_name are similar; it's mainly the visibility rules that distinguish the two. The introduction of direct_name requires the insertion of one new explicit textual rule: to forbid statement_identifiers from being operator_symbols. This is the only case where the explicit rule is needed, because this is the only case where the declaration of the entity is implicit. For example, there is no need to syntactically forbid (say) “X: "Rem";”, because it is impossible to declare a type whose name is an operator_symbol in the first place.

17.e/3

The syntax rules for explicit_dereference and implicit_dereference are new; this makes other rules simpler, since dereferencing an access value has substantially different semantics from selected_components. We also use name instead of prefix in the explicit_dereference rule since that seems clearer. Note that these rules rely on the fact that function calls are now names, so we don't need to use prefix to allow function calls in front of .all.

17.f
discussion

Actually, it would be reasonable to allow any primary in front of .all, since only the value is needed, but that would be a bit radical.

17.g

We no longer use the term appropriate for a type since we now describe the semantics of a prefix in terms of implicit dereference.

Extensions to Ada 2005

17.h/3

A qualified_expression is now a name denoting a constant view; this allows them to be used as a prefix and to be renamed as an object. They are often used to remove ambiguity from function calls, and there may be no other way to do that. Interestingly, a type_conversion of a qualified_expression is already legal in these contexts, so this change mainly reduces clutter by eliminating an otherwise unneeded type_conversion from some expressions.

Wording Changes from Ada 2005

17.i/3
correction

Added a missing rule so that most dereferences are assumed constrained (without determining whether the designated object is). This is just confirming the Ada 95 rules; Ada 2005 failed to ensure that this property was unchanged.

17.j/3

Added generalized_reference and generalized_indexing as types of name; these are documented as extensions in the appropriate subclauses.

Wording Changes from Ada 2012

17.k/5

Added a target_name (see 5.2.1) to the syntax of name.

4.1.1 Indexed Components

1

[An indexed_component denotes either a component of an array or an entry in a family of entries. ]

Syntax

2

indexed_component ::= prefix(expression {, expression})

Name Resolution Rules

3

The prefix of an indexed_component with a given number of expressions shall resolve to denote an array (after any implicit dereference) with the corresponding number of index positions, or shall resolve to denote an entry family of a task or protected object (in which case there shall be only one expression).

4

The expected type for each expression is the corresponding index type.

Static Semantics

5

When the prefix denotes an array, the indexed_component denotes the component of the array with the specified index value(s). The nominal subtype of the indexed_component is the component subtype of the array type.

6

When the prefix denotes an entry family, the indexed_component denotes the individual entry of the entry family with the specified index value.

Dynamic Semantics

7

For the evaluation of an indexed_component, the prefix and the expressions are evaluated in an arbitrary order. The value of each expression is converted to the corresponding index type. A check is made that each index value belongs to the corresponding index range of the array or entry family denoted by the prefix. Constraint_Error is raised if this check fails.

Examples

8

Examples of indexed components:

9

My_Schedule(Sat) -- a component of a one-dimensional array (see 3.6.1) Page(10) -- a component of a one-dimensional array (see 3.6) Board(M, J + 1) -- a component of a two-dimensional array (see 3.6.1) Page(10)(20) -- a component of a component (see 3.6) Request(Medium) -- an entry in a family of entries (see 9.1) Next_Frame(L)(M, N) -- a component of a function call (see 6.1)

10/5

Distinct notations are used for components of multidimensional arrays (such as Board) and arrays of arrays (such as Page). The components of an array of arrays are arrays and can therefore be indexed. Thus Page(10)(20) denotes the 20th component of Page(10). In the last example Next_Frame(L) is a function call returning an access value that designates a two-dimensional array.

4.1.2 Slices

1

[ A slice denotes a one-dimensional array formed by a sequence of consecutive components of a one-dimensional array. A slice of a variable is a variable; a slice of a constant is a constant;] a slice of a value is a value.

Syntax

2

slice ::= prefix(discrete_range)

Name Resolution Rules

3

The prefix of a slice shall resolve to denote a one-dimensional array (after any implicit dereference).

4

The expected type for the discrete_range of a slice is the index type of the array type.

Static Semantics

5

A slice denotes a one-dimensional array formed by the sequence of consecutive components of the array denoted by the prefix, corresponding to the range of values of the index given by the discrete_range.

6

The type of the slice is that of the prefix. Its bounds are those defined by the discrete_range.

Dynamic Semantics

7

For the evaluation of a slice, the prefix and the discrete_range are evaluated in an arbitrary order. If the slice is not a null slice (a slice where the discrete_range is a null range), then a check is made that the bounds of the discrete_range belong to the index range of the array denoted by the prefix. Constraint_Error is raised if this check fails.

8/5

NOTE 1 By the rules given in 3.10.2, a slice is illegal as the prefix of an Access attribute_reference, even if the components or the array as a whole are aliased.

8.a
proof

Slices are not aliased, by 3.10, “Access Types”.

8.b
reason

This is to ease implementation of general-access-to-array. If slices were aliased, implementations would need to store array dope with the access values, which is not always desirable given access-to-incomplete types completed in a package body.

9

NOTE 2 For a one-dimensional array A, the slice A(N .. N) denotes an array that has only one component; its type is the type of A. On the other hand, A(N) denotes a component of the array A and has the corresponding component type.

Examples

10

Examples of slices:

11

Stars(1 .. 15) -- a slice of 15 characters (see 3.6.3) Page(10 .. 10 + Size) -- a slice of 1 + Size components (see 3.6) Page(L)(A .. B) -- a slice of the array Page(L) (see 3.6) Stars(1 .. 0) -- a null slice (see 3.6.3) My_Schedule(Weekday) -- bounds given by subtype (see 3.6.1 and 3.5.1) Stars(5 .. 15)(K) -- same as Stars(K) (see 3.6.3) -- provided that K is in 5 .. 15

4.1.3 Selected Components

1

[Selected_components are used to denote components (including discriminants), entries, entry families, and protected subprograms; they are also used as expanded names as described below. ]

Syntax

2

selected_component ::= prefix . selector_name

3

selector_name ::= identifier | character_literal | operator_symbol

Name Resolution Rules

4

A selected_component is called an expanded name if, according to the visibility rules, at least one possible interpretation of its prefix denotes a package or an enclosing named construct (directly, not through a subprogram_renaming_declaration or generic_renaming_declaration).

4.a
discussion

See AI83-00187.

5

A selected_component that is not an expanded name shall resolve to denote one of the following:

5.a
ramification

If the prefix of a selected_component denotes an enclosing named construct, then the selected_component is interpreted only as an expanded name, even if the named construct is a function that could be called without parameters.

6
7.a/3
reason

The components of a protected object cannot be named except by an expanded name, even from within the corresponding protected body. The protected body cannot reference the private components of some arbitrary object of the protected type; the protected body may reference components of the current instance only (by an expanded name or a direct_name).

7.b
ramification

Only the discriminants and components visible at the place of the selected_component can be selected, since a selector_name can only denote declarations that are visible (see 8.3).

8
  • A single entry, an entry family, or a protected subprogram:
  • 9
  • The prefix shall resolve to denote an object or value of some task or protected type (after any implicit dereference). The selector_name shall resolve to denote an entry_declaration or subprogram_declaration occurring (implicitly or explicitly) within the visible part of that type. The selected_component denotes the corresponding entry, entry family, or protected subprogram.
9.a
reason

This explicitly says “visible part” because even though the body has visibility on the private part, it cannot call the private operations of some arbitrary object of the task or protected type, only those of the current instance (and expanded name notation has to be used for that).

9.1/2
  • A view of a subprogram whose first formal parameter is of a tagged type or is an access parameter whose designated type is tagged:
  • 9.2/3
  • The prefix (after any implicit dereference) shall resolve to denote an object or value of a specific tagged type T or class-wide type T'Class. The selector_name shall resolve to denote a view of a subprogram declared immediately within the declarative region in which an ancestor of the type T is declared. The first formal parameter of the subprogram shall be of type T, or a class-wide type that covers T, or an access parameter designating one of these types. The designator of the subprogram shall not be the same as that of a component of the tagged type visible at the point of the selected_component. The subprogram shall not be an implicitly declared primitive operation of type T that overrides an inherited subprogram implemented by an entry or protected subprogram visible at the point of the selected_component. The selected_component denotes a view of this subprogram that omits the first formal parameter. This view is called a prefixed view of the subprogram, and the prefix of the selected_component (after any implicit dereference) is called the prefix of the prefixed view.
9.b/3
discussion

The part of the rule that excludes a primitive overriding subprogram as a selector applies only to the wrapper subprogram that is implicitly declared to override a subprogram inherited from a synchronized interface that is implemented by an operation of a task or protected type (see 9.1 and 9.4). We don't want calls that use a prefixed view to be ambiguous between the wrapper subprogram and the implementing entry or protected operation. Note that it is illegal to declare an explicit primitive that has a prefixed view that is homographic with one of the type's operations, so in normal cases it isn't possible to have an ambiguity in a prefix call. However, a class-wide operation of an ancestor type that is declared in the same declaration list with the ancestor type is also considered, and that can still make a call ambiguous.

10

An expanded name shall resolve to denote a declaration that occurs immediately within a named declarative region, as follows:

11
  • The prefix shall resolve to denote either a package [(including the current instance of a generic package, or a rename of a package)], or an enclosing named construct.
  • 12
  • The selector_name shall resolve to denote a declaration that occurs immediately within the declarative region of the package or enclosing construct [(the declaration shall be visible at the place of the expanded name — see 8.3)]. The expanded name denotes that declaration.
12.a
ramification

Hence, a library unit or subunit can use an expanded name to refer to the declarations within the private part of its parent unit, as well as to other children that have been mentioned in with_clauses.

13
  • If the prefix does not denote a package, then it shall be a direct_name or an expanded name, and it shall resolve to denote a program unit (other than a package), the current instance of a type, a block_statement, a loop_statement, or an accept_statement (in the case of an accept_statement or entry_body, no family index is allowed); the expanded name shall occur within the declarative region of this construct. Further, if this construct is a callable construct and the prefix denotes more than one such enclosing callable construct, then the expanded name is ambiguous, independently of the selector_name.

Legality Rules

13.1/5

For a prefixed view of a subprogram whose first formal parameter is an access parameter, the prefix shall be legal as the prefix of an attribute_reference with attribute_designator Access appearing as the first actual parameter in a call on the unprefixed view of the subprogram.

13.a/5
ramification

This rule prevents, for instance, using a nonaliased prefix in such a prefixed view. It also prevents using discriminant-dependent components as the prefix of such a prefixed view if those components would not be allowed to be renamed.

13.2/2

For a subprogram whose first parameter is of mode in out or out, or of an anonymous access-to-variable type, the prefix of any prefixed view shall denote a variable.

13.b/2
reason

We want calls through a prefixed view and through a normal view to have the same legality. Thus, the implicit 'Access in this new notation needs the same legality check that an explicit 'Access would have. Similarly, we need to prohibit the object from being constant if the first parameter of the subprogram is in out, because that is (obviously) prohibited for passing a normal parameter.

Dynamic Semantics

14

The evaluation of a selected_component includes the evaluation of the prefix.

15

For a selected_component that denotes a component of a variant, a check is made that the values of the discriminants are such that the value or object denoted by the prefix has this component. The exception Constraint_Error is raised if this check fails.

Examples

16

Examples of selected components:

17/5

Tomorrow.Month -- a record component (see 3.8) Next_Car.Owner -- a record component (see 3.10.1) Next_Car.Owner.Age -- a record component (see 3.10.1) -- the previous two lines involve implicit dereferences Writer.Unit -- a record component (a discriminant) (see 3.8.1) Min_Cell(H).Value -- a record component of the result (see 6.1) -- of the function call Min_Cell(H) Cashier.Append -- a prefixed view of a procedure (see 3.9.4) Control.Seize -- an entry of a protected object (see 9.4) Pool(K).Write -- an entry of the task Pool(K) (see 9.1)

18

Examples of expanded names:

19

Key_Manager."<" -- an operator of the visible part of a package (see 7.3.1) Dot_Product.Sum -- a variable declared in a function body (see 6.1) Buffer.Pool -- a variable declared in a protected unit (see 9.11) Buffer.Read -- an entry of a protected unit (see 9.11) Swap.Temp -- a variable declared in a block statement (see 5.6) Standard.Boolean -- the name of a predefined type (see A.1)

Extensions to Ada 83

19.a

We now allow an expanded name to use a prefix that denotes a rename of a package, even if the selector is for an entity local to the body or private part of the package, so long as the entity is visible at the place of the reference. This eliminates a preexisting anomaly where references in a package body may refer to declarations of its visible part but not those of its private part or body when the prefix is a rename of the package.

Wording Changes from Ada 83

19.b

The syntax rule for selector_name is new. It is used in places where visibility, but not necessarily direct visibility, is required. See 4.1, “Names” for more information.

19.c

The description of dereferencing an access type has been moved to 4.1, “Names”; name.all is no longer considered a selected_component.

19.d

The rules have been restated to be consistent with our new terminology, to accommodate class-wide types, etc.

Extensions to Ada 95

19.e/2

The prefixed view notation for tagged objects is new. This provides a similar notation to that used in other popular languages, and also reduces the need for use_clauses. This is sometimes known as “distinguished receiver notation”.

19.f/2

Given the following definitions for a tagged type T:

19.g/2

procedure Do_Something (Obj : in out T; Count : in Natural); procedure Do_Something_Else (Obj : access T; Flag : in Boolean); My_Object : aliased T;

19.h/2

the following calls are equivalent:

19.i/2

Do_Something (My_Object, Count => 10); My_Object.Do_Something (Count => 10);

19.j/2

as are the following calls:

19.k/2

Do_Something_Else (My_Object'Access, Flag => True); My_Object.Do_Something_Else (Flag => True);

Wording Changes from Ada 2005

19.l/3
correction

Corrected the definition of a prefixed view to ignore the implicit subprograms declared for “implemented by” entries and protected subprograms.

Incompatibilities With Ada 2012

19.m/5
correction

Added a rule to ensure that all reasons that the prefix of an Access attribute can be illegal are covered by the rule for the implicit Access attribute of a prefixed view. If the object is a subcomponent that depends on discriminants or fails a static accessibility check, Ada 2012 would have allowed the prefix while Ada 2022 would not. This violated the principle that a prefixed view and a normal call have the same semantics; practically, the code may not have worked anyway if a compiler implemented generalized indexing by code expansion into the canonical form. Thus, such code wasn't practically portable.

4.1.4 Attributes

1

[An attribute is a characteristic of an entity that can be queried via an attribute_reference or a range_attribute_reference.]

1.a/5

Term entry: attribute — characteristic or property of an entity that can be queried, and in some cases specified

Syntax

2/5

attribute_reference ::=
prefix'attribute_designator
| reduction_attribute_reference

3/2

attribute_designator ::=
identifier[(static_expression)]
| Access | Delta | Digits | Mod

4

range_attribute_reference ::= prefix'range_attribute_designator

5

range_attribute_designator ::= Range[(static_expression)]

Name Resolution Rules

6/5

In an attribute_reference that is not a reduction_attribute_reference, if the attribute_designator is for an attribute defined for (at least some) objects of an access type, then the prefix is never interpreted as an implicit_dereference; otherwise (and for all range_attribute_references and reduction_attribute_references), if there is a prefix and the type of the name within the prefix is of an access type, the prefix is interpreted as an implicit_dereference. Similarly, if the attribute_designator is for an attribute defined for (at least some) functions, then the prefix is never interpreted as a parameterless function_call; otherwise (and for all range_attribute_references and reduction_attribute_references), if there is a prefix and the prefix consists of a name that denotes a function, it is interpreted as a parameterless function_call.

6.a
discussion

The first part of this rule is essentially a "preference" against implicit dereference, so that it is possible to ask for, say, 'Size of an access object, without automatically getting the size of the object designated by the access object. This rule applies to 'Access, 'Unchecked_Access, 'Size, and 'Address, and any other attributes that are defined for at least some access objects.

6.b

The second part of this rule implies that, for a parameterless function F, F'Address is the address of F, whereas F'Size is the size of the anonymous constant returned by F.

6.c/1

We normally talk in terms of expected type or profile for name resolution rules, but we don't do this for attributes because certain attributes are legal independent of the type or the profile of the prefix.

6.d/2

Other than the rules given above, the Name Resolution Rules for the prefix of each attribute are defined as Name Resolution Rules for that attribute. If no such rules are defined, then no context at all should be used when resolving the prefix. In particular, any knowledge about the kind of entities required must not be used for resolution unless that is required by Name Resolution Rules. This matters in obscure cases; for instance, given the following declarations:

6.e/2

function Get_It return Integer is ... -- (1) function Get_It return Some_Record_Type is ... -- (2)

6.f/2

the following attribute_reference cannot be resolved and is illegal:

6.g/2

if Get_It'Valid then

6.h/3

even though the Valid attribute is only defined for objects of scalar types, and thus cannot be applied to the result of function (2). That information cannot be used to resolve the prefix. The same would be true if (2) had been a procedure; even though the procedure does not denote an object, the attribute_reference is still illegal.

7

The expression, if any, in an attribute_designator or range_attribute_designator is expected to be of any integer type.

Legality Rules

8

The expression, if any, in an attribute_designator or range_attribute_designator shall be static.

Static Semantics

9/4

An attribute_reference denotes a value, an object, a subprogram, or some other kind of program entity. Unless explicitly specified otherwise, for an attribute_reference that denotes a value or an object, if its type is scalar, then its nominal subtype is the base subtype of the type; if its type is tagged, its nominal subtype is the first subtype of the type; otherwise, its nominal subtype is a subtype of the type without any constraint, null_exclusion, or predicate. Similarly, unless explicitly specified otherwise, for an attribute_reference that denotes a function, when its result type is scalar, its result subtype is the base subtype of the type, when its result type is tagged, the result subtype is the first subtype of the type, and when the result type is some other type, the result subtype is a subtype of the type without any constraint, null_exclusion, or predicate.

9.a
ramification

The attributes defined by the language are summarized in K.2. Implementations can define additional attributes.

9.b/3
discussion

The nominal subtype is primarily a concern when an attribute_reference, or a call on an attribute_reference, is used as the expression of a case statement, due to the full coverage requirement based on the nominal subtype. For nondiscrete cases, we define the nominal subtype mainly for completeness. Implementations may specify otherwise for implementation-defined attribute functions.

9.c/3

The rule is written to match the meaning of the italicized T in the definition of attributes such as Input; see 4.5.1.

9.d/3

To be honest: We don't worry about the fact that “base subtype” is not explicitly defined for the universal types. Since it is not possible to constrain a universal numeric type, all subtypes are unconstrained, and hence can be considered base subtypes. The wording above could be altered to bypass this issue, but it doesn't seem necessary, since universal integer is handled specially in the rules for case expression full coverage, and we don't allow user-defined functions for attribute functions whose result type is universal.

10

[A range_attribute_reference X'Range(N) is equivalent to the range X'First(N) .. X'Last(N), except that the prefix is only evaluated once. Similarly, X'Range is equivalent to X'First .. X'Last, except that the prefix is only evaluated once.]

Dynamic Semantics

11/5

The evaluation of a range_attribute_reference or an attribute_reference that is not a reduction_attribute_reference consists of the evaluation of the prefix.[ The evaluation of a reduction_attribute_reference is defined in 4.5.10.]

Implementation Permissions

12/5

{8652/0015} An implementation may provide implementation-defined attributes; the identifier for such an implementation-defined attribute shall differ from those of the language-defined attributes.

12.a
implementation defined

Implementation-defined attributes.

12.b
ramification

They cannot be reserved words because reserved words are not legal identifiers.

12.c

The semantics of implementation-defined attributes, and any associated rules, are, of course, implementation defined. For example, the implementation defines whether a given implementation-defined attribute can be used in a static expression.

13/5

An implementation may extend the definition of a language-defined attribute by accepting uses of that attribute that would otherwise be illegal in the following cases:

14/5
  • in order to support compatibility with a previous edition of of this Reference Manual; or
14.a/1
ramification

{8652/0015} Implementations are allowed to support the Small attribute for floating types, as this was defined in Ada 83, even though the name would conflict with a language-defined attribute.

15/5
  • in the case of a language-defined attribute whose prefix is required by this document to be a floating point subtype, an implementation may accept an attribute_reference whose prefix is a fixed point subtype[; the semantics of such an attribute_reference are implementation defined.]
16

NOTE 1 Attributes are defined throughout this document, and are summarized in K.2.

17/5

NOTE 2 By the general rules given above, there is no expected type or profile for the name in a prefix of an attribute_reference (or a range_attribute_reference), which means that no context can be used to resolve the name. However, by the rules given in 3.10.2 for the case of the Access attribute, the expected type for the attribute_reference will be a single access type, and the resolution of the name can make use of the designated type or profile of this access type.

17.a/2
proof

In the general case, there is no “expected type” for the prefix of an attribute_reference. In the special case of 'Access, there is an “expected type” or “expected profile” for the prefix.

17.b
reason

'Access is a special case, because without it, it would be very difficult to take 'Access of an overloaded subprogram.

Examples

18

Examples of attributes:

19

Color'First -- minimum value of the enumeration type Color (see 3.5.1) Rainbow'Base'First -- same as Color'First (see 3.5.1) Real'Digits -- precision of the type Real (see 3.5.7) Board'Last(2) -- upper bound of the second dimension of Board (see 3.6.1) Board'Range(1) -- index range of the first dimension of Board (see 3.6.1) Pool(K)'Terminated -- True if task Pool(K) is terminated (see 9.1) Date'Size -- number of bits for records of type Date (see 3.8) Message'Address -- address of the record variable Message -- (see 3.7.1)

Extensions to Ada 83

19.a

We now uniformly treat X'Range as X'First..X'Last, allowing its use with scalar subtypes.

19.b

We allow any integer type in the static_expression of an attribute designator, not just a value of universal_integer. The preference rules ensure upward compatibility.

Wording Changes from Ada 83

19.c

We use the syntactic category attribute_reference rather than simply "attribute" to avoid confusing the name of something with the thing itself.

19.d

The syntax rule for attribute_reference now uses identifier instead of simple_name, because attribute identifiers are not required to follow the normal visibility rules.

19.e

We now separate attribute_reference from range_attribute_reference, and enumerate the reserved words that are legal attribute or range attribute designators. We do this because identifier no longer includes reserved words.

19.f

The Ada 95 name resolution rules are a bit more explicit than in Ada 83. The Ada 83 rule said that the "meaning of the prefix of an attribute must be determinable independently of the attribute designator and independently of the fact that it is the prefix of an attribute". That isn't quite right since the meaning even in Ada 83 embodies whether or not the prefix is interpreted as a parameterless function call, and in Ada 95, it also embodies whether or not the prefix is interpreted as an implicit_dereference. So the attribute designator does make a difference — just not much.

19.g

Note however that if the attribute designator is Access, it makes a big difference in the interpretation of the prefix (see 3.10.2).

Wording Changes from Ada 95

19.h/2

{8652/0015} Corrigendum: The wording was changed to allow implementations to continue to implement the Ada 83 Small attribute. This was always intended to be allowed.

19.i/2

The note about resolving prefixes of attributes was updated to reflect that the prefix of an Access attribute now has an expected type (see 3.10.2).

Wording Changes from Ada 2005

19.j/3
correction

Defined the nominal subtype of an attribute_reference to close a minor language hole.

Wording Changes from Ada 2012

19.k/4

Corrigendum: Allowed overriding the nominal subtype of an attribute_reference for an object; that is used elsewhere in this standard.

19.l/4

Corrigendum: Added wording so it is clear that predicates don't apply to the result of an attribute.

19.m/5

Added reduction_attribute_reference and cleaned up the rules here to avoid trampling the definition of those in 4.5.10.

19.n/5

Added a permission to support fixed point versions of float attributes, such as the rounding attributes found in A.5.3.

4.1.5 User-Defined References

Static Semantics

1/3

Given a discriminated type T, the following type-related operational aspect may be specified:

2/3

Implicit_Dereference
This aspect is specified by a name that denotes an access discriminant declared for the type T.
2.a/3

Aspect Description for Implicit_Dereference: Mechanism for user-defined implicit .all.

3/3

A (view of a) type with a specified Implicit_Dereference aspect is a reference type. A reference object is an object of a reference type. The discriminant named by the Implicit_Dereference aspect is the reference discriminant of the reference type or reference object. [A generalized_reference is a name that identifies a reference object, and denotes the object or subprogram designated by the reference discriminant of the reference object.]

3.a/5

Term entry: reference type — type that has user-defined behavior for “.all”, defined by the Implicit_Dereference aspect

Syntax

4/3
generalized_reference ::= reference_object_name

Name Resolution Rules

5/3

The expected type for the reference_object_name in a generalized_reference is any reference type.

Static Semantics

5.1/4

The Implicit_Dereference aspect is nonoverridable (see 13.1.1).

5.a/4
reason

This ensures that all descendants of a reference type have the same reference discriminant. This prevents generic contract problems with formal derived types.

6/3

A generalized_reference denotes a view equivalent to that of a dereference of the reference discriminant of the reference object.

7/5

Given a reference type T, the Implicit_Dereference aspect is inherited by descendants of type T if not overridden [(which is only permitted if confirming)]. If a descendant type constrains the value of the reference discriminant of T by a new discriminant, that new discriminant is the reference discriminant of the descendant. [If the descendant type constrains the value of the reference discriminant of T by an expression other than the name of a new discriminant, a generalized_reference that identifies an object of the descendant type denotes the object or subprogram designated by the value of this constraining expression.]

Dynamic Semantics

8/3

The evaluation of a generalized_reference consists of the evaluation of the reference_object_name and a determination of the object or subprogram designated by the reference discriminant of the named reference object. A check is made that the value of the reference discriminant is not the null access value. Constraint_Error is raised if this check fails. The generalized_reference denotes the object or subprogram designated by the value of the reference discriminant of the named reference object.

Examples

9/5

Examples of the specification and use of generalized references:

10/3

type Barrel is tagged ... -- holds objects of type Element 11/3

type Ref_Element(Data : access Element) is limited private with Implicit_Dereference => Data; -- This Ref_Element type is a "reference" type. -- "Data" is its reference discriminant. 12/3

function Find (B : aliased in out Barrel; Key : String) return Ref_Element; -- Returns a reference to an element of a barrel. 13/3

B: aliased Barrel; 14/3

... 15/3

Find (B, "grape") := Element'(...); -- Assign through a reference. 16/3

-- This is equivalent to: Find (B, "grape").Data.all := Element'(...);

Extensions to Ada 2005

16.a/3

The aspect Implicit_Dereference and the generalized_reference are new.

Incompatibilities With Ada 2012

16.b/4

Corrigendum: Defined Implicit_Dereference to be nonoveridable, which makes redefinitions and hiding of the aspect illegal. It's possible that some program could violate one of these new restrictions, but this is not very likely as reference types are not likely to be used in a hierarchy.

4.1.6 User-Defined Indexing

Static Semantics

1/3

Given a tagged type T, the following type-related, operational aspects may be specified:

2/5

Constant_Indexing
This aspect shall be specified by a name that denotes one or more functions declared immediately within the same declaration list in which T, or the declaration completed by T, is declared. All such functions shall have at least two parameters, the first of which is of type T or T'Class, or is an access-to-constant parameter with designated type T or T'Class.
2.a/3

Aspect Description for Constant_Indexing: Defines function(s) to implement user-defined indexed_components.

3/5

Variable_Indexing
This aspect shall be specified by a name that denotes one or more functions declared immediately within the same declaration list in which T, or the declaration completed by T, is declared. All such functions shall have at least two parameters, the first of which is of type T or T'Class, or is an access parameter with designated type T or T'Class. All such functions shall have a return type that is a reference type (see 4.1.5), whose reference discriminant is of an access-to-variable type.
3.a/3
reason

We require these functions to return a reference type so that the object returned from the function can act like a variable. We need no similar rule for Constant_Indexing, since all functions return constant objects.

3.b/3

Aspect Description for Variable_Indexing: Defines function(s) to implement user-defined indexed_components.

4/4

These aspects are inherited by descendants of T (including the class-wide type T'Class).

4.a/3
ramification

Indexing can be provided for multiple index types by overloading routines with different parameter profiles. For instance, the map containers provide indexing on both cursors and keys by providing pairs of overloaded routines to the Constant_Indexing and Variable_Indexing aspects.

5/3

An indexable container type is (a view of) a tagged type with at least one of the aspects Constant_Indexing or Variable_Indexing specified. An indexable container object is an object of an indexable container type. [A generalized_indexing is a name that denotes the result of calling a function named by a Constant_Indexing or Variable_Indexing aspect.]

5.a/5

Term entry: indexable container type — type that has user-defined behavior for indexing, via the Constant_Indexing or Variable_Indexing aspects

5.1/4

The Constant_Indexing and Variable_Indexing aspects are nonoverridable (see 13.1.1).

5.b/5
reason

This (and the following Legality Rules) ensures that all descendants of an indexable container type have aspects with the same properties. This prevents generic contract problems with formal derived types.

5.c/4

A nonoverridable aspect allows the replacement of the implementation of an indexing function and the addition of a new indexing function for a derived type, but not the removal of an indexing function. This is necessary so that indexing can be used on objects of T'Class. So long as the tag of O is that of its nominal subtype, we do not want T'Class(O)(I) to mean something different than O(I). Thus we cannot allow a change in the function identified. As T'Class(O)(I) expands into a dispatching call, we need to ensure that there is a body for each such function -- but it is OK for that body to be changed from the original body (that's just normal dispatching).

Legality Rules

6/5

If an ancestor of a type T is an indexable container type, then any explicit specification of the Constant_Indexing or Variable_Indexing aspects shall be confirming; that is, the specified name shall match the inherited aspect (see 13.1.1).

Paragraphs 7 through 8 were deleted.

9/5

In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.

9.1/5

A generalized_indexing is illegal if the equivalent prefixed view (see below) is illegal.

Syntax

10/3
generalized_indexing ::= indexable_container_object_prefixactual_parameter_part

Name Resolution Rules

11/3

The expected type for the indexable_container_object_prefix of a generalized_indexing is any indexable container type.

11.a/5
ramification

A prefix can be an implicit_dereference (see 4.1), so an access-to-indexable_container_object can be the prefix (English meaning!) of a generalized_indexing.

12/3

If the Constant_Indexing aspect is specified for the type of the indexable_container_object_prefix of a generalized_indexing, then the generalized_indexing is interpreted as a constant indexing under the following circumstances:

13/3
  • when the Variable_Indexing aspect is not specified for the type of the indexable_container_object_prefix;
  • 14/3
  • when the indexable_container_object_prefix denotes a constant;
  • 15/3
  • when the generalized_indexing is used within a primary where a name denoting a constant is permitted.
15.a/3
ramification

This means it is not interpreted as a constant indexing for the variable_name in the LHS of an assignment (not inside a primary), nor for the name used for an out or in out parameter (not allowed to be a constant), nor for the name in an object renaming (not inside a primary), unless there is no Variable_Indexing aspect defined.

16/3

Otherwise, the generalized_indexing is interpreted as a variable indexing.

17/3

When a generalized_indexing is interpreted as a constant (or variable) indexing, it is equivalent to a call on a prefixed view of one of the functions named by the Constant_Indexing (or Variable_Indexing) aspect of the type of the indexable_container_object_prefix with the given actual_parameter_part, and with the indexable_container_object_prefix as the prefix of the prefixed view.

17.a/3
ramification

In other words, the generalized_indexing is equivalent to:

17.b/3

indexable_container_object_prefix.Indexing actual_parameter_part

17.c/4

where Indexing is the name specified for the Constant_Indexing or Variable_Indexing aspect. This equivalence is then resolved in the normal way; the aspect specifies a name, it does not denote declarations.

18/4

NOTE The Constant_Indexing and Variable_Indexing aspects cannot be redefined when inherited for a derived type, but the functions that they denote can be modified by overriding or overloading.

Examples

19/5

Examples of the specification and use of generalized indexing:

20/3

type Indexed_Barrel is tagged ... with Variable_Indexing => Find; -- Indexed_Barrel is an indexable container type, -- Find is the generalized indexing operation. 21/3

function Find (B : aliased in out Indexed_Barrel; Key : String) return Ref_Element; -- Return a reference to an element of a barrel (see 4.1.5). 22/3

IB: aliased Indexed_Barrel; 23/3

-- All of the following calls are then equivalent: Find (IB,"pear").Data.all := Element'(...); -- Traditional call IB.Find ("pear").Data.all := Element'(...); -- Call of prefixed view IB.Find ("pear") := Element'(...); -- Implicit dereference (see 4.1.5) IB ("pear") := Element'(...); -- Implicit indexing and dereference IB ("pear").Data.all := Element'(...); -- Implicit indexing only

Extensions to Ada 2005

23.a/3

Aspects Constant_Indexing and Variable_Indexing, and the generalized_indexing syntax are new.

Incompatibilities With Ada 2012

23.b/5
correction

Prevented a derived type from specifying Constant_Indexing if the ancestor specified Variable_Indexing (and vice versa). This is necessary to preserve the intent that for an object Obj whose tag is that of its nominal subtype, T'Class(Obj)(I) always has the same meaning as Obj(I). Situations like this should be rare in practice; most types will either define both aspects or neither.

23.c/5
correction

Added a rule that a generalized indexing is illegal if the equivalent prefixed view would be illegal. If the prefixed view would be illegal for any reason, Ada 2012 would have allowed the generalized indexing while Ada 2022 does not. This violated the principle that a generalized indexing and the equivalent prefixed view have the same semantics; practically, the code may not have worked anyway if a compiler implemented generalized indexing by code expansion into the canonical form. Thus, such code wasn't practically portable.

Wording Changes from Ada 2012

23.d/4

Corrigendum: Converted confusing and unnecessary normative wording about "overriding an aspect" into a note.

23.e/4

Corrigendum: Defined Constant_Indexing and Variable_Indexing to be nonoveridable. This is merely a new description for Legality Rules which already applied to these aspects.

23.f/5
correction

Allowed the completion of a private type to use declarations from either the visible part or the private part.