Copyright Digital Equipment Corp. All rights reserved.

/CHECK

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