/CHECK[=ALL|NONE|([NO]UNINITIALIZED_VARIABLES, [NO]BOUNDS,
[NO]POINTER_SIZE[=(option,...)], [NO]FP_MODE, [NO]ARG_INFO)]
/NOCHECK (D)
This qualifier is for use only as a debugging aid. It should not be used
to build production code without carefully assessing its performance impact
on the application in question for each platform on which the application
runs. For example, the I64-only FP_MODE check can add significant overhead
to every function in the compilation, even if the application uses little
or no floating point.
/CHECK=NONE is equivalent to /NOCHECK.
/CHECK=ALL is equivalent to
/CHECK=(UNINITIALIZED_VARIABLES,BOUNDS,POINTER_SIZE=ALL,FP_MODE,ARG_INFO).
/CHECK=UNINITIALIZED_VARIABLES initializes all automatic variables to the
value 0x7ff580057ff58005. This value is a double signaling NaN and, if
used as a floating-point value in certain double operations, causes a
floating-point trap if traps are enabled. Traps are not enabled if the
program is compiled /FLOAT=IEEE and the /IEEE value is something other than
FAST.
On I64 systems:
o Traps are not caused when values are converted to an integer type.
o The float type does not trap.
/CHECK=BOUNDS enables run-time checking of array bounds. Array-bounds
processing is performed in the following way:
o Checks are done only when accessing an array.
o Checks are not done when accessing a pointer, even if that access is
done using the subscript operator. This means that checks are not done
on arrays declared as formal parameters because they are considered
pointers in the C language. If a formal parameter is a multi-dimension
array, all bounds except the first are checked.
o If an array is accessed using the subscript operator (as either the
left or right operand), and the subscript operator is not the operand
of an address-of operator, the check is for the index to be between 0
and the number of array elements minus one, inclusive.
o If an array is accessed using the subscript operator (as either the
left or right operand), and the subscript operator is the operand of
the address-of operator, the check is for the index to be between 0 and
the number of elements in the array, inclusive.
The reason for treating the address-of case differently is that it is
common programming practice to have a loop such as:
int a[10];
int *b;
for (b = a ; b < &a[10] ; b++) { .... }
In this case, access to &a[10] is allowed even though it is outside the
range of the array.
o If the array is being accessed using pointer addition, the check is for
the value being added to be between 0 and the number of elements in the
array, inclusive.
o If the array is being accessed using pointer subtraction (that is, the
subraction of an integer value from a pointer, not the subtraction of
one pointer from another), the check is for the value being subtracted
to be between the negation of the number of elements in the array and
0, inclusive.
o In the previous three cases, an optional compile-time message (ident
SUBSCRBOUNDS2) can be enabled to detect the case where an array has
been accessed using either a constant subscript or constant pointer
arithmetic, and the element accessed is exactly one past the end of the
array.
o Bounds checking is not done for arrays declared with one element.
(Because ANSI C does not allow arrays without dimensions inside
structs, it is common practice to declare such arrays with a bounds
specifier of 1.)
In this case, an optional compile-time message (ident SUBSCRBOUNDS1)
can be enabled to detect the case where an array declared with a single
element is accessed using either a constant subscript or constant
pointer arithmetic, and the element accessed is not part of the array.
o VSI C emits run-time checks for arrays indexed by constants, even
though the compiler can and does detect this situation at compile-time.
An exeption is that no run-time check is made if the compiler can
determine that the access is valid.
o If a multi-dimension array is accessed, the compiler performs checks on
each of the subscript expressions, making sure each is within the
corresponding bound. So for the following code, the compiler checks
that both x and y are between 0 and 9. It does not check that 10 * x +
y is between 0 and 99:
int a[10][10];
int x,y,z;
x = a[x][y];
/CHECK=POINTER_SIZE directs the compiler to check 32-bit pointer values to
make sure they will fit in a 32-bit pointer. If such a value cannot be
represented by a 32-bit pointer, the run-time code signals a range error
(SS$_RANGEERR).
Use one or more of the following POINTER_SIZE option keywords to determine
the pointer-size checks you want made:
[NO]ASSIGNMENT Check whenever a 64-bit pointer is assigned to a
32-bit pointer (including use as an actual argument).
[NO]CAST Check whenever a 64-bit pointer is cast to a 32-bit
pointer.
[NO]INTEGER_CAST Check whenever a long pointer is cast to a 32-bit
integer.
[NO]PARAMETER Check all formal parameters at function startup to
make sure that all formal parameters declared to be
32-bit pointers are 32-bit values.
ALL Do all checks.
NONE Do no checks.
/CHECK=FP_MODE generates code in the prologue of every function defined in
the compilation to compare the current values of certain fields in the
processor's floating-point status register (FPSR) with the values expected
in those fields based on the command-line qualifiers with which the
function was compiled.
The values checked are the rounding mode and the trap-enable bits:
o If the rounding mode is not consistent with the value of the
/ROUNDING_MODE qualifier specified at compile time, an informational
message SYSTEM-I-FPMODERC is issued at runtime, citing the current mode
and the compile-time specified mode (Note that /ROUNDING_MODE=DYNAMIC
is treated the same as /ROUNDING_MODE=NEAREST for this purpose).
o If the trap-enable flags are not consistent with the setting of the
/IEEE qualifier (for /FLOAT=IEEE_FLOAT compilations) or with the
setting used to implement VAX floating types (for /FLOAT=G_FLOAT or
/FLOAT=D_FLOAT compilations), an informational message
SYSTEM-I-FPMODECTL is issued at run time, citing the current
trap-enable flags as well as the trap-enable flags expected by the
compilation. To identify the point of failure, you need to rerun the
program under DEBUG and issue "SET BREAK/EXCEPTION".
Note that the checking code generated for /CHECK=FP_MODE includes a
standard call to OTS$CHECK_FP_MODE within the prologue of each function,
and OTS$CHECK_FP_MODE itself assumes the standard calling conventions
(described in the OpenVMS Calling Standard). Because of this, it is not
possible to use this checking option when compiling function definitions
that have a nonstandard linkage (see #pragma linkage and #pragma
use_linkage) specifying conventional scratch registers with the PRESERVED
or NOTUSED attribute. Doing so will cause the compiler to issue the
"REGCONFLICT" E-level diagnostic at the opening brace of such function
definitions. To compile such functions successfully, the FP_MODE keyword
must be removed from the list of /CHECK= keywords.
/CHECK=ARG_INFO generates code to verify the input parameters to functions
defined in the compiled source. This code checks for datatype consistency
between the caller and its called function.
When the runtime does parameter-type checking, it categorizes the actual
type information into one of six possibilities:
VAX single-precision floating-point
VAX double-precision floating-point - D_floating
VAX double-precision floating-point - G_floating
IEEE single-precision floating-point
IEEE double-precision floating-point
none-of-the-above "bucket"
It is only a mismatch of these types that is considered. So while the
run-time code will catch a case of a VAX D_floating number passed to a
function that expects a VAX single-precision number, it will not detect the
case of an int passed to a function that expects a long double type
(because both int and long double are viewed as the same type; that is,
they both fall into the none-of-the-above bucket).
When a mismatch is found, a %SYSTEM-I-ARGTYP1 is output at runtime for each
argument slot whose type does not match the expected type.
This checking applies only to arguments passed in the first eight argument
slots, and will not check that the number of arguments passed matches the
number expected.
If the /CHECK qualifier is omitted, the default is /NOCHECK, which equates
to /CHECK=(NOUNINITIALIZED_VARIABLE, NOBOUNDS, NOPOINTER_SIZE, NOFP_MODE,
NOARGINFO).
If you specify /CHECK, the default is /CHECK=(UNINITIALIZED_VARIABLES,
BOUNDS, POINTER_SIZE=(ASSIGNMENT,PARAMETER), FP_MODE, ARG_INFO).