/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).