6.1.1 Preconditions and Postconditions
For a noninstance subprogram,
a generic subprogram, or an entry, the following language-defined aspects
may be specified with an
aspect_specification
(see
13.1.1):
Pre
This aspect specifies a specific precondition for a callable entity;
it shall be specified by an
expression,
called a
specific precondition expression.
If not specified for an entity, the specific precondition expression
for the entity is the enumeration literal True.
Pre'Class
This aspect specifies a class-wide precondition for an operation of a
tagged type and its descendants; it shall be specified by an
expression,
called a
class-wide precondition expression.
If not specified for an entity, then if no other class-wide precondition
applies to the entity, the class-wide precondition expression for the
entity is the enumeration literal True.
Post
This aspect specifies a specific postcondition for a callable entity;
it shall be specified by an
expression,
called a
specific postcondition expression.
If not specified for an entity, the specific postcondition expression
for the entity is the enumeration literal True.
Post'Class
This aspect specifies a class-wide postcondition for an operation of
a tagged type and its descendants; it shall be specified by an
expression,
called a
class-wide postcondition expression.
If not specified for an entity, the class-wide postcondition expression
for the entity is the enumeration literal True.
Name Resolution Rules
The expected type for a precondition or postcondition
expression is any boolean type.
Within the expression for a Pre'Class or Post'Class
aspect for a primitive subprogram
S of a tagged type
T,
a
name that
denotes a formal parameter (or
S'Result) of type
T is interpreted
as though it had a (notional) type
NT that is a formal derived
type whose ancestor type is
T, with directly visible primitive
operations. Similarly, a
name
that denotes a formal access parameter (or
S'Result) of type access-to-
T
is interpreted as having type access-to-
NT. The result of this
interpretation is that the only operations that can be applied to such
names are
those defined for such a formal derived type.
For an attribute_reference with attribute_designator
Old, if the attribute reference has an expected type or shall resolve
to a given type, the same applies to the
prefix;
otherwise, the
prefix
shall be resolved independently of context.
Legality Rules
The Pre or Post aspect shall not be specified for
an abstract subprogram or a null procedure. Only the Pre'Class and Post'Class
aspects may be specified for such a subprogram.
If a type
T
has an implicitly declared subprogram
P inherited from a parent
type
T1 and a homograph (see
8.3) of
P from a progenitor type
T2, and
the corresponding primitive subprogram P1
of type T1 is neither null nor abstract; and
the class-wide precondition expression True does
not apply to P1 (implicitly or explicitly); and
there is a class-wide precondition expression that
applies to the corresponding primitive subprogram P2 of T2
that does not fully conform to any class-wide precondition expression
that applies to P1,
then:
If the type T is abstract, the implicitly
declared subprogram P is abstract.
Otherwise, the subprogram
P requires
overriding and shall be overridden with a nonabstract subprogram.
If a renaming of a subprogram or entry S1
overrides an inherited subprogram S2, then the overriding is illegal
unless each class-wide precondition expression that applies to S1
fully conforms to some class-wide precondition expression that applies
to S2 and each class-wide precondition expression that applies
to S2 fully conforms to some class-wide precondition expression
that applies to S1.
Pre'Class shall not be specified for an overriding
primitive subprogram of a tagged type T unless the Pre'Class aspect
is specified for the corresponding primitive subprogram of some ancestor
of T.
In addition to the places where
Legality Rules normally apply (see
12.3),
these rules also apply in the private part of an instance of a generic
unit.
Static Semantics
If a Pre'Class or Post'Class aspect is specified
for a primitive subprogram
S of a tagged type
T, or such
an aspect defaults to True, then a corresponding expression also applies
to the corresponding primitive subprogram
S of each descendant
of
T. The
corresponding expression is constructed from
the associated expression as follows:
References to formal parameters of S (or
to S itself) are replaced with references to the corresponding
formal parameters of the corresponding inherited or overriding subprogram
S (or to the corresponding subprogram S itself).
The primitive subprogram S is illegal if
it is not abstract and the corresponding expression for a Pre'Class or
Post'Class aspect would be illegal.
If performing checks is required by the Pre, Pre'Class,
Post, or Post'Class assertion policies (see
11.4.2)
in effect at the point of a corresponding aspect specification applicable
to a given subprogram or entry, then the respective precondition or postcondition
expressions are considered
enabled.
An
expression
is
potentially unevaluated if it occurs within:
the right operand of a short-circuit control form;
or
For a
prefix
X that denotes an object of a nonlimited type, the following attribute
is defined:
X'Old
Each X'Old in a postcondition
expression that is enabled denotes a constant that is implicitly declared
at the beginning of the subprogram body, entry body, or accept statement.
The implicitly
declared entity denoted by each occurrence of X'Old is declared as follows:
X'Old : constant A := X;
If X is
of a specific tagged type T then
anonymous : constant T'Class := T'Class(X);
X'Old : T renames T(anonymous);
where the name X'Old denotes
the object renaming.
Otherwise
X'Old : constant S := X;
where S is the nominal
subtype of X. This includes the case where the type of S is an
anonymous array type or a universal type.
The nominal subtype of X'Old is as implied
by the above definitions. The expected type of the prefix of an Old attribute
is that of the attribute. Similarly, if an Old attribute shall resolve
to be of some type, then the prefix of the attribute shall resolve to
be of that type.
Reference to this attribute is only allowed
within a postcondition expression. The
prefix
of an Old
attribute_reference
shall not contain a Result
attribute_reference,
nor an Old
attribute_reference,
nor a use of an entity declared within the postcondition expression but
not within
prefix
itself (for example, the loop parameter of an enclosing
quantified_expression).
The
prefix
of an Old
attribute_reference
that is potentially unevaluated shall statically denote an entity.
For a
prefix
F that denotes a function declaration, the following attribute is defined:
F'Result
Within a postcondition expression
for function F, denotes the result object of the function. The type of
this attribute is that of the function result except within a Post'Class
postcondition expression for a function with a controlling result or
with a controlling access result. For a controlling result, the type
of the attribute is
T'Class, where
T is the function result
type. For a controlling access result, the type of the attribute is an
anonymous access type whose designated type is
T'Class, where
T is the designated type of the function result type.
Use of this attribute is allowed only within
a postcondition expression for F.
Dynamic Semantics
Upon a call of the
subprogram or entry, after evaluating any actual parameters, precondition
checks are performed as follows:
The specific precondition check begins with the
evaluation of the specific precondition expression that applies to the
subprogram or entry, if it is enabled; if the expression evaluates to
False, Assertions.Assertion_Error is raised; if the expression is not
enabled, the check succeeds.
The class-wide precondition check begins with the
evaluation of any enabled class-wide precondition expressions that apply
to the subprogram or entry. If and only if all the class-wide precondition
expressions evaluate to False, Assertions.Assertion_Error is raised.
The precondition checks are performed in an arbitrary
order, and if any of the class-wide precondition expressions evaluate
to True, it is not specified whether the other class-wide precondition
expressions are evaluated. The precondition checks and any check for
elaboration of the subprogram body are performed in an arbitrary order.
It is not specified whether in a call on a protected operation, the checks
are performed before or after starting the protected action. For an entry
call, the checks are performed prior to checking whether the entry is
open.
Upon successful return from a call of the subprogram
or entry, prior to copying back any by-copy
in out or
out
parameters, the postcondition check is performed. This consists of the
evaluation of any enabled specific and class-wide postcondition expressions
that apply to the subprogram or entry. If any of the postcondition expressions
evaluate to False, then Assertions.Assertion_Error is raised. The postcondition
expressions are evaluated in an arbitrary order, and if any postcondition
expression evaluates to False, it is not specified whether any other
postcondition expressions are evaluated. The postcondition check, and
any constraint or predicate checks associated with
in out or
out
parameters are performed in an arbitrary order.
For a call to a task entry, the postcondition check
is performed before the end of the rendezvous; for a call to a protected
operation, the postcondition check is performed before the end of the
protected action of the call. The postcondition check for any call is
performed before the finalization of any implicitly-declared constants
associated (as described above) with Old
attribute_references
but after the finalization of any other entities whose accessibility
level is that of the execution of the callable construct.
If a precondition or postcondition check fails, the
exception is raised at the point of the call; the exception cannot be
handled inside the called subprogram or entry. Similarly, any exception
raised by the evaluation of a precondition or postcondition expression
is raised at the point of call.
For any call to a subprogram or entry S (including
dispatching calls), the checks that are performed to verify specific
precondition expressions and specific and class-wide postcondition expressions
are determined by those for the subprogram or entry actually invoked.
Note that the class-wide postcondition expressions verified by the postcondition
check that is part of a call on a primitive subprogram of type T
includes all class-wide postcondition expressions originating in any
progenitor of T, even if the primitive subprogram called is inherited
from a type T1 and some of the postcondition expressions do not
apply to the corresponding primitive subprogram of T1. Any operations
within a class-wide postcondition expression that were resolved as primitive
operations of the (notional) formal derived type NT, are in the
evaluation of the postcondition bound to the corresponding operations
of the type identified by the controlling tag of the call on S.
This applies to both dispatching and non-dispatching calls on S.
The class-wide precondition check for a call to a
subprogram or entry S consists solely of checking the class-wide
precondition expressions that apply to the denoted callable entity (not
necessarily to the one that is invoked). Any operations within such an
expression that were resolved as primitive operations of the (notional)
formal derived type NT are in the evaluation of the precondition
bound to the corresponding operations of the type identified by the controlling
tag of the call on S. This applies to both dispatching and non-dispatching
calls on S.
For a call via an access-to-subprogram value, all
precondition and postcondition checks performed are determined by the
subprogram or entry denoted by the prefix of the Access attribute reference
that produced the value.
5 A precondition is checked just before
the call. If another task can change any value that the precondition
expression depends on, the precondition need not hold within the subprogram
or entry body.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe