Next: Stack Overflow Checking, Previous: Style Checking, Up: Switches for gcc
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. The following 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_Error
as 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 suppress
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
variable 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
to X1
, X2
, 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
to X1
will result in wrap around to the largest negative number.
The conversions of F
will result in some Integer
value
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
semantics).
For floating-point, GNAT has the Machine_Overflows
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 gnatmake or
gcc command.
The setting of these switches only controls the default setting of the
checks. You may modify them using either Suppress
(to remove
checks) or Unsuppress
(to add back suppressed checks) pragmas in
the program source.