DEC C
User's Guide for OpenVMS Systems


Previous Contents Index

The following sections describe these options in greater detail.

[NO]ACCURACY_SENSITIVE (ALPHA ONLY)

The default is ACCURACY_SENSITIVE.

If you specify NOACCURACY_SENSITIVE, the compiler is free to reorder floating-point operations based on algebraic identities (inverses, associativity, and distribution). This allows the compiler to move divide operations outside of loops, which improves performance.

The default, ACCURACY_SENSITIVE, directs the compiler to use only certain scalar rules for calculations. This setting can prevent some optimizations.

If you use the /ASSUME=NOACCURACY_SENSITIVE qualifier, DEC C might reorder code (based on algebraic identities) to improve performance. The results can be different from the default (/ASSUME=ACCURACY_SENSITIVE) because of how the intermediate results are rounded. However, the NOACCURACY_SENSITIVE results are not categorically less accurate than those gained by the default.

[NO]ALIGNED_OBJECTS (ALPHA ONLY)

The default is /ASSUME=ALIGNED_OBJECTS.

On OpenVMS Alpha systems, dereferencing a pointer to a longword- or quadword-aligned object is more efficient than dereferencing a pointer to a byte- or word-aligned object. Therefore, the compiler can generate more optimized code if it makes the assumption that a pointer object of an aligned pointer type does point to an aligned object.

Since the compiler determines the alignment of the dereferenced object from the type of the pointer, and the program is allowed to compute a pointer that references an unaligned object (even though the pointer type indicates that it references an aligned object), the compiler must assume that the dereferenced object's alignment matches or exceeds the alignment indicated by the pointer type. Specifying /ASSUME=ALIGNED_OBJECTS (the default) allows the compiler to make such an assumption. With this assumption made, the compiler can generate more efficient code for pointer dereferences of aligned pointer types.

To prevent the compiler from assuming the pointer type's alignment for objects that it points to, use the /ASSUME=NOALIGNED_OBJECTS qualifier.

Before deciding whether to specify /ASSUME=NOALIGNED_OBJECTS or /ASSUME=ALIGNED_OBJECTS, you need to know what programming practices will affect your decision.

The compiler assumes that pointers point to objects that are aligned at least as much as the alignment of the pointer type. For example:

If your module breaks this rule, your program will suffer alignment faults at runtime that can seriously degrade performance. If you can identify the places in your code where the rule is broken, use the __unaligned type qualifier. Otherwise, the /ASSUME=NOALIGNED_OBJECTS qualifier effectively treats all dereferences as if they were unaligned.

DEC C for OpenVMS Alpha Systems aligns all nonmember declarations on natural boundaries, so by default all objects do comply with the previous assumption. Also, the standard library routine malloc on OpenVMS systems returns quadword-aligned heap memory.

A program can violate the previous assumption in any of the following ways:

The following example explicitly specifies a lesser alignment for an object than the pointer type's alignment, which occurs when the address of an unaligned int member of a struct with #pragma nomember_alignment is used in a pointer dereference:


#pragma nomember_alignment 
struct foo { 
    char C; 
    int i; /* i is unaligned because of char C */ 
}; 
 
struct foo st; 
int        *i_p; 
 
i_p = &st.i; 
 
... *i_p ...    /* An expression containing a dereferenced i_p */ 

This example casts a pointer to a pointer type with stricter alignment:


int        *i_p; 
char       *c_p; 
 
....... 
....... 
 
i_p = (int *)c_p; 
 
... *i_p ...    /* An expression containing a dereferenced i_p */ 

The following example encloses a member-aligned object inside a nonmember-aligned object:


#pragma member_alignment 
struct inside { 
    int i;  /* this type asserts that its objects have at least 
               longword alignment (int is a longword)... */ 
}; 
 
#pragma nomember_alignment 
struct outside { 
    char C; 
    struct inside s; /* ...but foo_ptr -> s is only byte-aligned! */ 
} *foo_ptr; 

