3.10 Access Types
1
{access type} 
{access value} 
{designate} 
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. 
{pointer: 
See access value} {pointer 
type: See access type}  
1.a
Discussion: A name 
denotes an entity; an access value designates an entity. 
The “dereference” of an access value X, written “X.all”, 
is a name that denotes the entity designated 
by X. 
Language Design Principles
1.b
Access values should always be well defined 
(barring uses of certain unchecked features of Section 13). In particular, 
uninitialized access variables should be prevented by compile-time rules. 
Syntax
2/2
{
AI95-00231-01} 
access_type_definition ::= 
    [null_exclusion] access_to_object_definition
  | 
[null_exclusion] access_to_subprogram_definition 
3
access_to_object_definition ::= 
    access [
general_access_modifier] 
subtype_indication 
4
general_access_modifier ::= all | 
constant 
5
access_to_subprogram_definition ::= 
    access [
protected] 
procedure parameter_profile
  | 
access [
protected] 
function  parameter_and_result_profile 
5.1/2
6/2
{
AI95-00231-01} 
{
AI95-00254-01} 
{
AI95-00404-01} 
access_definition ::= 
    [null_exclusion] access [constant] subtype_mark
  | [null_exclusion] access [protected] procedure parameter_profile
  | [null_exclusion] access [protected] function parameter_and_result_profile access subtype_mark 
Static Semantics
7/1
{
8652/0012} 
{
AI95-00062-01} 
{access-to-object type} {access-to-subprogram 
type} {pool-specific 
access type} {general 
access type} There are two kinds of access 
types, 
access-to-object types, whose values designate objects, 
and 
access-to-subprogram types, whose values designate subprograms. 
{storage pool} 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. {pool 
element} 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”].
 
8
{pool-specific access 
type} {general 
access type} 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. 
 
8.a
Implementation Note: The value of an 
access type will typically be a machine address. However, a value of 
a pool-specific access type can be represented as an offset (or index) 
relative to its storage pool, since it can point only to the elements 
of that pool. 
9/2
{
AI95-00225-01} 
{
AI95-00363-01} 
{aliased} A 
view of an object is defined to be 
aliased if it is defined by 
an 
object_declaration or 
component_definition 
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. 
The Finally, 
the current instance of a limited
 tagged 
type, 
a protected type, a task type, or a type 
that has the reserved word limited in its full definition is also 
defined to be aliased. Finally, and 
a formal parameter or generic formal object of a tagged type 
is are 
defined to be aliased. [Aliased views are the ones that can be designated 
by an access value.] 
{constrained 
(object)} {unconstrained 
(object)} {constrained 
by its initial value} If the view defined 
by an object_declaration is aliased, and the 
type of the object has discriminants, then the object is constrained; 
if its nominal subtype is unconstrained, then the object is constrained 
by its initial value. [Similarly, if the object created by an allocator 
has discriminants, the object is constrained, either by the designated 
subtype, or by its initial value.]  
9.a
Glossary entry: {Aliased} An aliased 
view of an object is one that can be designated by an access value. Objects 
allocated by allocators are aliased. Objects can also be explicitly declared 
as aliased with the reserved word aliased. The Access attribute 
can be used to create an access value designating an aliased object.
9.b
Ramification: The current instance of 
a nonlimited type is not aliased.
9.c
The object created by an allocator is aliased, 
but not its subcomponents, except of course for those that themselves 
have aliased in their component_definition.
9.d
The renaming of an aliased object is aliased.
9.e
Slices are never aliased. See 
4.1.2 
for more discussion. 
 
9.f/2
Reason: {
AI95-00225-01} 
The current instance of a limited type is defined to be aliased so that 
an access discriminant of a component can be initialized with T'Access 
inside the definition of T.
 Note that we don't 
want this to apply to a type that could become nonlimited later within 
its immediate scope, so we require the full definition to be limited. 
9.g
A formal parameter of a tagged type is defined 
to be aliased so that a (tagged) parameter X may be passed to an access 
parameter P by using P => X'Access. Access parameters are most important 
for tagged types because of dispatching-on-access-parameters (see 
3.9.2). 
By restricting this to formal parameters, we minimize problems associated 
with allowing components that are not declared aliased to be pointed-to 
from within the same record.
 
