# Ada Programming/Types/access
## What's an Access Type?

Access types in Ada are what other languages call pointers. They point to objects located at certain addresses. So normally one can think of access types as simple addresses (there are exceptions from this simplified view). Ada instead of saying points to talks of granting access to or designating an object.
Objects of access types are implicitly initialized with null, i.e. they point to nothing when not explicitly initialized.
Access types should be used rarely in Ada. In a lot of circumstances where pointers are used in other languages, there are other ways without pointers. If you need dynamic data structures, first check whether you can use the Ada Container library. Especially for indefinite record or array components, the Ada 2012 package Ada.Containers.Indefinite_Holders (RM A.18.18) can be used instead of pointers.
There are four kinds of access types in Ada: Pool access types - General access types - Anonymous access types - Access to subprogram types.

## Pool access

A pool access type handles accesses to objects which were created on some specific heap (or storage pool as it is called in Ada). A pointer of these types cannot point to a stack or library level (static) object or an object in a different storage pool. Therefore, conversion between pool access types is illegal. (Unchecked_Conversion may be used, but note that deallocation via an access object with a storage pool different from the one it was allocated with is erroneous.)
A storage size clause may be used to limit the corresponding (implementation defined anonymous) storage pool. A storage size clause of 0 disables calls of an allocator.
The storage pool is implementation defined if not specified. Ada supports user defined storage pools, so you can define the storage pool with
Objects in a storage pool are created with the keyword new:
You access the object in the storage pool by appending .all. Mother.all is the complete record; components are denoted as usual with the dot notation: Mother.all.First_Name. When accessing components, implicit dereferencing (i.e. omitting all) can serve as a convenient shorthand:
Implicit dereferencing also applies to arrays:
Be careful to discriminate between deep and shallow copies when copying with access objects:

### Deleting objects from a storage pool

Although the Ada standard mentions a garbage collector, which would automatically remove all unneeded objects that have been created on the heap (when no storage pool has been defined), only Ada compilers targeting a virtual machine like Java or .NET actually have garbage collectors.
When an access type goes out of scope, the corresponding still allocated data items are finalized (i.e. they do no longer exist) in an arbitrary order; the allocated memory, however, is only freed when the attribute Storage_Size has been defined for the access type via an attribute_definition clause. (Note: Finalization and deallocation are different things!)

#### Proof

The following are excerpts from the Ada Reference Manual. The ellipses stand for parts not relevant for the case.
RM 3.10(7/1) There are ... access-to-object types, whose values designate objects... Associated with an access-to-object type is a storage pool; several access types may 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.
(8) Access-to-object types are further subdivided into pool-specific access types, whose values can designate only the elements of their associated storage pool...
RM 7.6(1) ... Every object is finalized before being destroyed (for example, by leaving a subprogram_body containing an object_declaration, or by a call to an instance of Unchecked_Deallocation)...
RM 7.6.1(5) For the finalization of an object:
(6/3) If the full type of the object is an elementary type, finalization has no effect;
(7/3) If the full type of the object is a tagged type, and the tag of the object identifies a controlled type, the Finalize procedure of that controlled type is called;
(10) Immediately before an instance of Unchecked_Deallocation reclaims the storage of an object, the object is finalized. If an instance of Unchecked_Deallocation is never applied to an object created by an allocator, the object will still exist when the corresponding master completes, and it will be finalized then.
(11.1/3) Each nonderived access type T has an associated collection, which is the set of objects created by allocators of T, or of types derived from T. Unchecked_Deallocation removes an object from its collection. Finalization of a collection consists of finalization of each object in the collection, in an arbitrary order…
RM 13.11(1) Each access-to-object type has an associated storage pool. The storage allocated by an allocator comes from the pool; instances of Unchecked_Deallocation return storage to the pool. Several access types can share the same pool.
(2/2) A storage pool is a variable of a type in the class rooted at Root_Storage_Pool, which is an abstract limited controlled type. By default, the implementation chooses a standard storage pool for each access-to-object type…
(11) A storage pool type (or pool type) is a descendant of Root_Storage_Pool. The elements of a storage pool are the objects allocated in the pool by allocators.
(15) Storage_Size or Storage_Pool may be specified for a nonderived access-to-object type via an attribute_definition_clause...
(17) If Storage_Pool is not specified for a type defined by an access_to_object_definition, then the implementation chooses a standard storage pool for it in an implementation-defined manner...
(18/4) If Storage_Size is specified for an access type T, an implementation-defined pool P is used for the type. The Storage_Size of P is at least that requested, and the storage for P is reclaimed when the master containing the declaration of the access type is left...

#### Example

