3.10.2 Operations of Access Types

The attribute Access is used to create access values
designating aliased objects and nonintrinsic subprograms. The “accessibility”
rules prevent dangling references (in the absence of uses of certain
unchecked features — see Clause 13).

Static Semantics

The
accessibility rules, which prevent dangling references, are written in
terms of accessibility levels, which reflect the run-time nesting
of masters. As explained in 7.6.1,
a master is the execution of a certain construct, such as a subprogram_body.
An accessibility level is deeper than another if it is more deeply
nested at run time. For example, an object declared local to a called
subprogram has a deeper accessibility level than an object declared local
to the calling subprogram. The accessibility rules for access types require
that the accessibility level of an object designated by an access value
be no deeper than that of the access type. This ensures that the object
will live at least as long as the access type, which in turn ensures
that the access value cannot later designate an object that no longer
exists. The Unchecked_Access attribute may be used to circumvent the
accessibility rules.

A given accessibility
level is said to be statically deeper than another if the given
level is known at compile time (as defined below) to be deeper than the
other for all possible executions. In most cases, accessibility is enforced
at compile time by Legality Rules. Run-time accessibility checks are
also used, since the Legality Rules do not cover certain cases involving
access parameters and generic packages.

The accessibility level of a given master is deeper
than that of each dynamically enclosing master, and deeper than that
of each master upon which the task executing the given master directly
depends (see 9.3).

An entity or view defined by a declaration and
created as part of its elaboration has the same accessibility level as
the innermost master of the declaration except in the cases of renaming
and derived access types described below. Other than for an explicitly
aliased parameter, a formal parameter of a callable entity has the same
accessibility level as the master representing the invocation of the
entity.

The accessibility level of an aggregate
that is used (in its entirety) to directly initialize part of an object
is that of the object being initialized. In other contexts, the accessibility
level of an aggregate
is that of the innermost master that evaluates the aggregate.

If the result is used (in its entirety)
to directly initialize part of an object, the master is that of the object
being initialized. In the case where the initialized object is a coextension
(see below) that becomes a coextension of another object, the master
is that of the eventual object to which the coextension will be transferred.

If the result is of an anonymous
access type and defines an access discriminant, the master is the same
as that for an object created by an anonymous allocator
that defines an access discriminant (even if the access result is of
an access-to-subprogram type).

In the case of a call to a function whose
result type is an anonymous access type, the accessibility level of the
type of the result of the function call is also determined by the point
of call as described above.

Within a return statement, the accessibility level
of the return object is that of the execution of the return statement.
If the return statement completes normally by returning from the function,
then prior to leaving the function, the accessibility level of the return
object changes to be a level determined by the point of call, as does
the level of any coextensions (see below) of the return object.

If the value of the access discriminant
is determined by a discriminant_association
in a subtype_indication,
the accessibility level of the object or subprogram designated by the
associated value (or library level if the value is null);

If the value of the access discriminant
is determined by a default_expression
in the declaration of the discriminant, the level of the object or subprogram
designated by the associated value (or library level if null);

If the value of the access discriminant
is determined by a record_component_association
in an aggregate,
the accessibility level of the object or subprogram designated by the
associated value (or library level if the value is null);

The accessibility level of the anonymous access
type of an access parameter specifying an access-to-object type is the
same as that of the view designated by the actual (or library-level if
the actual is null).

The accessibility level of the anonymous access
type of an access parameter specifying an access-to-subprogram type is
deeper than that of any master; all such anonymous access types have
this same level.

The accessibility level of the type of a stand-alone
object of an anonymous access-to-object type is the same as the accessibility
level of the type of the access value most recently assigned to the object;
accessibility checks ensure that this is never deeper than that of the
declaration of the stand-alone object.

The accessibility
level of an object created by an allocator
is the same as that of the access type, except for an allocator
of an anonymous access type (an anonymous allocator) in certain
contexts, as follows: For an anonymous allocator that defines the result
of a function with an access result, the accessibility level is determined
as though the allocator
were in place of the call of the function; in the special case of a call
that is the operand of a type conversion, the level is that of the target
access type of the conversion. For an anonymous allocator defining the
value of an access parameter, the accessibility level is that of the
innermost master of the call. For an anonymous allocator whose type is
that of a stand-alone object of an anonymous access-to-object type, the
accessibility level is that of the declaration of the stand-alone object.
For one defining an access discriminant, the accessibility level is determined
as follows:

In the first case,
the allocated object is said to be a coextension of the object
whose discriminant designates it, as well as of any object of which the
discriminated object is itself a coextension or subcomponent. If the
allocated object is a coextension of an anonymous object representing
the result of an aggregate or function call that is used (in its entirety)
to directly initialize a part of an object, after the result is assigned,
the coextension becomes a coextension of the object being initialized
and is no longer considered a coextension of the anonymous object. All
coextensions of an object (which have not thus been transfered by such
an initialization) are finalized when the object is finalized (see 7.6.1).

The accessibility level of the anonymous access
type of an access parameter specifying an access-to-subprogram type is
statically deeper than that of any master; all such anonymous access
types have this same level.

The statically deeper relationship does not apply
to the accessibility level of the anonymous type of an access parameter
specifying an access-to-object type nor does it apply to a descendant
of a generic formal type; that is, such an accessibility level is not
considered to be statically deeper, nor statically shallower, than any
other.

The statically deeper relationship does not apply
to the accessibility level of the type of a stand-alone object of an
anonymous access-to-object type; that is, such an accessibility level
is not considered to be statically deeper, nor statically shallower,
than any other.

Inside a return statement that applies to a function
F, when determining whether the accessibility level of an explicitly
aliased parameter of F is statically deeper than the level of
the return object of F, the level of the return object is considered
to be the same as that of the level of the explicitly aliased parameter;
for statically comparing with the level of other entities, an explicitly
aliased parameter of F is considered to have the accessibility
level of the body of F.

For determining whether a level is statically deeper
than the level of the anonymous access type of an access result of a
function, when within a return statement that applies to the function,
the level of the master of the call is presumed to be the same as that
of the level of the master that elaborated the function body.

For determining whether one level is statically
deeper than another when within a generic package body, the generic package
is presumed to be instantiated at the same level as where it was declared;
run-time checks are needed in the case of more deeply nested instantiations.

For determining whether one level is statically
deeper than another when within the declarative region of a type_declaration,
the current instance of the type is presumed to be an object created
at a deeper level than that of the type.

X'Access yields an access value
that designates the object denoted by X. The type of X'Access is an access-to-object
type, as determined by the expected type. The expected type shall be
a general access type. X shall denote an aliased
view of an object, including possibly the current instance (see 8.6)
of a limited type within its definition, or a formal parameter or generic
formal object of a tagged type. The view denoted by the prefix
X shall satisfy the following additional requirements, presuming the
expected type for X'Access is the general access type A with designated
type D:

If A is a named access type and
D is a tagged type, then the type of the view shall be covered
by D; if A is anonymous and D is tagged, then the
type of the view shall be either D'Class or a type covered by
D; if D is untagged, then the type of the view shall be
D, and either:

D shall be discriminated
in its full view and unconstrained in any partial view, and the designated
subtype of A shall be unconstrained. For the purposes of determining
within a generic body whether D is unconstrained in any partial
view, a discriminated subtype is considered to have a constrained partial
view if it is a descendant of an untagged generic formal private or derived
type.

If the nominal subtype
of X does not statically match the designated subtype of A, a
view conversion of X to the designated subtype is evaluated (which might
raise Constraint_Error — see 4.6) and
the value of X'Access designates that view.

P'Access yields an access value
that designates the subprogram denoted by P. The type of P'Access is
an access-to-subprogram type (S), as determined by the expected
type. The accessibility level of P shall not be statically
deeper than that of S. 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. The profile of P shall be subtype conformant with the designated
profile of S, and shall not be Intrinsic. If
the subprogram denoted by P is declared within a generic unit, and the
expression P'Access occurs within the body of that generic unit or within
the body of a generic unit declared within the declarative region of
the generic unit, then the ultimate ancestor of S shall be either
a nonformal type declared within the generic unit or an anonymous access
type of an access parameter.

The statically deeper relationship does not apply
to the accessibility level of an expression
having distributed accessibility; that is, such an accessibility level
is not considered to be statically deeper, nor statically shallower,
than any other.

Any static accessibility requirement that is imposed
on an expression
that has distributed accessibility (or on its type) is instead imposed
on the dependent_expressions
of the underlying conditional_expression.
This rule is applied recursively if a dependent_expression
also has distributed accessibility.

88 The Unchecked_Access attribute yields
the same result as the Access attribute for objects, but has fewer restrictions
(see 13.10). There are other predefined operations
that yield access values: an allocator
can be used to create an object, and return an access value that designates
it (see 4.8); evaluating the literal null
yields a null access value that designates no entity at all (see 4.2).

89 The predefined operations
of an access type also include the assignment operation, qualification,
and membership tests. Explicit conversion is allowed between general
access types with matching designated subtypes; explicit conversion is
allowed between access-to-subprogram types with subtype conformant profiles
(see 4.6). Named access
types have predefined equality operators; anonymous access types do not,
but they can use the predefined equality operators for universal_access
(see 4.5.2).

92 The
Access attribute for subprograms and parameters of an anonymous access-to-subprogram
type may together be used to implement “downward closures”
— that is, to pass a more-nested subprogram as a parameter to a
less-nested subprogram, as might be appropriate for an iterator abstraction
or numerical integration. Downward closures can also be implemented using
generic formal subprograms (see 12.6). Note
that Unchecked_Access is not allowed for subprograms.

94 An implementation may consider two access-to-subprogram
values to be unequal, even though they designate the same subprogram.
This might be because one points directly to the subprogram, while the
other points to a special prologue that performs an Elaboration_Check
and then jumps to the subprogram. See 4.5.2.