9.h
A view conversion 
of an aliased view is aliased so that the type of an access parameter 
can be changed without first converting to a named access type. For example: 
9.i
type T1 is tagged ...;
procedure P(X : access T1);
9.j
type 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;
9.k/2
This paragraph 
was deleted.{
AI95-00363-01} 
The rule about objects with discriminants is necessary 
because values of a constrained access subtype can designate an object 
whose nominal subtype is unconstrained; without this rule, a check on 
every use of such values would be required to ensure that the discriminants 
of the object had not changed. With this rule (among others), we ensure 
that if there might exist aliased views of a discriminated object, then 
the object is necessarily constrained. Note that this rule is necessary 
only for untagged types, since a discriminant of a tagged type can't 
have a default, so all tagged discriminated objects are always constrained 
anyway.  
9.l/2
We considered making more kinds of objects aliased 
by default. In particular, any object of a by-reference type will pretty 
much have to be allocated at an addressable location, so it can be passed 
by reference without using bit-field pointers. Therefore, one might wish 
to allow the Access and and Unchecked_Access 
attributes for such objects. However, private parts are transparent to 
the definition of “by-reference type”, so if we made all 
objects of a by-reference type aliased, we would be violating the privacy 
of private parts. Instead, we would have to define a concept of “visibly 
by-reference” and base the rule on that. This seemed to complicate 
the rules more than it was worth, especially since there is no way to 
declare an untagged limited private type to be by-reference, since the 
full type might by nonlimited. 
9.m
Discussion: Note that we do not use the 
term “aliased” to refer to formal parameters that are referenced 
through multiple access paths (see 
6.2). 
 
10
An 
access_to_object_definition 
defines an access-to-object type and its first subtype; 
{designated 
subtype (of a named access type)} {designated 
type (of a named access type)} 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. 
{access-to-constant 
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]. 
{access-to-variable 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. 
 
10.a
To be honest: The type of the designated 
subtype is called the designated type. 
10.b
Reason: The modifier all was picked 
to suggest that values of a general access type could point into “all” 
storage pools, as well as to objects declared aliased, and that “all” 
access (both read and update) to the designated object was provided. 
We couldn't think of any use for pool-specific access-to-constant types, 
so any access type defined with the modifier constant is considered 
a general access type, and can point into any storage pool or at other 
(appropriate) aliased objects. 
10.c
Implementation Note: The predefined generic 
Unchecked_Deallocation can be instantiated for any named access-to-variable 
type. There is no (language-defined) support for deallocating objects 
designated by a value of an access-to-constant type. Because of this, 
an allocator for an access-to-constant type can allocate out of a storage 
pool with no support for deallocation. Frequently, the allocation can 
be done at link-time, if the size and initial value are known then. 
10.d
Discussion: For the purpose of generic 
formal type matching, the relevant subclasses of access types are access-to-subprogram 
types, access-to-constant types, and (named) access-to-variable types, 
with its subclass (named) general access-to-variable types. Pool-specific 
access-to-variable types are not a separately matchable subclass of types, 
since they don't have any “extra” operations relative to 
all (named) access-to-variable types. 
11
{access-to-subprogram 
type} An 
access_to_subprogram_definition 
defines an access-to-subprogram type and its first subtype; 
{designated 
profile (of an access-to-subprogram type)} the 
parameter_profile or 
parameter_and_result_profile 
defines the 
designated profile of the access type. 
{calling 
convention (associated with a designated profile)} 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.] 
 
11.a
Ramification: The calling convention 
protected is in italics to emphasize that it cannot be specified 
explicitly by the user. This is a consequence of it being a reserved 
word. 
11.b/2
Implementation Note: {
AI95-00254-01} 
For 
a named an 
access-to-subprogram type, the representation of an access value might 
include implementation-defined information needed to support up-level 
references — for example, a static link. The accessibility rules 
(see 
3.10.2) ensure that in a "global-display-based" 
implementation model (as opposed to a static-link-based model), 
a 
named an access-to-(unprotected)-subprogram 
value need consist only of the address of the subprogram. The global 
display is guaranteed to be properly set up any time the designated subprogram 
is called. Even in a static-link-based model, the only time a static 
link is definitely required is for an access-to-subprogram type declared 
in a scope nested at least two levels deep within subprogram or task 
bodies, since values of such a type might designate subprograms nested 
a smaller number of levels. For the normal case of 
a 
named an access-to-subprogram type 
declared at the outermost (library) level, a code address by itself should 
be sufficient to represent the access value in many implementations.
 