The following program will compile but will fail the accessibility check on runtime with an exception.
There is also a pragma Controlled, which, when applied to such an access type, prevents automatic garbage collection of objects created with it. Note that pragma Controlled was dropped from Ada 2012, subpools for storage management replacing it. See RM 2012 13.11.3 and 13.11.4.
Therefore, in order to delete an object from the heap, you need the generic unit Ada.Unchecked_Deallocation. Apply utmost care to not create dangling pointers when deallocating objects as is shown in the example below. (And note that deallocating objects with a different access type than the one with which they were created is erroneous when the corresponding storage pools are different.)
It is exactly because of this problem with dangling pointers that the deallocation operation is called unchecked. It is the chore of the programmer to take care that this does not happen.
Since Ada allows for user-defined storage pools, you could also try a garbage collector library.

### Constructing Reference Counting Pointers

You can find some implementations of reference counting pointers, called Safe or Smart Pointers, on the net. Using such a type prevents caring about deallocation, since this will automatically be done when there are no more pointers to an object. But be careful - most of those implementations do not prevent deliberate deallocation, thus undermining the alleged safety attained with their use.
A nice tutorial how to construct such a type can be found in a series of Gems on the AdaCore web site.
Gem #97: Reference Counting in Ada – Part 1 This little gem constructs a simple reference counted pointer that does not prevent deallocation, i.e. is inherently unsafe.
Gem #107: Preventing Deallocation for Reference-counted Types This further gem describes how to arrive at a pointer type whose safety cannot be compromised (tasking issues aside). The cost of this improved safety is awkward syntax.
Gem #123: Implicit Dereferencing in Ada 2012 This gem shows how to simplify the syntax with the new Ada 2012 generation. (Admittedly, this gem is a bit unrelated to reference counting since the new language feature can be applied to any kind of container.)

## General access

General access types grant access to objects created on any storage pool, on the stack or at library level (static). They come in two versions, granting either read-write access or read-only access. Conversions between general access types are allowed, but subject to certain access level checks.
Dereferencing is like for pool access types. Objects (other than pool objects) to be referenced have to be declared aliased, and references to them are created with the attribute 'Access. Access level restrictions prevent accesses to objects from outliving the accessed object, which would make the program erroneous. The attribute 'Unchecked_Access omits the corresponding checks.

### Access to Variable

When the keyword all is used in their definition, they grant read-write access.

### Access to Constant

General access types granting read-only access to the referenced object use the keyword constant in their definition. The referenced object may be a constant or a variable.

### Some examples
## Anonymous access

Also Anonymous access types come in two versions like general access types, granting either read-write access or read-only access depending on whether the keyword constant appears.
An anonymous access can be used as a parameter to a subprogram or as a discriminant. Here are some examples:
Before using an anonymous access, you should consider a named access type or, even better, consider if the "out" or "in out" modifier is not more appropriate.
This language feature is only available from Ada 2005 on.
In Ada 2005, anonymous accesses are allowed in more circumstances:

## Implicit Dereference

This language feature has been introduced in Ada 2012.
Ada 2012 simplifies accesses to objects via pointers with new syntax.
Imagine you have a container holding some kind of elements.
Now, how do you access elements stored in the container. Of course, you can retrieve them by
This will however copy the element, which is unfortunate if the element is big. You get direct access with
Now, pointers are dangerous since you might easily create dangling pointers like so:
Use of an accessor object instead of an access type can prevent inadvertent deallocation (this is still Ada 2005):
(For the null exclusion not null in the declaration of the discriminant, see below). Access via such an accessor is safe: The discriminant can only be used for dereferencing, it cannot be copied to an object of type Element_Ptr because its accessibility level is deeper. In the form above, the accessor provides read and write access. If the keyword constant is added, only read access is possible.
Access to the container object now looks like so:
Here the new Ada 2012 feature of aspects comes along handy; for the case at hand, the aspect Implicit_Dereference is the one we need:
Now rather than writing the long and ugly function call of above, we can just omit the discriminant and its dereference like so:
Note that the call Get (Cont) is overloaded — it can denote the accessor object or the element, the compiler will select the correct interpretation depending on context.

## Null exclusions

This language feature is only available from Ada 2005 on.
All access subtypes can be modified with not null, objects of such a subtype can then never have the value null, so initializations are compulsory.
The language also allows to declare the first subtype directly with a null exclusion:
However, in nearly all cases this is not a good idea because it renders objects of this type nearly unusable (for example, you are unable to free the allocated memory). Not null accesses are intended for access subtypes, object declarations, and subprogram parameters.

## Access to Subprogram

An access to subprogram allows the caller to call a subprogram without knowing its name nor its declaration location. One of the uses of this kind of access is the well known callbacks.
For getting an access to a subprogram, the attribute Access is applied to a subprogram name with the proper parameter and result profile.

### Anonymous access to Subprogram

This language feature is only available from Ada 2005 on.
There is now no limit on the number of keyword in a sequence:
This is a function that returns the access to a function that in turn returns an access to a function returning an access to some type.

## Access FAQ

A few "Frequently Asked Question" and "Frequently Encountered Problems" (mostly from C users) regarding Ada's access types.

### Access vs. access all

An access all can do anything a simple access can do. So one might ask: "Why use simple access at all?" - And indeed some programmers never use simple access.
Unchecked_Deallocation is always dangerous if misused. It is just as easy to deallocate a pool-specific object twice, and just as dangerous as deallocating a stack object. The advantage of "access all" is that you may not need to use Unchecked_Deallocation at all.
Moral: if you have (or may have) a valid reason to store an 'Access or 'Unchecked_Access into an access object, then use "access all" and don't worry about it. If not, the mantra of "least privilege" suggests that the "all" should be left out (don't enable capabilities that you are not going to use).
The following (perhaps disastrous) example will try to deallocate a stack object:
With a simple access you know at least that you won't try to deallocate a stack object. The reason is that access does not allow pointers to be created from stack objects.

### Access vs. System.Address

An access can be something different from a mere memory address, it may be something more. For example, an "access to String" often needs some way of storing the string size as well. If you need a simple address and are not concerned about strong typing, use the System.Address type.

### C compatible pointer

The correct way to create a C compatible access is to use pragma Convention:
pragma Convention should be used on any type you want to use in C. The compiler will warn you if the type cannot be made C compatible.
You may also consider the following - shorter - alternative when declaring Day_Of_Month:
Before you use access types in C, you should consider using the normal "in", "out" and "in out" modifiers. pragma Export and pragma Import know how parameters are usually passed in C and will use a pointer to pass a parameter automatically where C would have used them as well. Of course the RM contains precise rules on when to use a pointer for "in", "out", and "in out" - see "B.3: Interfacing with C".

### Where is void*?

While actually a problem for "interfacing with C", here are some possible solutions:
Less portable, but perhaps more usable (for 32 bit CPUs):
With GNAT you can get 32/64 bit portability by using:
Closer to the true nature of void - pointing to an element of zero size is a pointer to a null record. This also has the advantage of having a representation for void and void*:

## Thin and Fat Access Types

The difference between an access type and an address will be detailed in the following. The term pointer is used because this is usual terminology.
There is a predefined unit System.Address_to_Access_Conversion converting back and forth between access values and addresses. Use these conversions with care, as is explained below.

### Thin Pointers

Thin pointers grant access to constrained subtypes.
Objects of subtypes like these have a static size, so a simple address suffices to access them. In the case of arrays, this is generally the address of the first element.
For pointers of this kind, use of System.Address_to_Access_Conversion is safe.

### Fat Pointers

Objects of subtype Unc need a constraint, i.e. a start and a stop index, thus pointers to them need also to include those. So a simple address like the one of the first component is not sufficient. Note that A'Address is the same as A(A'First)'Address for any array object.
For pointers of this kind, System.Address_to_Access_Conversion will probably not work satisfactorily.

### Example

Here, CO is a nominally constrained object, a pointer to it need not store the constraint, i.e. a thin pointer suffices. In contrast, UO is an object of a nominally unconstrained subtype, its actual subtype is constrained by the initial value.
The relevant paragraphs in the RM are difficult to understand. In short words:
An access type's target type is called the designated subtype, in our example Unc. RM 3.10.2(27.1/2) requires that Acc_Unc's designated subtype statically match the nominal subtype of the object.
Now the nominal subtype of CO is the constrained anonymous subtype Unc (-1 .. +1), the nominal subtype of UO is the unconstrained subtype Unc. In the illegal cases, the designated and nominal subtypes do not statically match.

## See also
### Wikibook

* Ada Programming
* Ada Programming/Types

### Ada Reference Manual
#### Ada 95

* 4.8: Allocators
* 13.11: Storage Management
* 13.11.2: Unchecked Storage Deallocation
* 3.7: Discriminants
* 3.10: Access Types
* 6.1: Subprogram Declarations
* B.3: Interfacing with C

#### Ada 2005

* 4.8: Allocators
* 13.11: Storage Management
* 13.11.2: Unchecked Storage Deallocation
* 3.7: Discriminants
* 3.10: Access Types
* 6.1: Subprogram Declarations
* B.3: Interfacing with C

#### Newest RM

* 3.10: Access Types
* 7.6: Assignment and Finalization
* 7.6.1: Completion and Finalization
* 13.11: Storage Management

### Ada Quality and Style Guide

* 5.4.5 Dynamic Data
* 5.9.2 Unchecked Deallocation