4.1.3 Selected Components
[
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
Name Resolution Rules
Discussion: See AI83-00187.
A
selected_component
that is not an expanded name shall resolve to denote one of the following:
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.
A component [(including a discriminant)]:
Reason: {
AI05-0005-1}
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).
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).
A single entry, an entry family, or a protected
subprogram:
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).
{
AI95-00252-01}
{
AI95-00407-01}
{
AI22-0091-1}
A view of a subprogram whose first formal parameter is of a
class-wide
type or a tagged type
declared
immediately within the same declarative region as the subprogram, or
is an access parameter whose designated type is
such
a type tagged:
{
AI95-00252-01}
{
AI95-00407-01}
{
AI05-0090-1}
{
AI22-0024-1}
{
AI22-0091-1}
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
, if T is of a tagged type, 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
T 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.
In
the special case where the prefix is class-wide and controlling, the
prefixed view is not abstract, even if the unprefixed view is abstract;
otherwise the prefixed view is abstract if and only if the unprefixed
view is abstract.
Discussion: {
AI05-0090-1}
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.
Ramification: {
AI22-0091-1}
The notation of prefixed views is effectively available
for all forms of type, with the exception of access types, since the
rules specify that an implicit dereference is performed for access prefixes.
If interpretations were allowed both with and without implicit dereference,
this could lead to ambiguities for calls that were legal before prefixed
views were generalized to allow them for untagged types, which would
be a serious incompatibility.
{
AI22-0091-1}
The rules do cause an anomaly for a private type
completed by an access type. In places where only the private type is
visible, prefixed notation can be used, while in places where the full
type is visible, it cannot be used. As private types completed directly
by an access type are uncommon, we're willing to tolerate this anomaly.
{
AI22-0024-1}
In the context of a subprogram renaming (see 8.5.4)
or the matching of an actual subprogram with a formal subprogram (see
12.6), a prefixed view whose prefix is class-wide
and controlling shall have an expected profile such that each formal
parameter or result type corresponding to a controlling parameter (or
access parameter) or controlling result (or access result) in the unprefixed
view, is (or designates) the same class-wide type as the prefix. In a
renaming or matching of a prefixed view whose prefix is of a specific
type or is not controlling, the unprefixed view shall not be abstract
and the types of the formal parameters or result in the expected profile
shall match those of the corresponding formal parameters or result of
the unprefixed view. [In either case, any constraints, null exclusions,
or predicates on the formal parameters or results in the view declared
by the renaming or instantiation come from the unprefixed view, as in
the normal case.] When renaming or matching a prefixed view whose prefix
is tag-indeterminate and controlling, the controlling tag is statically
determined to be that of the type of the prefix.
An expanded name shall
resolve to denote a declaration that occurs immediately within a named
declarative region, as follows:
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.
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.
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.
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
Ramification: {
AI12-0204-1}
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.
{
AI95-00407-01}
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.
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
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
Examples of selected
components:
{
AI95-00252-01}
{
AI95-00407-01}
{
AI12-0178}
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)
Examples of expanded
names:
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
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
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.
The rules have been restated to be consistent
with our new terminology, to accommodate class-wide types, etc.
Extensions to Ada 95
{
AI95-00252-01}
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”.
Given the following
definitions for a tagged type T:
procedure Do_Something (Obj : in out T; Count : in Natural);
procedure Do_Something_Else (Obj : access T; Flag : in Boolean);
My_Object : aliased T;
the following
calls are equivalent:
Do_Something (My_Object, Count => 10);
My_Object.Do_Something (Count => 10);
as are the following
calls:
Do_Something_Else (My_Object'Access, Flag => True);
My_Object.Do_Something_Else (Flag => True);
Wording Changes from Ada 2005
{
AI05-0090-1}
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
{
AI12-0204-1}
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.
Incompatibilities With Ada 2022
{
AI22-0024-1}
Corrigendum: Added rules
to explain what happens when a prefixed view with a class-wide prefix
and a controlling first parameter is renamed (or passed to a generic
formal). We've adopted rules that make such renames as close as possible
to those of a call of such a prefixed view. For the most part, this adds
capabilities, but some additional restrictions to the renameable profile
of such a view were also needed. Thus, it is possible that a program
for Ada 2012 (and original Ada 2022) that has a non-abstract primitive
with multiple controlling operands renamed a class-wide prefixed view
with the specific types as controlling parameters. This is no longer
allowed. However, the semantics of such a call are poorly defined (mixed
dynamically and statically tagged calls are not generally allowed in
Ada). It is rather unlikely that such a situation exists in existing
code, in part because some compilers are likely to reject or fail on
the renaming given the undefined nature of a call. Moreover, subprograms
with multiple controlling parameters are uncommon, as are subprogram
renamings themselves.
{
AI22-0091-1}
Prefixed views are now allowed for objects of all
types other than access types. Previously, only tagged types were considered.
Therefore, if the prefix and subprogram are both overloaded on a tagged
type and an untagged type, a prefixed view that previously referenced
the tagged operation can become ambiguous. This should be rare (since
it requires two entities to be overloaded), and is easily fixed by qualifying
the prefix. Note that we don't allow prefixed views for objects and operations
of an access type, as that would introduce a potential ambiguity that
could only be eliminated by replacing the prefixed view with a normal
call.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe