4.8 Allocators
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
[The evaluation of an allocator
creates an object and yields an access value that designates the object. ]
Syntax
2/3allocator
::=
new [subpool_specification
] subtype_indication
| new [subpool_specification
] qualified_expression
2.1/3subpool_specification
::=
(subpool_handle_name
)
2.2/3For an allocator
with a subtype_indication
, the subtype_indication
shall not specify a null_exclusion
.
allocator
would necessarily raise Constraint_Error, as the default value is null. Also note that the syntax does not allow a null_exclusion
in an initialized allocator
, so it makes sense to make the uninitialized case illegal as well. Name Resolution Rules
3/3{8652/0010} The expected type for an allocator
shall be a single access-to-object type with designated type D such that either D covers the type determined by the subtype_mark
of the subtype_indication
or qualified_expression
, or the expected type is anonymous and the determined type is D'Class. A subpool_handle_name
is expected to be of any type descended from Subpool_Handle, which is the type used to identify a subpool, declared in package System.Storage_Pools.Subpools (see 13.11.4).
Legality Rules
4An initialized allocator is an allocator
with a qualified_expression
. An uninitialized allocator is one with a subtype_indication
. In the subtype_indication
of an uninitialized allocator, a constraint
is permitted only if the subtype_mark
denotes an [unconstrained] composite subtype; if there is no constraint
, then the subtype_mark
shall denote a definite subtype.
If the type of the allocator
is an access-to-constant type, the allocator
shall be an initialized allocator.
If a subpool_specification
is given, the type of the storage pool of the access type shall be a descendant of Root_Storage_Pool_With_Subpools.
If the designated type of the type of the allocator
is class-wide, the accessibility level of the type determined by the subtype_indication
or qualified_expression
shall not be statically deeper than that of the type of the allocator
.
If the subtype determined by the subtype_indication
or qualified_expression
of the allocator
has one or more access discriminants, then the accessibility level of the anonymous access type of each access discriminant shall not be statically deeper than that of the type of the allocator
(see 3.10.2).
An allocator
shall not be of an access type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero.
allocator
for an access type that has Storage_Size specified to be zero is required to raise Storage_Error anyway. It's better to detect the error at compile-time, as the allocator
might be executed infrequently. This also simplifies the rules for Pure units, where we do not want to allow any allocators for library-level access types, as they would represent state.allocator
s are not allowed, so we don't need to consider them. So we don't need an assume-the-best rule here. If the designated type of the type of the allocator
is limited, then the allocator
shall not be used to define the value of an access discriminant, unless the discriminated type is immutably limited (see 7.5).
allocator
. Note that there is an asymmetry in what types are considered limited; this is required to preserve privacy. We have to assume that the designated type might be limited as soon as we see a limited partial view, but we want to ensure that the containing object is of a type that is always limited. 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.
Static Semantics
6/3If the designated type of the type of the allocator
is elementary, then the subtype of the created object is the designated subtype. If the designated type is composite, then the subtype of the created object is the designated subtype when the designated subtype is constrained or there is an ancestor of the designated type that has a constrained partial view; otherwise, the created object is constrained by its initial value [(even if the designated subtype is unconstrained with defaults)].
allocator
are aliased, and most aliased composite objects need to be constrained so that access subtypes work reasonably. Problematic access subtypes are prohibited for types with a constrained partial view. Dynamic Semantics
7/2For the evaluation of an initialized allocator, the evaluation of the qualified_expression
is performed first. An object of the designated type is created and the value of the qualified_expression
is converted to the designated subtype and assigned to the object.
For the evaluation of an uninitialized allocator, the elaboration of the subtype_indication
is performed first. Then:
- If the designated type is elementary, an object of the designated subtype is created and any implicit initial value is assigned;
- {8652/0002} If the designated type is composite, an object of the designated type is created with tag, if any, determined by the
subtype_mark
of thesubtype_indication
. This object is then initialized by default (see 3.3.1) using thesubtype_indication
to determine its nominal subtype. A check is made that the value of the object belongs to the designated subtype. Constraint_Error is raised if this check fails. This check and the initialization of the object are performed in an arbitrary order.
For any allocator
, if the designated type of the type of the allocator
is class-wide, then a check is made that the master of the type determined by the subtype_indication
, or by the tag of the value of the qualified_expression
, includes the elaboration of the type of the allocator
. If any part of the subtype determined by the subtype_indication
or qualified_expression
of the allocator
(or by the tag of the value if the type of the qualified_expression
is class-wide) has one or more access discriminants, then a check is made that the accessibility level of the anonymous access type of each access discriminant is not deeper than that of the type of the allocator
. Program_Error is raised if either such check fails.
qualified_expression
is class-wide (other cases are statically detected).task body TT is
type Acc_TC is access T'Class;
P : Acc_TC;
begin
accept E(X : T'Class) do
P := new T'Class'(X);
-- Master check on tag of X.
-- Can't use "accessibility levels" since they might be incomparable.
-- Must revert to checking that the master of the type identified by
-- X'tag includes the elaboration of Acc_TC, so it is sure to outlive it.
end E;
If the object to be created by an allocator
has a controlled or protected part, and the finalization of the collection of the type of the allocator
(see 7.6.1) has started, Program_Error is raised.
allocator
is evaluated in code reached from a Finalize routine for a type declared in the same master. That's highly unlikely; Finalize routines are much more likely to be deallocating objects than allocating them. If the object to be created by an allocator
contains any tasks, and the master of the type of the allocator
is completed, and all of the dependent tasks of the master are terminated (see 9.3), then Program_Error is raised.
If the allocator
includes a subpool_handle_name
, Constraint_Error is raised if the subpool handle is null. Program_Error is raised if the subpool does not belong (see 13.11.4) to the storage pool of the access type of the allocator
.
[If the created object contains any tasks, they are activated (see 9.2).] Finally, an access value that designates the created object is returned.
Bounded (Run-Time) Errors
11.1/2 It is a bounded error if the finalization of the collection of the type (see 7.6.1) of the allocator
has started. If the error is detected, Program_Error is raised. Otherwise, the allocation proceeds normally.
allocator
comes from a storage pool (possibly user defined). The exception Storage_Error is raised by an allocator
if there is not enough storage. Instances of Unchecked_Deallocation can be used to explicitly reclaim storage.allocator
, the exception Constraint_Error can be raised by the evaluation of the qualified_expression
, by the elaboration of the subtype_indication
, or by the initialization. Examples
16Examples of allocators:
new Cell'(0, null, null) -- initialized explicitly, see 3.10.1
new Cell'(Value => 0, Succ => null, Pred => null) -- initialized explicitly
new Cell -- not initialized
18new Matrix(1 .. 10, 1 .. 20) -- the bounds only are given
new Matrix'(1 .. 10 => (1 .. 20 => 0.0)) -- initialized explicitly
19new Buffer(100) -- the discriminant only is given
new Buffer'(Size => 80, Pos => 0, Value => (1 .. 80 => 'A')) -- initialized explicitly
20Expr_Ptr'(new Literal) -- allocator for access-to-class-wide type, see 3.9.1
Expr_Ptr'(new Literal'(Expression with 3.5)) -- initialized explicitly
Incompatibilities With Ada 83
subtype_indication
of an uninitialized allocator may not have an explicit constraint
if the designated type is an access type. In Ada 83, this was permitted even though the constraint
had no effect on the subtype of the created object. Extensions to Ada 83
Wording Changes from Ada 83
Inconsistencies With Ada 95
Incompatibilities With Ada 95
Extensions to Ada 95
allocator
can be a controlling parameter of a dispatching call. This was an oversight in Ada 95.Wording Changes from Ada 95
allocator
occurs after the finalization of the collection or the waiting for tasks. This is not listed as an incompatibility as the Ada 95 behavior was unspecified, and Ada 95 implementations tend to generate programs that crash in this case.allocator
s. These checks could not fail in Ada 95 (as all of the designated types had to be declared at the same level, so the access type would necessarily have been at the same level or more nested than the type of allocated object).allocator
s. These checks could not fail in Ada 95 as the discriminants always have the accessibility of the object. Incompatibilities With Ada 2005
null_exclusion
s illegal for uninitialized allocator
s, as such an allocator
would always raise Constraint_Error. Programs that depend on the unconditional raising of a predefined exception should be very rare.