11.5 Suppressing Checks
1/2
{
AI95-00224-01}
Checking pragmas{Checking
pragmas} give instructions to an implementation
on handling language-defined checks. A
pragma
Suppress gives permission to an implementation to omit certain language-defined
checks
, while a pragma
Unsuppress revokes the permission to omit checks..
2
{language-defined
check} {check
(language-defined)} {run-time
check: See language-defined check} {run-time
error} {error
(run-time)} A
language-defined check
(or simply, a “check”) is one of the situations defined by
this International Standard that requires a check to be made at run time
to determine whether some condition is true.
{failure
(of a language-defined check)} A check
fails when the condition being checked is false, causing an exception
to be raised.
2.a
Discussion: All such checks are defined
under “Dynamic Semantics” in clauses and subclauses throughout
the standard.
Syntax
3/2
{
AI95-00224-01}
The form
s of checking pragmas are of a pragma Suppress is as follows:
4/2
4.1/2
5/2
{
AI95-00224-01}
{configuration pragma (Suppress)
[partial]} {pragma,
configuration (Suppress) [partial]} {configuration
pragma (Unsuppress) [partial]} {pragma,
configuration (Unsuppress) [partial]} A
checking pragma pragma
Suppress is allowed only immediately within a
declarative_part,
immediately within a
package_specification,
or as a configuration pragma.
Legality Rules
6/2
{
AI95-00224-01}
The
identifier shall be the name of a check.
The name (if present)
shall statically denote some entity.
7/2
This paragraph was
deleted.{
AI95-00224-01}
For a pragma Suppress
that is immediately within a package_specification
and includes a name, the name
shall denote an entity (or several overloaded subprograms) declared immediately
within the package_specification.
Static Semantics
7.1/2
{
AI95-00224-01}
A checking pragma applies to the named check in
a specific region, and applies to all entities in that region. A checking
pragma given in a declarative_part or immediately
within a package_specification applies from
the place of the pragma to the end of the
innermost enclosing declarative region. The region for a checking pragma
given as a configuration pragma is the declarative region for the entire
compilation unit (or units) to which it applies.
7.2/2
{
AI95-00224-01}
If a checking pragma applies to a generic instantiation,
then the checking pragma also applies to the instance. If a checking
pragma applies to a call to a subprogram that has a pragma
Inline applied to it, then the checking pragma also applies to the inlined
subprogram body.
8/2
{
AI95-00224-01}
A
pragma Suppress gives permission to an implementation
to omit the named check
(or every check in the
case of All_Checks) for any entities to which it applies. from
the place of the pragma to the end of the
innermost enclosing declarative region, or, if the pragma
is given in a package_specification and includes
a name, to the end of the scope of the named
entity. If the pragma includes a name,
the permission applies only to checks performed on the named entity,
or, for a subtype, on objects and values of its type. Otherwise, the
permission applies to all entities. {suppressed
check} If permission has been given to
suppress a given check, the check is said to be
suppressed.
8.a
Ramification: A check is suppressed even
if the implementation chooses not to actually generate better code. {
Program_Error
(raised by failure of run-time check)}
This allows
the implementation to raise Program_Error, for example, if the erroneousness
is detected.
8.1/2
{
AI95-00224-01}
A pragma Unsuppress
revokes the permission to omit the named check (or every check in the
case of All_Checks) given by any pragma Suppress
that applies at the point of the pragma Unsuppress.
The permission is revoked for the region to which the pragma
Unsuppress applies. If there is no such permission at the point of a
pragma Unsuppress, then the pragma
has no effect. A later pragma Suppress can
renew the permission.
9
The following are the
language-defined checks:
10
- {Constraint_Error
(raised by failure of run-time check)} [The
following checks correspond to situations in which the exception Constraint_Error
is raised upon failure.]
11/2
[When evaluating a dereference (explicit or implicit), check that the
value of the name is not null. When
converting to a subtype that excludes null, check that the converted
value is not null. When passing an
actual parameter to a formal access parameter, check that the value of
the actual parameter is not null. When
evaluating a discriminant_association for
an access discriminant, check that the value of the discriminant is not
null. ]
12
{Discriminant_Check
[distributed]} Discriminant_Check
[Check that the discriminants of a composite value have the values imposed
by a discriminant constraint. Also, when accessing a record component,
check that it exists for the current discriminant values.]
13/2
[Check that the second operand is not zero for the operations /, rem rem
and mod mod.]
14
{Index_Check
[distributed]} Index_Check
[Check that the bounds of an array value are equal to the corresponding
bounds of an index constraint. Also, when accessing a component of an
array object, check for each dimension that the given index value belongs
to the range defined by the bounds of the array object. Also, when accessing
a slice of an array object, check that the given discrete range is compatible
with the range defined by the bounds of the array object.]
15
{Length_Check
[distributed]} Length_Check
[Check that two arrays have matching components, in the case of array
subtype conversions, and logical operators for arrays of boolean components.]
16
{Overflow_Check
[distributed]} Overflow_Check
[Check that a scalar value is within the base range of its type, in cases
where the implementation chooses to raise an exception instead of returning
the correct mathematical result.]
17
{Range_Check
[distributed]} Range_Check
[Check that a scalar value satisfies a range constraint. Also, for the
elaboration of a subtype_indication, check
that the constraint (if present) is compatible
with the subtype denoted by the subtype_mark.
Also, for an aggregate, check that an index
or discriminant value belongs to the corresponding subtype. Also, check
that when the result of an operation yields an array, the value of each
component belongs to the component subtype.]
18
{Tag_Check
[distributed]} Tag_Check
[Check that operand tags in a dispatching call are all equal. Check for
the correct tag on tagged type conversions, for an assignment_statement,
and when returning a tagged limited object from a function.]
19
- {Program_Error
(raised by failure of run-time check)} [The
following checks correspond to situations in which the exception Program_Error
is raised upon failure.]
19.1/2
{
AI95-00280}
{Accessibility_Check
[distributed]} Accessibility_Check
[Check the accessibility level of an entity or
view.]
19.2/2
{
AI95-00280}
{Allocation_Check
[distributed]} Allocation_Check
[For an allocator, check
that the master of any tasks to be created by the allocator
is not yet completed or some dependents have not yet terminated, and
that the finalization of the collection has not started.]
20
{Elaboration_Check
[distributed]} Elaboration_Check
[When a subprogram or protected entry is called, a task activation is
accomplished, or a generic instantiation is elaborated, check that the
body of the corresponding unit has already been elaborated.]
21/2
This
paragraph was deleted.{
AI95-00280}
{Accessibility_Check
[distributed]} Accessibility_Check
[Check the accessibility level of an entity or
view.]
22
- [The
following check corresponds to situations in which the exception Storage_Error
is raised upon failure.]
23
{Storage_Check
[distributed]} {Storage_Error
(raised by failure of run-time check)} Storage_Check
[Check that evaluation of an allocator does
not require more space than is available for a storage pool. Check that
the space available for a task or subprogram has not been exceeded.]
23.a
Reason: We considered splitting this
out into three categories: Pool_Check (for allocators),
Stack_Check (for stack usage), and Heap_Check (for implicit use of the
heap — use of the heap other than through an allocator).
Storage_Check would then represent the union of these three. However,
there seems to be no compelling reason to do this, given that it is not
feasible to split Storage_Error.
24
- [The
following check corresponds to all situations in which any predefined
exception is raised.]
25
{All_Checks
[distributed]} All_Checks
Represents the union of all checks; [suppressing All_Checks suppresses
all checks.]
25.a
Ramification: All_Checks includes both
language-defined and implementation-defined checks.
Erroneous Execution
26
{erroneous execution
(cause) [partial]} If a given check has
been suppressed, and the corresponding error situation occurs, the execution
of the program is erroneous.
Implementation Permissions
27/2
{
AI95-00224-01}
An implementation is allowed to place restrictions on
checking
pragmas, subject only to the requirement that pragma
Unsuppress shall allow any check names supported by pragma
Suppress Suppress pragmas.
An implementation is allowed to add additional check names, with implementation-defined
semantics.
{unspecified [partial]}
When Overflow_Check has been suppressed, an implementation
may also suppress an unspecified subset of the Range_Checks.
27.a/2
This paragraph
was deleted.Reason: {
AI95-00224-01}
The permission to restrict is given so the implementation
can give an error message when the requested suppression is nonsense,
such as suppressing a Range_Check on a task type. It would be verbose
and pointless to list all the cases of nonsensical language-defined checks
in the standard, and since the list of checks is open-ended, we can't
list the restrictions for implementation-defined checks anyway.
27.b
Implementation defined: Implementation-defined
check names.
27.c
Discussion: For Overflow_Check, the intention
is that the implementation will suppress any Range_Checks that are implemented
in the same manner as Overflow_Checks (unless they are free).
27.1/2
{
AI95-00224-01}
An implementation may support an additional parameter
on pragma Unsuppress similar to the one allowed
for pragma Suppress (see J.10).
The meaning of such a parameter is implementation-defined.
27.c.1/2
Implementation defined:
Existence and meaning of second parameter
of pragma Unsuppress.
Implementation Advice
28
The implementation should minimize the code executed
for checks that have been suppressed.
28.a.1/2
Implementation Advice:
Code executed for checks that have been
suppressed should be minimized.
28.a
Implementation Note: However, if a given
check comes for free (for example, the hardware automatically performs
the check in parallel with doing useful work) or nearly free (for example,
the check is a tiny portion of an expensive run-time system call), the
implementation should not bother to suppress the check. Similarly, if
the implementation detects the failure at compile time and provides a
warning message, there is no need to actually suppress the check.
29
3
{optimization}
{efficiency}
There is no guarantee that a suppressed check is
actually removed; hence a
pragma Suppress
should be used only for efficiency reasons.
29.1/2
4 {
AI95-00224-01}
It is possible to give both a pragma
Suppress and Unsuppress for the same check immediately within the same
declarative_part. In that case, the last pragma
given determines whether or not the check is suppressed. Similarly, it
is possible to resuppress a check which has been unsuppressed by giving
a pragma Suppress in an inner declarative
region.
Examples
30/2
{
AI95-00224-01}
Examples of suppressing and unsuppressing checks:
31/2
{
AI95-00224-01}
pragma Suppress(
Index_Check);
pragma Unsuppress(Overflow_Check); Range_Check);
pragma Suppress(Index_Check, On => Table);
Extensions to Ada 83
31.a
{
extensions to Ada 83}
A
pragma Suppress is allowed as a configuration
pragma. A
pragma Suppress without a
name
is allowed in a
package_specification.
31.b
Additional check names are added. We allow implementations
to define their own checks.
Wording Changes from Ada 83
31.c
We define the checks in a distributed manner.
Therefore, the long list of what checks apply to what is merely a NOTE.
31.d
We have removed the detailed rules about what
is allowed in a pragma Suppress, and allow
implementations to invent their own. The RM83 rules weren't quite right,
and such a change is necessary anyway in the presence of implementation-defined
checks.
31.e
We make it clear that the difference between
a Range_Check and an Overflow_Check is fuzzy. This was true in Ada 83,
given RM83-11.6, but it was not clear. We considered removing Overflow_Check
from the language or making it obsolescent, just as we did for Numeric_Error.
However, we kept it for upward compatibility, and because it may be useful
on machines where range checking costs more than overflow checking, but
overflow checking still costs something. Different compilers will suppress
different checks when asked to suppress Overflow_Check — the non-uniformity
in this case is not harmful, and removing it would have a serious impact
on optimizers.
31.f
Under Access_Check, dereferences cover the cases
of selected_component, indexed_component,
slice, and attribute
that are listed in RM83, as well as the new explicit_dereference,
which was included in selected_component in
RM83.
Extensions to Ada 95
31.g/2
31.h/2
{
AI95-00280-01}
Allocation_Check was added to support suppressing
the new check on allocators (see 4.8).
Wording Changes from Ada 95
31.i/2
{
8652/0036}
{
AI95-00176-01}
{
AI95-00224-01}
The description of Access_Check was corrected by
the Corrigendum to include the discriminant case. This change was then
replaced by the more general notion of checking conversions to subtypes
that exclude null in Ada 2005.
31.j/2
{
AI95-00224-01}
The On parameter of pragma Suppress was moved to
Annex J. This feature's effect is inherently non-portable, depending
on the implementation's model of computation. Compiler surveys demonstrated
this, showing that implementations vary widely in the interpretation
of these parameters, even on the same target. While this is relatively
harmless for Suppress (which is never required to do anything), it would
be a significant problem for Unsuppress (we want the checks to be made
for all implementations). By moving it, we avoid needing to define the
meaning of Unsuppress with an On parameter.
31.k/2
{
AI95-00280-01}
The order of the Program_Error checks was corrected
to be alphabetical.