The expression foo_ptr -> s has a type whose alignment is explicitly specified to be longword (because longword is the strictest alignment of the structure's members), but the expression type is only guaranteed to be byte-aligned.

Also note that just as the pointer type information can direct the compiler to generate the appropriate code to dereference the pointer (code that does not cause alignment faults), it can also direct the compiler to generate even better code if it indicates that the object is at least longword-aligned.

[NO]CLEAN_PARAMETERS (ALPHA ONLY)

The default is /ASSUME=CLEAN_PARAMETERS.

The Alpha Calling Standard requires integers less than 64 bits long that are passed by value to have their upper bits either zeroed or sign-extended to make full 64-bit values. These are referred to as clean parameters. Some old code does not follow this convention. This can cause problems if the called program assumes that the caller followed the Calling Standard by passing only clean parameters.

Specifying /ASSUME=NOCLEAN_PARAMETERS allows a program to be called by old code that might pass unclean integer parameters. It directs the compiler to generate runtime code to clean the short integers so they comply with the Calling Standard.

[NO]EXACT_CDD_OFFSETS

The default is /ASSUME=NOEXACT_CDD_OFFSETS.

If /ASSUME=EXACT_CDD_OFFSETS is specified, the records input from the CDD are given the exact alignment (relative to the start of the record) specified by the CDD definition. This alignment is independent of the current compiler member-alignment setting.

If /ASSUME=NOEXACT_CDD_OFFSETS is specified, the compiler may modify the offsets specified in a CDD record according to the current member-alignment setting.

[NO]HEADER_TYPE_DEFAULT

The default is /ASSUME=HEADER_TYPE_DEFAULT.

In previous versions of DEC C, the #include directive always supplied a default file type of .h for C compilations. Similarly, DEC C++ supplied a default file type of .hxx for C++ compilations.

However, the ANSI C++ standard requires that, for example, #include <iostream> be distinguishable from #include <iostream.hxx> . This is not possible with the header file-type default mechanism in effect.

You can disable the type default mechanism for either DEC C or DEC C++ by specifying /ASSUME=NOHEADER_TYPE_DEFAULT.

With /ASSUME=NOHEADER_TYPE_DEFAULT specified, an #include directive written with the standard syntax for header name (enclosed in quotes or angle brackets) will use the filename as specified, without supplying a default file type. More precisely stated, the default file type will be empty (just ".").

For example, a directory might contain three files named IOSTREAM., IOSTREAM.HXX, and IOSTREAM.H. By default, the C++ compiler processes #include <iostream> such that the file IOSTREAM.HXX is found, while the C compiler would find IOSTREAM.H.

However, if /ASSUME=NOHEADER_TYPE_DEFAULT is specified, the same directive causes the file IOSTREAM. to be found by both compilers, and the only way to include the file named IOSTREAM.HXX or IOSTREAM.H is to specify the .hxx or .h file type explicitly in the #include directive. Be aware that while the OpenVMS operating system treats filenames as case-insensitive and normally displays them in uppercase, filenames in #include directives should use lowercase for best portability. This is more in keeping with other C and C++ implementations.

[NO]MATH_ERRNO (ALPHA ONLY)

The default is /ASSUME=MATH_ERRNO, which does not allow intrinsic code for such math functions to be generated, even if /OPTIMIZE=INTRINSICS is in effect. Their prototypes and call formats, however, are still checked.

[NO]POINTERS_TO_GLOBALS (ALPHA ONLY)

The default is /ASSUME=POINTER_TO_GLOBALS, which directs the compiler to assume that global variables have had their addresses taken in separately compiled modules and that, in general, any pointer dereference could be accessing the same memory as any global variable. This is often a significant barrier to optimization.

The /ANSI_ALIAS command-line qualifier allows some resolution based on data type, but /ASSUME=NOPOINTER_TO_GLOBALS provides significant additional resolution and improved optimization in many cases.

/ASSUME=NOPOINTER_TO_GLOBALS tells the compiler that any global variable accessed through a pointer in the compilation must have had its address taken within that compilation. The compiler can see any code that takes the address of an extern variable. If it does not see the address of the variable being taken, the compiler can assume that no pointer points to the variable.

Consider the following code sequence:


extern int x; 
... 
int *p; 
... 
*p = 3; 

Under /ASSUME=NOPOINTERS_TO_GLOBALS, the compiler can assume that x is not changed by the assignment through p when generating code. This can lead to faster code.

In combination with the /PLUS_LIST_OPTIMIZE qualifier, several source modules can be treated as a single compilation for the purpose of this analysis. Because run-time libraries such as the DEC C RTL do not take the addresses of global variables defined in user programs, source modules can often be combined into a single compilation that allows /ASSUME=NOPOINTER_TO_GLOBALS to be used effectively.

Be aware that /ASSUME=NOPOINTERS_TO_GLOBALS does not tell the compiler that the compilation never uses pointers to access global variables (which is seldom true of real C programs).

[NO]WHOLE_PROGRAM

The default is /NOWHOLE_PROGRAM.

The optimizations enabled by /ASSUME=WHOLE_PROGRAM include all those enabled by /ASSUME=NOPOINTER_TO_GLOBALS, and possibly additional optimizations as well.

[NO]WRITABLE_STRING_LITERALS

For /STANDARD=VAXC or /STANDARD=COMMON, the default is /ASSUME=WRITABLE_STRING_LITERALS.

For all other compiler modes, the default is /ASSUME=NOWRITABLE_STRING_LITERALS.

/[NO]CHECK[=([NO]UNINITIALIZED_VARIABLES, [NO]POINTER_SIZE[=(option,...)])] (ALPHA ONLY)

This qualifier is for use as a debugging aid.

Use /CHECK=UNINITIALIZED_VARIABLES to initialize all automatic variables to the value 0xfffa5a5afffa5a5a. This value is a floating NaN and, if used, causes a floating-point trap. If used as a pointer, this value is likely to cause an ACCVIO.

Use /CHECK=POINTER_SIZE to direct the compiler to generate code that checks 64-bit pointer values (used in certain contexts where 32-bit pointers are also present) 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).