11.c
For access-to-protected-subprogram, the access 
values will necessarily include both an address (or other identification) 
of the code of the subprogram, as well as the address of the associated 
protected object. This could be thought of as a static link, but it will 
be needed even for global-display-based implementation models. It corresponds 
to the value of the “implicit parameter” that is passed into 
every call of a protected operation, to identify the current instance 
of the protected type on which they are to operate.
11.d
Any Elaboration_Check is performed when a call 
is made through an access value, rather than when the access value is 
first "created" via a 'Access. For implementation models that 
normally put that check at the call-site, an access value will have to 
point to a separate entry point that does the check. Alternatively, the 
access value could point to a "subprogram descriptor" that 
consisted of two words (or perhaps more), the first being the address 
of the code, the second being the elaboration bit. Or perhaps more efficiently, 
just the address of the code, but using the trick that the descriptor 
is initialized to point to a Raise-Program-Error routine initially, and 
then set to point to the "real" code when the body is elaborated.
11.e
For implementations that share code between 
generic instantiations, the extra level of indirection suggested above 
to support Elaboration_Checks could also be used to provide a pointer 
to the per-instance data area normally required when calling shared code. 
The trick would be to put a pointer to the per-instance data area into 
the subprogram descriptor, and then make sure that the address of the 
subprogram descriptor is loaded into a "known" register whenever 
an indirect call is performed. Once inside the shared code, the address 
of the per-instance data area can be retrieved out of the subprogram 
descriptor, by indexing off the "known" register.
11.f/2
This paragraph 
was deleted.{
AI95-00344-01} 
Essentially the same implementation issues arise 
for calls on dispatching operations of tagged types, except that the 
static link is always known "statically." 
11.g/2
{
AI95-00254-01} 
Note that access parameters of an anonymous access-to-subprogram type 
are 
not permitted. 
Such If 
there were such parameters
 represent, 
full “downward” closures
would be required, 
meaning that in an implementation that uses a per-task (global) display, 
the display 
will would 
have to be passed as a hidden parameter, and reconstructed at the point 
of call.
 This was felt to be an undue implementation 
burden, given that an equivalent (actually, more general) capability 
is available via formal subprogram parameters to a generic.  
12/2
 {
AI95-00230-01} 
{
AI95-00231-01} 
{
AI95-00254-01} 
{anonymous access type} {designated 
subtype (of an anonymous access type)} {designated 
type (of an anonymous access type)} An 
access_definition defines an anonymous general 
access type or an anonymous access-to-subprogram 
type. For a general access type, access-to-variable 
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.{designated 
profile (of an anonymous access type)} . 
[An access_definition is used in the specification 
of an access discriminant (see 3.7) or an access 
parameter (see 6.1).] 
13/2
 {
AI95-00230-01} 
{
AI95-00231-01} 
{null value (of an access type)} 
For each 
(named) access 
type, there is 
a literal null which has 
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 a 
named access type is the default initial value of the type.] 
Non-null Other 
values of an access
-to-object type are obtained 
by evaluating 
an attribute_reference 
for the Access or Unchecked_Access attribute of an aliased view of an 
object or non-intrinsic subprogram, or, in the case of a named access-to-object 
type, 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. Non-null values of an access-to-subprogram type are obtained 
by evaluating an attribute_reference for the 
Access attribute of a non-intrinsic subprogram..
 
13.a/2
This paragraph 
was deleted.Ramification: {
AI95-00231-01} 
A value of an anonymous access type (that is, the 
value of an access parameter or access discriminant) cannot be null. 
 
13.b/2
This paragraph 
was deleted.Reason: {
AI95-00231-01} 
Access parameters allow dispatching on the tag 
of the object designated by the actual parameter (which gets converted 
to the anonymous access type as part of the call). In order for dispatching 
to work properly, there had better be such an object. Hence, the type 
conversion will raise Constraint_Error if the value of the actual parameter 
is null.  
13.1/2
   {
AI95-00231-01} 
{excludes null 
(subtype)} 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. 
 
13.c/2
Reason: {
AI95-00231-01} 
An 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. 
13.d/2
{
AI95-00416-01} 
Note that we considered imposing a similar implicit 
null exclusion for controlling access results, but chose not to do that, 
because there is no Ada 95 compatibility issue, and there is no automatic 
null check inherent in the use of a controlling access result. If a null 
check is necessary, it is because there is a dereference of the result, 
or because the value is passed to a parameter whose subtype excludes 
null. If there is no dereference of the result, a null return value is 
perfectly acceptable, and can be a useful indication of a particular 
status of the call.  
14/1
 {
8652/0013} 
{
AI95-00012-01} 
{constrained (subtype) [partial]} 
{unconstrained (subtype) 
[partial]} [All subtypes of an access-to-subprogram 
type are constrained.] The first subtype of a type defined by an 
access_definition access_type_definition 
or an 
access_to_object_definition is unconstrained 
if the designated subtype is an unconstrained array or discriminated 
subtype type; 
otherwise it is constrained. 
 
