If you compile with the default options, GNAT will insert many run-time
checks into the compiled code, including code that performs range
checking against constraints, but not arithmetic overflow checking for
integer operations (including division by zero) or checks for access
before elaboration on subprogram calls. All other run-time checks, as
required by the Ada 95 Reference Manual, are generated by default.
gcc switches refine this default behavior:
pragma Suppress (all_checks) had been present in the source. Validity checks are also suppressed (in other words -gnatp also implies -gnatVn. Use this switch to improve the performance of the code at the expense of safety in the presence of invalid data or program bugs.
Constraint_Erroras required by standard Ada semantics). These overflow checks correspond to situations in which the true value of the result of an operation may be outside the base range of the result type. The following example shows the distinction:
X1 : Integer := Integer'Last; X2 : Integer range 1 .. 5 := 5; X3 : Integer := Integer'Last; X4 : Integer range 1 .. 5 := 5; F : Float := 2.0E+20; ... X1 := X1 + 1; X2 := X2 + 1; X3 := Integer (F); X4 := Integer (F);
Here the first addition results in a value that is outside the base range
of Integer, and hence requires an overflow check for detection of the
constraint error. Thus the first assignment to
X1 raises a
Constraint_Error exception only if -gnato is set.
The second increment operation results in a violation
of the explicit range constraint, and such range checks are always
performed (unless specifically suppressed with a pragma
or the use of -gnatp).
The two conversions of
F both result in values that are outside
the base range of type
Integer and thus will raise
Constraint_Error exceptions only if -gnato is used.
The fact that the result of the second conversion is assigned to
X4 with a restricted range is irrelevant, since the problem
is in the conversion, not the assignment.
Basically the rule is that in the default mode (-gnato not used), the generated code assures that all integer variables stay within their declared ranges, or within the base range if there is no declared range. This prevents any serious problems like indexes out of range for array operations.
What is not checked in default mode is an overflow that results in
an in-range, but incorrect value. In the above example, the assignments
X3 all give results that are within the
range of the target variable, but the result is wrong in the sense that
it is too large to be represented correctly. Typically the assignment
X1 will result in wrap around to the largest negative number.
The conversions of
F will result in some
and if that integer value is out of the
X4 range then the
subsequent assignment would generate an exception.
Note that the -gnato switch does not affect the code generated
for any floating-point operations; it applies only to integer
For floating-point, GNAT has the
attribute set to
False and the normal mode of operation is to
generate IEEE NaN and infinite values on overflow or invalid operations
(such as dividing 0.0 by 0.0).
The reason that we distinguish overflow checking from other kinds of range constraint checking is that a failure of an overflow check can generate an incorrect value, but cannot cause erroneous behavior. This is unlike the situation with a constraint check on an array subscript, where failure to perform the check can result in random memory description, or the range check on a case statement, where failure to perform the check can cause a wild jump.
Note again that -gnato is off by default, so overflow checking is
not performed in default mode. This means that out of the box, with the
default settings, GNAT does not do all the checks expected from the
language description in the Ada Reference Manual. If you want all constraint
checks to be performed, as described in this Manual, then you must
explicitly use the -gnato switch either on the
The setting of these switches only controls the default setting of the
checks. You may modify them using either
Suppress (to remove
Unsuppress (to add back suppressed checks) pragmas in
the program source.