3.10 Access Types
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
A value of an access type (an access value) provides indirect access to the object or subprogram it designates. Depending on its type, an access value can designate either subprograms, objects created by allocators (see 4.8), or more generally aliased objects of an appropriate type.
Language Design Principles
Syntax
2/2access_type_definition
::=
[null_exclusion
] access_to_object_definition
| [null_exclusion
] access_to_subprogram_definition
3access_to_object_definition
::=
access [general_access_modifier
] subtype_indication
4general_access_modifier
::=
all | constant
5access_to_subprogram_definition
::=
access [protected] procedure parameter_profile
| access [protected] function parameter_and_result_profile
5.1/2null_exclusion
::=
not null
6/2access_definition
::=
[null_exclusion
] access [constant] subtype_mark
| [null_exclusion
] access [protected] procedure parameter_profile
| [null_exclusion
] access [protected] function parameter_and_result_profile
Static Semantics
7/1{8652/0012} There are two kinds of access types, access-to-object types, whose values designate objects, and access-to-subprogram types, whose values designate subprograms. Associated with an access-to-object type is a storage pool; several access types may share the same storage pool. All descendants of an access type share the same storage pool. A storage pool is an area of storage used to hold dynamically allocated objects (called pool elements) created by allocators[; storage pools are described further in 13.11, “Storage Management”].
Access-to-object types are further subdivided into pool-specific access types, whose values can designate only the elements of their associated storage pool, and general access types, whose values can designate the elements of any storage pool, as well as aliased objects created by declarations rather than allocators, and aliased subcomponents of other objects.
A view of an object is defined to be aliased if it is defined by an object_declaration
, component_definition
, parameter_specification
, or extended_return_object_declaration
with the reserved word aliased, or by a renaming of an aliased view. In addition, the dereference of an access-to-object value denotes an aliased view, as does a view conversion (see 4.6) of an aliased view. A qualified_expression
denotes an aliased view when the operand denotes an aliased view. The current instance of an immutably limited type (see 7.5) is defined to be aliased. Finally, a formal parameter or generic formal object of a tagged type is defined to be aliased. [Aliased views are the ones that can be designated by an access value.]
component_definition
.type T1 is tagged ...;
procedure P(X : access T1);
10.itype T2 is new T1 with ...;
procedure P(X : access T2) is
begin
P(T1(X.all)'Access); -- hand off to T1's P
. . . -- now do extra T2-specific processing
end P;
An access_to_object_definition
defines an access-to-object type and its first subtype; the subtype_indication
defines the designated subtype of the access type. If a general_access_modifier
appears, then the access type is a general access type. If the modifier is the reserved word constant, then the type is an access-to-constant type[; a designated object cannot be updated through a value of such a type]. If the modifier is the reserved word all, then the type is an access-to-variable type[; a designated object can be both read and updated through a value of such a type]. If no general_access_modifier
appears in the access_to_object_definition
, the access type is a pool-specific access-to-variable type.
An access_to_subprogram_definition
defines an access-to-subprogram type and its first subtype; the parameter_profile
or parameter_and_result_profile
defines the designated profile of the access type. There is a calling convention associated with the designated profile[; only subprograms with this calling convention can be designated by values of the access type.] By default, the calling convention is “protected” if the reserved word protected appears, and “Ada” otherwise. [See Annex B for how to override this default.]
An access_definition
defines an anonymous general access type or an anonymous access-to-subprogram type. For a general access type, the subtype_mark
denotes its designated subtype; if the general_access_modifier
constant appears, the type is an access-to-constant type; otherwise, it is an access-to-variable type. For an access-to-subprogram type, the parameter_profile
or parameter_and_result_profile
denotes its designated profile.
For each access type, there is a null access value designating no entity at all, which can be obtained by (implicitly) converting the literal null to the access type. [The null value of an access type is the default initial value of the type.] Nonnull values of an access-to-object type are obtained by evaluating an allocator
[, which returns an access value designating a newly created object (see 3.10.2)], or in the case of a general access-to-object type, evaluating an attribute_reference
for the Access or Unchecked_Access attribute of an aliased view of an object. Nonnull values of an access-to-subprogram type are obtained by evaluating an attribute_reference
for the Access attribute of a nonintrinsic subprogram.
A null_exclusion
in a construct specifies that the null value does not belong to the access subtype defined by the construct, that is, the access subtype excludes null. In addition, the anonymous access subtype defined by the access_definition
for a controlling access parameter (see 3.9.2) excludes null. Finally, for a subtype_indication
without a null_exclusion
, the subtype denoted by the subtype_indication
excludes null if and only if the subtype denoted by the subtype_mark
in the subtype_indication
excludes null.
access_definition
used in a controlling parameter excludes null because it is necessary to read the tag to dispatch, and null has no tag. We would have preferred to require not null to be specified for such parameters, but that would have been too incompatible with Ada 95 code to require.{8652/0013} [All subtypes of an access-to-subprogram type are constrained.] The first subtype of a type defined by an access_definition
or an access_to_object_definition
is unconstrained if the designated subtype is an unconstrained array or discriminated subtype; otherwise, it is constrained.
range_constraint
s (see 3.5) do not permit the subtype_mark
of the subtype_indication
to denote an access-to-scalar type, only a scalar type. The Legality Rules on index_constraint
s (see 3.6.1) and discriminant_constraint
s (see 3.7.1) both permit access-to-composite types in a subtype_indication
with such _constraint
s. Note that an access-to-access-to-composite is never permitted in a subtype_indication
with a constraint
. composite_constraint
s are permitted for an access type, and only on access-to-composite types. A constraint on an access-to-scalar or access-to-access type might be violated due to assignments via other access paths that were not so constrained. By contrast, if the designated subtype is an array or discriminated type without defaults, the constraint could not be violated by unconstrained assignments, since array objects are always constrained, and discriminated objects are also constrained when the type does not have defaults for its discriminants. Constraints are not allowed on general access-to-unconstrained discriminated types if the type has defaults for its discriminants; constraints on pool-specific access types are usually allowed because allocated objects are usually constrained by their initial value. Legality Rules
15.1/2If a subtype_indication
, discriminant_specification
, parameter_specification
, parameter_and_result_profile
, object_renaming_declaration
, or formal_object_declaration
has a null_exclusion
, the subtype_mark
in that construct shall denote an access subtype that does not exclude null.
null_exclusion
that occurs in an access_definition
in one of these constructs (for an access_definition
, the subtype_mark
in such an access_definition
is not restricted). Dynamic Semantics
16/2A composite_constraint
is compatible with an unconstrained access subtype if it is compatible with the designated subtype. A null_exclusion
is compatible with any access subtype that does not exclude null. An access value satisfies a composite_constraint
of an access subtype if it equals the null value of its type or if it designates an object whose value satisfies the constraint. An access value satisfies an exclusion of the null value if it does not equal the null value of its type.
The elaboration of an access_type_definition
creates the access type and its first subtype. For an access-to-object type, this elaboration includes the elaboration of the subtype_indication
, which creates the designated subtype.
The elaboration of an access_definition
creates an anonymous access type.
allocator
(see 4.8) for the access type. A storage pool (roughly) corresponds to what some other languages call a “heap”. See 13.11 for a discussion of pools.index_constraint
s and discriminant_constraint
s can be applied to access types (see 3.6.1 and 3.7.1). Examples
22Examples of access-to-object types:
type Frame is access Matrix; -- see 3.6
type Peripheral_Ref is not null access Peripheral; -- see 3.8.1
type Binop_Ptr is access all Binary_Operation'Class;
-- general access-to-class-wide, see 3.9.1
24Example of an access subtype:
subtype Drum_Ref is Peripheral_Ref(Drum); -- see 3.8.1
26Example of an access-to-subprogram type:
type Message_Procedure is access procedure (M : in String := "Error!");
procedure Default_Message_Procedure(M : in String);
Give_Message : Message_Procedure := Default_Message_Procedure'Access;
...
procedure Other_Procedure(M : in String);
...
Give_Message := Other_Procedure'Access;
...
Give_Message("File not found."); -- call with parameter (.all is optional)
Give_Message.all; -- call with no parameters
Extensions to Ada 83
access_type_definition
is changed to support general access types (including access-to-constants) and access-to-subprograms. The syntax rules for general_access_modifier
and access_definition
are new. Wording Changes from Ada 83
Inconsistencies With Ada 95
Incompatibilities With Ada 95
Extensions to Ada 95
null_exclusion
is new. It can be used in both anonymous and named access type definitions. It is most useful to declare that parameters cannot be null, thus eliminating the need for checks on use.Wording Changes from Ada 95
Wording Changes from Ada 2005
Extensions to Ada 2012
3.10.1 Incomplete Type Declarations
1There are no particular limitations on the designated type of an access type. In particular, the type of a component of the designated type can be another access type, or even the same access type. This permits mutually dependent and recursive access types. An incomplete_type_declaration
can be used to introduce a type to be used as a designated type, while deferring its full definition to a subsequent full_type_declaration
.
Syntax
2/2incomplete_type_declaration
::=
type defining_identifier
[discriminant_part
] [is tagged];
Static Semantics
2.1/4An incomplete_type_declaration
declares an incomplete view of a type and its first subtype; the first subtype is unconstrained if a discriminant_part
appears. If the incomplete_type_declaration
includes the reserved word tagged, it declares a tagged incomplete view. If T denotes a tagged incomplete view, then T'Class denotes a tagged incomplete view. [An incomplete view of a type is a limited view of the type (see 7.5).]
Given an access type A whose designated type T is an incomplete view, a dereference of a value of type A also has this incomplete view except when:
- it occurs within the immediate scope of the completion of T, or
- it occurs within the scope of a
nonlimited_with_clause
that mentions a library package in whose visible part the completion of T is declared, or 2.5/3 - it occurs within the scope of the completion of T and T is an incomplete view declared by an
incomplete_type_declaration
.
In these cases, the dereference has the view of T visible at the point of the dereference.
package P is
private
type T;
type PtrT is access T;
end P;
2.d/2private package P.C is
Ptr : PtrT;
end P.C;
2.e/3with P.C;
package body P is
-- Ptr.all'Size is not legal here, but we are within the scope
-- of a nonlimited_with_clause for P.
type T is ...
-- Ptr.all'Size is legal here.
end P;
Similarly, if a subtype_mark
denotes a subtype_declaration
defining a subtype of an incomplete view T, the subtype_mark
denotes an incomplete view except under the same three circumstances given above, in which case it denotes the view of T visible at the point of the subtype_mark
.
Legality Rules
3/3An incomplete_type_declaration
requires a completion, which shall be a type_declaration
other than an incomplete_type_declaration
. [If the incomplete_type_declaration
occurs immediately within either the visible part of a package_specification
or a declarative_part
, then the type_declaration
shall occur later and immediately within this visible part or declarative_part
. If the incomplete_type_declaration
occurs immediately within the private part of a given package_specification
, then the type_declaration
shall occur later and immediately within either the private part itself, or the declarative_part
of the corresponding package_body
.]
incomplete_type_declaration
occurs immediately within the visible part of a package_specification
, then the completing type_declaration
shall occur immediately within this visible part. incomplete_type_declaration
can be imported (using aspect Import, see B.1), in which case no explicit completion is allowed. If an incomplete_type_declaration
includes the reserved word tagged, then a type_declaration
that completes it shall declare a tagged type. If an incomplete_type_declaration
has a known_discriminant_part
, then a type_declaration
that completes it shall have a fully conforming (explicit) known_discriminant_part
(see 6.3.1). [If an incomplete_type_declaration
has no discriminant_part
(or an unknown_discriminant_part
), then a corresponding type_declaration
is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation.]
A name
that denotes an incomplete view of a type may be used as follows:
- as the
subtype_mark
in thesubtype_indication
of anaccess_to_object_definition
; [the only form ofconstraint
allowed in thissubtype_indication
is adiscriminant_constraint
[(anull_exclusion
is not allowed)];]
discriminant_constraint
s even if the full type is deferred to the package body. However, there is no particular implementation burden because we have dropped the concept of the dependent compatibility check. In other words, we have effectively repealed AI83-00007. - as the
subtype_mark
in thesubtype_indication
of asubtype_declaration
; thesubtype_indication
shall not have anull_exclusion
or aconstraint
; 8/3 - as the
subtype_mark
in anaccess_definition
for an access-to-object type;
subtype_mark
in a construct that makes up an access_definition
, such as a formal_part
, just the one given directly in the syntax of access_definition
. - as the
subtype_mark
defining the subtype of a parameter or result in a profile occurring within abasic_declaration
;
- as a generic actual parameter whose corresponding generic formal parameter is a formal incomplete type (see 12.5.1).
If such a name
denotes a tagged incomplete view, it may also be used:
- as the
subtype_mark
defining the subtype of a parameter in the profile for asubprogram_body
,entry_body
, oraccept_statement
; 9/2 - as the
prefix
of anattribute_reference
whoseattribute_designator
is Class; such anattribute_reference
is restricted to the uses allowed here; it denotes a tagged incomplete view.
This paragraph was deleted.
- This paragraph was deleted.
If any of the above uses occurs as part of the declaration of a primitive subprogram of the incomplete view, and the declaration occurs immediately within the private part of a package, then the completion of the incomplete view shall also occur immediately within the private part; it shall not be deferred to the package body.
No other uses of a name
that denotes an incomplete view of a type are allowed.
A prefix
that denotes an object shall not be of an incomplete view. An actual parameter in a call shall not be of an untagged incomplete view. The result object of a function call shall not be of an incomplete view. A prefix
shall not denote a subprogram having a formal parameter of an untagged incomplete view, nor a return type that is an incomplete view.
prefix
. Dereferences used in other contexts do not pose a problem since normal type matching will preclude their use except when the full type is “nearby” as context (for example, as the expected type).prefix
es that are directly of an incomplete view. For instance, a parameter P can be declared of a tagged incomplete type, but we don't want to allow P'Size, P'Alignment, or the like, as representation values aren't known for an incomplete view.The controlling operand or controlling result of a dispatching call shall not be of an incomplete view if the operand or result is dynamically tagged.
package Pack is
type T is tagged;
function F return access T'Class;
function G (X : access T) return Integer;
I : Integer := G (F); -- Illegal by above rule.
type T is tagged null record;
end Pack;
Paragraph 11 was deleted.
Dynamic Semantics
12The elaboration of an incomplete_type_declaration
has no effect.
declarative_part
, an incomplete_type_declaration
and a corresponding full_type_declaration
cannot be separated by an intervening body. This is because a type has to be completely defined before it is frozen, and a body freezes all types declared prior to it in the same declarative_part
(see 13.14).name
that denotes an object of an incomplete view is defined to be of a limited type. Hence, the target of an assignment statement cannot be of an incomplete view.Examples
14Example of a recursive type:
type Cell; -- incomplete type declaration
type Link is access Cell;
16type Cell is
record
Value : Integer;
Succ : Link;
Pred : Link;
end record;
17Head : Link := new Cell'(0, null, null);
Next : Link := Head.Succ;
18Examples of mutually dependent access types:
type Person(<>); -- incomplete type declaration
type Car is tagged; -- incomplete type declaration
20/2type Person_Name is access Person;
type Car_Name is access all Car'Class;
21/2type Car is tagged
record
Number : Integer;
Owner : Person_Name;
end record;
22type Person(Sex : Gender) is
record
Name : String(1 .. 20);
Birth : Date;
Age : Integer range 0 .. 130;
Vehicle : Car_Name;
case Sex is
when M => Wife : Person_Name(Sex => F);
when F => Husband : Person_Name(Sex => M);
end case;
end record;
23/5My_Car, Your_Car, Next_Car : Car_Name := new Car; -- see 4.8
Casey : Person_Name := new Person(M);
...
Casey .Vehicle := Your_Car;
Extensions to Ada 83
full_type_declaration
that completes an incomplete_type_declaration
may have a known_discriminant_part
even if the incomplete_type_declaration
does not.discriminant_constraint
may be applied to an incomplete type, even if its completion is deferred to the package body, because there is no “dependent compatibility check” required any more. Of course, the constraint can be specified only if a known_discriminant_part
was given in the incomplete_type_declaration
. As mentioned in the previous paragraph, that is no longer required even when the full type has discriminants. Wording Changes from Ada 83
package Pack is
type Pri is private;
private
type Sep;
type Pri is access Sep;
X : Pri;
end Pack;
23.epackage body Pack is -- Could be separately compiled!
type Sep is ...;
X := new Sep;
end Pack;
23.fpragma Elaborate(Pack);
private package Pack.Child is
I : Integer := X.all'Size; -- Legal, by AI-00039.
end Pack.Child;
Incompatibilities With Ada 95
Extensions to Ada 95
subtype_declaration
can be used to give a new name to an incomplete view of a type. This is valuable to give shorter names to entities imported with a limited_with_clause
. Wording Changes from Ada 95
Extensions to Ada 2005
Wording Changes from Ada 2005
Wording Changes from Ada 2012
3.10.2 Operations of Access Types
1/3[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).]
Language Design Principles
Name Resolution Rules
2/2For an attribute_reference
with attribute_designator
Access (or Unchecked_Access — see 13.10), the expected type shall be a single access type A such that:
- A is an access-to-object type with designated type D and the type of the
prefix
is D'Class or is covered by D, or 2.2/2 - A is an access-to-subprogram type whose designated profile is type conformant with that of the prefix.
[The prefix
of such an attribute_reference
is never interpreted as an implicit_dereference
or a parameterless function_call
(see 4.1.4).] The designated type or profile of the expected type of the attribute_reference
is the expected type or profile for the prefix
.
name
in a prefix
of an attribute_reference
. In all other cases, the name
has to be resolved without using context. See 4.1.4.prefix
may provide both multiple types; “single” only means that a single, specific interpretation must remain after resolution. We say “single” here to trigger the Legality Rules of 8.6. The resolution of an access attribute is similar to that of an assignment_statement
. For example: type Int_Ptr is access all Integer;
type Char_Ptr is access all Character;
type Float_Ptr is access all Float;
2.d/2function Zap (Val : Int_Ptr) return Float; -- (1)
function Zap (Val : Float_Ptr) return Float; -- (2)
function Zop return Int_Ptr; -- (3)
function Zop return Char_Ptr; -- (4)
2.e/2Result : Float := Zap (Zop.all'Access); -- Resolves to Zap (1) and Zop (3).
Static Semantics
3/5[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 (called a master 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.]
Each master, and each entity and view created by it, has an accessibility level; when two levels are defined to be the same, the accessibility levels of the two associated entities are said to be tied to each other. Accessibility levels are defined as follows:
- 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. A formal parameter of a callable entity has the same accessibility level as the master representing the invocation of the entity.
component_definition
Special rules exist for the accessibility level of other anonymous types. Components whose (anonymous) type is defined by an access_definition
have accessibility levels corresponding to named access types defined at the same point. access_definition
is elaborated, for a type extension, the anonymous access types of components (other than access discriminants) inherited from the parent have the same accessibility as they did in the parent; those in the extension part have the accessibility determined by the scope where the type extension is declared. Similarly, the types of the nondiscriminant access components of a derived untagged type have the same accessibility as they did in the parent. - The accessibility level of a view of an object or subprogram defined by a
renaming_declaration
is the same as that of the renamed view, unless the renaming is of a formal subprogram, in which case the accessibility level is that of the instance. 9/2 - The accessibility level of a view conversion,
qualified_expression
, or parenthesized expression, is the same as that of the operand. 9.1/5 - The accessibility level of a
conditional_expression
(see 4.5.7) is the accessibility level of the evaluated dependent_expression
. 9.2/5 - The accessibility level of a
declare_expression
(see 4.5.9) is the accessibility level of the body_expression
. 10/4 - 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 anaggregate
is that of the innermost master that evaluates theaggregate
. Corresponding rules apply to a value conversion (see 4.6). 10.1/3 - The accessibility level of the result of a function call is that of the master of the function call, which is determined by the point of call as follows:
- If the result type at the point of the function (or access-to-function type) declaration is a composite type, and 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.
qualified_expression
s. prefix
, this bullet does not apply. Similarly, an assignment_statement
is not an initialization of an object, so this bullet does not apply. - If the result is of an anonymous access type and is converted to a (named or anonymous) access type , the master is determined following the rules given below for determining the master of an object created by an allocator (even if the access result is of an access-to-subprogram type) ;
- This paragraph was deleted.
- If the call itself defines the result of a function F , or has an accessibility level that is tied to the result of such a function F, then the master of the call is that of the master of the call invoking F ;
- In other cases, the master of the call is that of the innermost master that evaluates the function call.
- 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.
- The accessibility level of a derived access type is the same as that of its ultimate ancestor.
- The accessibility level of the anonymous access type defined by an
access_definition
of anobject_renaming_declaration
is the same as that of the renamed view. 11.2/5 - The accessibility level of the anonymous access type defined by an
access_definition
of aloop_parameter_subtype_indication
is that of the loop parameter. 12/2 - The accessibility level of the anonymous access type of an access discriminant in the
subtype_indication
orqualified_expression
of anallocator
, or in theexpression
orreturn_subtype_indication
of a return statement is determined as follows:
- If the value of the access discriminant is determined by a
discriminant_association
in asubtype_indication
, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);
allocator
or return statement: - An
extension_aggregate
where theancestor_part
is asubtype_mark
denoting a constrained subtype; 12.c/2 - An uninitialized
allocator
where thesubtype_indication
defines a constrained subtype; 12.d/2 - A discriminant of an object with a constrained nominal subtype, including constrained components, the result of calling a function with a constrained result subtype, the dereference of an access-to-constrained subtype, etc.
subtype_indication
mentioned in this bullet is not necessarily the one given in the allocator
or return statement that is determining the accessibility level; the constrained subtype might have been defined in an earlier declaration (as a named subtype).- 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 anaggregate
, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);
aggregate
has to occur in the context of an allocator
or return statement, while the subtype_indication
of the previous bullet can occur anywhere (it doesn't have to be directly given in the allocator
or return statement). - In other cases, where the value of the access discriminant is determined by an object with an unconstrained nominal subtype, the accessibility level of the object.
- The accessibility level of the anonymous access type of an access discriminant in any other context is that of the enclosing object.
- 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 anonymous access subtype defined by a
return_subtype_indication
that is anaccess_definition
(see 6.5) is that of the result subtype of the enclosing function. 13.3/4 - 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 anallocator
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 theallocator
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:
- for an
allocator
used to define the discriminant of an object, the level of the object; 14.2/3 - for an
allocator
used to define the constraint in asubtype_indication
in any other context, the level of the master that elaborates thesubtype_indication
. 14.3/3 - This paragraph was deleted.
- 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).
- Within a return statement, the accessibility level of the anonymous access type of an access result is that of the master of the call.
- The accessibility level of a view of an object or subprogram designated by an access value is the same as that of the access type.
- The accessibility level of a component, protected subprogram, or entry of (a view of) a composite object is the same as that of (the view of) the composite object.
In the above rules, the operative constituents of a name
or expression
(see 4.4) are considered to be used in a given context if the enclosing name
or expression
is used in that context.
qualified_expression
s, and conditional_expression
s are ignored for the purposes of calculating accessibility levels, determining the master of a function call, and so on. One accessibility level is defined to be statically deeper than another in the following cases:
- For a master construct that is statically nested within another master construct, the accessibility level of the inner master construct is statically deeper than that of the outer master construct.
- 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 following:
- the anonymous type of an access parameter specifying an access-to-object type;
- the type of a stand-alone object of an anonymous access-to-object type;
- a
raise_expression
; 19.4/5 - a descendant of a generic formal type;
- a descendant of a type declared in a generic formal package.
- When the statically deeper relationship does not apply, the accessibility level is not considered to be statically deeper, nor statically shallower, than any other.
- This paragraph was deleted.
- When within a function body or the return expression of an expression function, the accessibility level of the master representing an execution of the function is statically deeper than that of the master of the function call invoking that execution[, independent of how the master of the function call is determined (see above)] .
- [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; runtime checks are required 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.
type_declaration
, in an assume-the-worst manner. Notwithstanding other rules given above, the accessibility level of an entity that is tied to that of an explicitly aliased formal parameter of an enclosing function is considered (both statically and dynamically) to be the same as that of an entity whose accessibility level is tied to that of the return object of that function.
The accessibility level of all library units is called the library level; a library-level declaration or entity is one whose accessibility level is the library level.
Library_unit_declaration
s are library level. Nested declarations are library level if they are nested only within packages (possibly more than one), and not within subprograms, tasks, etc. - if the actual is an expression of a named access type — the accessibility level of that type;
- if the actual is an
allocator
— the accessibility level of the execution of the called subprogram; 22.e/1 - if the actual is a reference to the Access attribute — the accessibility level of the view denoted by the
prefix
; 22.f - if the actual is a reference to the Unchecked_Access attribute — library accessibility level;
- if the actual is an access parameter — the accessibility level of its type.
allocator
case is explicitly mentioned in the RM95, because otherwise the definition would be circular: the level of the anonymous type is that of the view designated by the actual, which is that of the access type. allocator
can have its lifetime prematurely ended by an instance of Unchecked_Deallocation.)package_body
live as long as objects declared outside the package, even though the body objects are not visible outside the package.allocator
, or by the master in which the object was declared. The former is used in several Legality Rules and runtime checks; the latter is used to define when X.all gets finalized. The level of a view reflects what we can conservatively “know” about the object of that view; for example, due to type_conversion
s, an access value might designate an object that was allocated by an allocator
for a different access type.- Checks involving access parameters of an access-to-object type. The fact that “statically deeper than” is not defined for the anonymous access type of an access parameter implies that any rule saying “shall not be statically deeper than” does not apply to such a type, nor to anything defined to have “the same” level as such a type.
- Checks involving generic formal types and their descendants. This is because the actual type can be more or less deeply nested than the generic unit. Note that this only applies to the generic unit itself, and not to the instance. Any static checks needed in the instance will be performed. Any other checks (such as those in the generic body) will require a run-time check of some sort (although implementations that macro-expand generics can determine the result of the check when the generic is expanded).
- Checks involving other entities and views within generic packages. This is because an instantiation can be at a level that is more deeply nested than the generic package itself. In implementations that use a macro-expansion model of generics, these violations can be detected at macro-expansion time. For implementations that share generics, run-time code is needed to detect the error.
- Checks during function return and
allocator
s, for nested type extensions and access discriminants.
allocator
s), because their accessibility is determined statically by the accessibility level of the enclosing object.- If the actual is an expression of a named access type, pass the static nesting level of that type.
- If the actual is an
allocator
, pass the static nesting level of the caller, plus one. 22.bb/1 - If the actual is a reference to the Access attribute, pass the level of the view denoted by the
prefix
. 22.cc - If the actual is a reference to the Unchecked_Access attribute, pass 0 (the library accessibility level).
- If the actual is an access parameter of an access-to-object type, usually just pass along the level passed in. However, if the static nesting level of the formal (access) parameter is greater than the static nesting level of the actual (access) parameter, the level to be passed is the minimum of the static nesting level of the access parameter and the actual level passed in.
type_conversion
of an access parameter of an access-to-object type of a given subprogram to a named access type, if the target type is statically nested within the subprogram, do nothing; the check can't fail in this case. Otherwise, check that the value passed in is <= the static nesting depth of the target type. The other Accessibility_Checks are handled in a similar manner.package body Lib_Unit is
type T is tagged ...;
type A0 is access all T;
Global: A0 := ...;
procedure P(X: in out T) is
Y: aliased T;
type A1 is access all T;
Ptr0: A0 := Global; -- OK.
Ptr1: A1 := X'Access; -- OK.
begin
Ptr1 := Y'Access; -- OK;
Ptr0 := A0(Ptr1); -- Illegal type conversion!
Ptr0 := X'Access; -- Illegal reference to Access attribute!
Ptr0 := Y'Access; -- Illegal reference to Access attribute!
Global := Ptr0; -- OK.
end P;
end Lib_Unit;
procedure Main is
type Level_1_Type is access all Integer;
22.llprocedure P(X: access Integer) is
type Nested_Type is access all Integer;
begin
... Nested_Type(X) ... -- (1)
... Level_1_Type(X) ... -- (2)
end P;
22.mmprocedure Q(X: access Integer) is
procedure Nested(X: access Integer) is
begin
P(X);
end Nested;
begin
Nested(X);
end Q;
22.nnprocedure R is
Level_2: aliased Integer;
begin
Q(Level_2'Access); -- (3)
end R;
22.ooLevel_1: aliased Integer;
begin
Q(Level_1'Access); -- (4)
R;
end Main;
type_declaration
, the rules are checked in an assume-the-worst manner. For example: package P is
type Int_Ptr is access all Integer;
type Rec(D: access Integer) is limited private;
private
type Rec_Ptr is access all Rec;
function F(X: Rec_Ptr) return Boolean;
function G(X: access Rec) return Boolean;
type Rec(D: access Integer) is
limited record
C1: Int_Ptr := Int_Ptr(D); -- Illegal!
C2: Rec_Ptr := Rec'Access; -- Illegal!
C3: Boolean := F(Rec'Access); -- Illegal!
C4: Boolean := G(Rec'Access);
end record;
end P;
The following attribute is defined for a prefix
X that denotes an aliased view of an object:
X'Access
- {8652/0010} 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 an access-to-variable type, then the view shall be a variable; [on the other hand, if A is an access-to-constant type, the view may be either a constant or a variable.]
- The view shall not be a subcomponent that depends on discriminants of an object unless the object is known to be constrained.
- Place nondiscriminant-dependent components with any aliased parts at offsets preceding any discriminant-dependent components in a discriminated record type with defaulted discriminants.
- Preallocate the maximum space for unconstrained discriminated variables with aliased subcomponents, rather than allocating the initial size and moving them to a larger (heap-resident) place if they grow as the result of an assignment.
- {8652/0010} 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:
- the designated subtype of A shall statically match the nominal subtype of the view; or
- D shall be discriminated in its full view and unconstrained in any partial view, and the designated subtype of A shall be unconstrained.
- The accessibility level of the view shall not be statically deeper than that of the access type A.
allocator
. The latter case is illegal if the accessibility level of X is statically deeper than that of the access type of the allocator
; a runtime check is needed in the case where the initial value comes from an access parameter. Other anonymous access-to-object types have "normal" accessibility checks. - In addition to the places where Legality Rules normally apply (see 12.3), these requirements apply also in the private part of an instance of a generic unit.
- A check is made that the accessibility level of X is not deeper than that of the access type A. If this check fails, Program_Error is raised.
- 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 can raise Constraint_Error — see 4.6) and the value of X'Access designates that view.
The following attribute is defined for a prefix
P that denotes a subprogram:
P'Access
- 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. If S is nonblocking, P shall be nonblocking. In addition to the places where Legality Rules normally apply (see 12.3), these rules apply 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.
Legality Rules
32.1/3An expression
is said to have distributed accessibility if it is
- a
conditional_expression
(see 4.5.7); or 32.3/5 - a
declare_expression
(see 4.5.9) whose body_expression
has distributed accessibility; or 32.4/5 - a view conversion,
qualified_expression
, or parenthesized expression whose operand has distributed accessibility.
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_expression
s of the underlying conditional_expression
. This rule is applied recursively if a dependent_expression
also has distributed accessibility.
expression
(or that of the type of an expression
) shall or shall not be statically deeper than some other level also applies, in the case where the expression
has distributed accessibility, to each dependent_expression
of the underlying conditional_expression
. 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).explicit_dereference
or an implicit_dereference
. See 4.1.Examples
40Example of use of the Access attribute:
Becky : Person_Name := new Person(F); -- see 3.10.1
Cars : array (1..2) of aliased Car;
...
Becky .Vehicle := Cars(1)'Access;
Casey .Vehicle := Cars(2)'Access;
Extensions to Ada 83
prefix
takes care of them all. This means that there should never be a case when X.all'Last is legal while X'Last is not. See AI83-00154. Incompatibilities With Ada 95
type T1 (D1 : Boolean := False) is
record
case D1 is
when False =>
C1 : aliased Integer;
when True =>
null;
end case;
end record;
type Acc_Int is access all Integer;
41.d/2A_T : aliased T1;
Ptr : Acc_Int := A_T.C1'Access; -- Illegal in Ada 2005, legal in Ada 95
A_T := (D1 => True); -- Raised Constraint_Error in Ada 95, but does not
-- in Ada 2005, so Ptr would become invalid when this
-- is assigned (thus Ptr is illegal).
Extensions to Ada 95
type Int_Ptr is access all Integer;
type Float_Ptr is access all Float;
41.j/2function Zap (Val : Int_Ptr) return Float;
function Zap (Val : Float_Ptr) return Float;
41.k/2Value : aliased Integer := 10;
41.l/2Result1 : Float := Zap (Value'access); -- Ambiguous in Ada 95; resolves in Ada 2005.
Result2 : Float := Zap (Int_Ptr'(Value'access)); -- Resolves in Ada 95 and Ada 2005.
Wording Changes from Ada 95
Incompatibilities With Ada 2005
Extensions to Ada 2005
Wording Changes from Ada 2005
conditional_expression
s (see 4.5.7).Inconsistencies With Ada 2012
type Rec is record
Comp : aliased Integer;
...
end record;
41.dd/5function F1 (A : aliased in out Rec) return access Integer is
function F2 (B : access Integer) return access Integer
is (B); -- (1)
begin
return F2 (A.Comp'Access); -- (2)
end F1;
Incompatibilities With Ada 2012
aggregate
built at the point of the conversion. This was previously unspecified, so this change might be incompatible if an Ada implementation treated the accessibility of such conversions as that of the operand type; in that case, previous legal conversions probably will become illegal as the lifetime of the conversion is very short. However, code that could tell this difference is fairly rare (taking 'Access of a component of a result of a type conversion), code depending on this accessibility was not portable, and such code could have created an immediately dangling pointer if the conversion actually made a copy (which is necessary in some instances).Extensions to Ada 2012
Wording Changes from Ada 2012
extended_return_statement
is defined here rather than in 6.5 so that all accessibility rules are here.raise_expression
does not need any static checks (it is considered to match any accessibility required).