14.a
Proof: The Legality Rules on 
range_constraints 
(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_constraints 
(see 
3.6.1) and 
discriminant_constraints 
(see 
3.7.1) both permit access-to-composite 
types in a 
subtype_indication with such 
_constraints. 
Note that an access-to-access-to-composite is never permitted in a 
subtype_indication 
with a 
constraint. 
 
14.b/2
Reason: {
AI95-00363-01} 
Only 
composite_constraints 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 
aliased 
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.(by fiat, 
see Static Semantics).  
Legality Rules
14.1/2
   {
AI95-00231-01} 
If 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.  
14.c/2
To be honest: {
AI95-00231-01} 
This means “directly allowed in”; we 
are not talking about a 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).  
14.d/2
Reason: {
AI95-00231-01} 
This is similar to doubly constraining a composite 
subtype, which we also don't allow.  
Dynamic Semantics
15/2
 {
AI95-00231-01} 
{compatibility (composite_constraint 
with an access subtype) [partial]} A 
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. 
{satisfies (for an access value) 
[partial]} 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. 
16
{elaboration (access_type_definition) 
[partial]} 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.
 
17/2
 {
AI95-00230-01} 
{
AI95-00254-01} 
{elaboration (access_definition) 
[partial]} The elaboration of an 
access_definition 
creates an anonymous
 general access
-to-variable 
type
 [(this happens as part of the initialization 
of an access parameter or access discriminant)]. 
 
18
81  Access values are called “pointers” 
or “references” in some other languages.
19
82  Each access-to-object type has an associated 
storage pool; several access types can share the same pool. An object 
can be created in the storage pool of an access type by an 
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.
 
20
83  Only 
index_constraints 
and 
discriminant_constraints can be applied 
to access types (see 
3.6.1 and 
3.7.1). 
 
Examples
21
Examples of access-to-object 
types: 
22/2
{
AI95-00433-01} 
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 
23
Example of an access 
subtype: 
24
subtype Drum_Ref 
is Peripheral_Ref(Drum);  --
  see 3.8.1 
25
Example of an access-to-subprogram 
type: 
26
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
26.a
{
extensions to Ada 83} 
The 
syntax for 
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
26.b
We use the term "storage pool" to 
talk about the data area from which allocation takes place. The term 
"collection" is no longer used. ("Collection" and 
"storage pool" are not the same thing because multiple unrelated 
access types can share the same storage pool; see 
13.11 
for more discussion.) 
 
Inconsistencies With Ada 95
26.c/2
{
AI95-00231-01} 
{inconsistencies with Ada 95} Access 
discriminants and non-controlling access parameters no longer exclude 
null. A program which passed null to such an access discriminant 
or access parameter and expected it to raise Constraint_Error may fail 
when compiled with Ada 2005. One hopes that there no such programs outside 
of the ACATS. (Of course, a program which actually wants to pass null 
will work, which is far more likely.) 
26.d/2
{
AI95-00363-01} 
Most unconstrained aliased objects with defaulted 
discriminants are no longer constrained by their initial values. This 
means that a program that raised Constraint_Error from an attempt to 
change the discriminants will no longer do so. The change only affects 
programs that depended on the raising of Constraint_Error in this case, 
so the inconsistency is unlikely to occur outside of the ACATS. This 
change may however cause compilers to implement these objects differently, 
possibly taking additional memory or time. This is unlikely to be worse 
than the differences caused by any major compiler upgrade.  
Incompatibilities With Ada 95
26.e/2
{
AI95-00225-01} 
{incompatibilities with Ada 95} Amendment 
Correction: The rule defining when a current instance of a limited 
type is considered to be aliased has been tightened to apply only to 
types that cannot become nonlimited. A program that attempts to take 
'Access of the current instance of a limited type that can become nonlimited 
will be illegal in Ada 2005. While original Ada 95 allowed the current 
instance of any limited type to be treated as aliased, this was inconsistently 
implemented in compilers, and was likely to not work as expected for 
types that are ultimately nonlimited.  
Extensions to Ada 95
26.f/2
{
AI95-00231-01} 
{extensions to Ada 95} The 
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. 
26.g/2
{
AI95-00231-01} 
{
AI95-00254-01} 
{
AI95-00404-01} 
The kinds of anonymous access types allowed were 
increased by adding anonymous access-to-constant and anonymous access-to-subprogram 
types. Anonymous access-to-subprogram types used as parameters allow 
passing of subprograms at any level.  
Wording Changes from Ada 95
26.h/2
{
8652/0012} 
{
AI95-00062-01} 
Corrigendum: Added accidentally-omitted 
wording that says that a derived access type shares its storage pool 
with its parent type. This was clearly intended, both because of a note 
in 3.4, and because anything else would have 
been incompatible with Ada 83. 
26.i/2
{
8652/0013} 
{
AI95-00012-01} 
Corrigendum: Fixed typographical errors 
in the description of when access types are constrained. 
26.j/2
{
AI95-00230-01} 
The wording was fixed to allow allocators 
and the literal null for anonymous access types. The former was 
clearly intended by Ada 95; see the Implementation Advice in 13.11. 
26.k/2
{
AI95-00363-01} 
The rules about aliased objects being constrained 
by their initial values now apply only to allocated objects, and thus 
have been moved to 4.8, “Allocators”.