To control the types of pointer-size checks you want made, use one or more of the POINTER_SIZE option keywords shown in Table 1-3.

Table 1-3 /CHECK =POINTER_SIZE Qualifier Options
Option Usage
[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.

Omitting this qualifier defaults to /NOCHECK, which equates to /CHECK=(NOUNINITIALIZED_VARIABLE,NOPOINTER_SIZE).

Specifying /CHECK=POINTER_SIZE defaults to /CHECK=POINTER_SIZE=(ASSIGNMENT,PARAMETER).

Specifying /CHECK defaults to /CHECK=(UNINITIALIZED_VARIABLES, POINTER_SIZE), which equates to /CHECK=(UNINITIALIZED_VARIABLES, POINTER_SIZE=(ASSIGNMENT,PARAMETER)).

For information about compiler features that affect pointer size, see the following:

The following contrived program contains a number of pointer assignments. The comment on each line indicates what /CHECK=POINTER_SIZE keyword to specify to enable checking for that line.


    #pragma required_pointer_size long 
    int *a; 
    char *b; 
    typedef char * l_char_ptr; 
 
    #pragma required_pointer_size short 
    char *c; 
    int *d; 
 
    foo(int * e)              /* Check e if PARAMETER is specified. */ 
    { 
        d = a;                /* Check a if ASSIGNMENT is specified. */ 
        c = (char *) a;       /* Check a if CAST is specified. */ 
        c = (char *) d;       /* No checking ever. */ 
        foo( a );             /* Check a if ASSIGNMENT is specified. */ 
        bar( a );             /* No checking ever - no prototype */ 
        b = (l_char_ptr) a;   /* No checking ever. */ 
        c = (l_char_ptr) a;   /* Check a if ASSIGNMENT is specified */ 
        b = (char *) a;       /* Check if CAST is specified. */ 
    } 

/[NO]COMMENTS=option

Governs whether or not comments appear in preprocess output files and, if they are to appear, whether they appear themselves or are replaced by a single space.

Table 1-4 shows the /COMMENTS qualifier options.

Table 1-4 /COMMENTS Qualifier Options
Option Usage
AS_IS Specifies that the comment appears in the output file.
SPACE Specifies that a single space replaces the comment in the output file.

/NOCOMMENTS specifies that nothing replaces the comment in the output file. This can result in inadvertent token pasting.

The DEC C preprocessor might replace a comment at the end of a line or on a line by itself with nothing, even if /COMMENTS=SPACE is specified. Doing so does not change the meaning of the program.

The default is /COMMENTS=SPACE for the ANSI89, RELAXED_ANSI89, and MIA modes of the compiler. The default is /NOCOMMENTS for all other compiler modes.

Specifying /COMMENTS on the command line defaults to /COMMENTS=AS_IS.

/[NO]CROSS_REFERENCE

Specifies whether the compiler generates cross-references for variable names.

If you specify /CROSS_REFERENCE, the compiler lists, for each variable referenced in the procedure, the line numbers of the lines on which the variable is referenced.

This qualifier has no effect unless you also specify /LIST and either /SHOW=SYMBOLS or /SHOW=BRIEF. The default is /NOCROSS_REFERENCE.

/[NO]DEBUG[=(option[,...])]

Includes information in the object module for use by the OpenVMS Debugger.

The default on Alpha systems is /DEBUG=(TRACEBACK,NOSYMBOLS).

The default on VAX systems is /DEBUG=(TRACEBACK,NOINLINE, NOSYMBOLS).

Table 1-5 describes the debugger options.

Table 1-5 Debugger Compilation Options
Option Usage
ALL Includes symbol table records and traceback records. This is equivalent to /DEBUG=INLINE.
INLINE (VAX ONLY) Generates debug information to cause a STEP command to STEP/INTO an inlined function call.
NOINLINE (VAX ONLY) Generates debug information to cause a STEP command to STEP/OVER an inlined function call.
NONE Does not include any debugging information. This is equivalent to /NODEBUG.
NOTRACEBACK Does not include traceback records. This option is used to exclude all extraneous information from thoroughly debugged program modules. This option is equivalent to /NODEBUG.
NOSYMBOLS Includes only traceback records. This is the default if the /DEBUG qualifier is not present on the command line.
SYMBOLS Includes symbol table records, but not the traceback records.
TRACEBACK Includes only traceback records. This is the default if the /DEBUG qualifier is not present on the command line.

/DECC

Invokes the DEC C compiler.

On OpenVMS VAX systems, the CC command is used to invoke either the VAX C or DEC C compiler. If your system has a VAX C compiler already installed on it, the DEC C installation procedure provides the option of specifying which compiler will be invoked by default when just the CC command is used. To invoke the compiler that is not the default, use the CC command with the appropriate qualifier: CC/DECC for the DEC C compiler, or CC/VAXC for the VAX C compiler. If your system does not have a VAX C compiler installed on it, the CC command will invoke the DEC C compiler.

On OpenVMS Alpha systems, specifying /DECC is equivalent to not specifying it; this qualifier is supported to provide compatibility with DEC C on OpenVMS VAX systems.

/[NO]DEFINE=(identifier[=definition][,...])

/[NO]UNDEFINE=(identifier[,...])

Performs the same functions as the #define and #undef preprocessor directives. The /DEFINE qualifier defines a macro to be substituted for every occurrence of a given identifier in the compilation unit or units. The /UNDEFINE qualifier cancels a previous definition (but not subsequent ones). When both /DEFINE and /UNDEFINE are present in a compilation unit or on the CC command line, /DEFINE is evaluated before /UNDEFINE.

Since /DEFINE and /UNDEFINE are not part of the source file, they are not associated with a listing line number or source line number. Therefore, when an error occurs in a command-line definition, the message displayed at the terminal does not indicate a line number. In the listing file, these diagnostic messages are placed before the source listing in the order that they were encountered. When the expansion of a definition causes an error at a specific source line in the program, the diagnostics---both at the terminal and in the listing file---are associated with that source line.

A command line containing the /DEFINE and the /UNDEFINE qualifiers can be long. Continuation characters cannot appear within quotes or they will be included in the macro stream. The length of a CC command line cannot exceed the maximum length allowed by DCL.

The /NODEFINE and /NOUNDEFINE qualifiers are provided for compatibility with other DCL qualifiers. You can use these qualifiers to cancel /DEFINE or /UNDEFINE qualifiers that you have specified in a symbol that you use to compile DEC C programs.

The defaults are /NODEFINE and /NOUNDEFINE.

Usage and Examples

Since the CC command line must be compatible with DCL, the syntax of the /DEFINE and /UNDEFINE qualifiers differs from the syntax of the #define and #undef preprocessor directives in the following way:

You can pass an equal sign to the compiler in any of the following ways:


$ CC/DEFINE=(EQU==,"equ =","equal==")

In the first definition, the first equal sign is removed by DCL as the delimiter; the second equal sign is passed to the compiler. In the second example, the space is recognized as a delimiter because the definition is inside quotes; therefore, only one equal sign is required. In the third definition, the first equal sign is recognized as the delimiter and is removed; the second equal sign is passed to the compiler.

You can pass quotation marks in any of the following ways:


$ CC/DEFINE=(QUOTES="""","funct(b)=printf(")")

In both examples, DCL removes the first and last quotation marks before passing the definition to the compiler.

Here is a simple use of the /UNDEFINE qualifier to cancel a previous definition of TRUE:


$ CC/UNDEFINE=TRUE

The /UNDEFINE qualifier is useful for undefining the predefined DEC C preprocessor constants. For example, if you use a preprocessor system identification macro (such as __vaxc , __vaxc , __decc , or __vms ) to conditionally compile segments of DEC C specific code, you can undefine that constant to see how the portable sections of your program execute. Consider the following program:


main() 
{ 
#if <double_uscore>DECC 
printf("I'm being compiled with DEC C on an OpenVMS system."); 
#else 
printf("I'm being compiled on some other compiler."); 
#endif 
} 


Previous Next Contents Index