3    Pragma Preprocessor Directives

The #pragma directive is a standard method for implementing features that vary from one compiler to the next. This chapter describes the implementation-specific pragmas that are supported on the C compiler:

Pragmas supported by all implementations of Compaq C are described in the Compaq C Language Reference Manual.

Some pragmas may perform macro expansion, by default. The Compaq C Language Reference Manual lists these pragmas. It also describes the use of double underscores as prefixes to pragma names and keywords to avoid macro expansion problems when porting a program that defines a macro with the same name as a pragma name or keyword.

You can force macro expansion for any pragma by adding a _m suffix to the pragma name. When the pragma name is followed by _m, the text that follows the pragma name is subject to macro replacement. See the example in Section 3.1.3.

3.1    The #pragma assert Directive

The #pragma  assert directive allows you to specify assertions about a program that the compiler can then use to generate more efficient code.

The #pragma  assert directive is never needed to make a program execute correctly; however, if a #pragma  assert is specified, the assertions must be valid or the program might behave incorrectly.

The #pragma  assert directive has the following formats:

#pragma  assert func_attrs(identifier-list)function-assertions

#pragma  assert global_status_variable(variable-list)

#pragma  assert non_zero(constant-expression) "string-literal"

3.1.1    #pragma assert func_attrs

Use this form of the #pragma assert directive to make assertions about a function's attributes.

This form of the pragma has the following format:

#pragma  assert func_attrs(identifier-list)function-assertions

identifier-list

A list of function identifiers about which the compiler can make assumptions based on the function-assertions. If you specify more than one identifier, separate them with commas.

function-assertions

A list of assertions that the compiler uses to make assumptions about the functions. Specify one or more of the following assertions, separating multiple assertions with white space:

noreturn

The compiler can assume that any call to the routine will never return.

nocalls_back

The compiler can assume that no routine in the source module will be called before control is returned from this function.

nostate

The compiler can assume that only the function's arguments determine the value that the function returns and any side-effects the function might have. If a function is marked as having both noeffects and nostate, the compiler can eliminate redundant calls to the function.

noeffects

The compiler can assume that any call to this function will have no effect except to set the return value of the function. If the compiler determines that the return value from a function call is never used, it can remove the call.

file_scope_vars(option)

The compiler can make assumptions about how a function will access variables that are declared at file scope (with either internal or external linkage). The option is one of the following keywords:

none

The function will not read or write to any file-scope variables except those whose type is volatile or those that are listed in a #pragma assert global_status_variable.

noreads

The function will not read any file-scope variables except those whose type is volatile or those that are listed in a #pragma assert global_status_variable.

nowrites

The function will not write to any file-scope variables except those whose type is volatile or those that are listed in a #pragma assert global_status_variable.

format (style, format-index, first-to-check-index)

The compiler can assume that this function takes printf or scanf style arguments which should be type-checked against a format string.

The format attribute allows you to identify your own functions which take format strings as arguments, so that the compiler can check the calls to these functions for errors. The compiler checks formats for the library functions printf, fprintf, sprintf, snprintf, scanf, fscanf, and sscanf whenever these functions are enabled as intrinsics (the default). You may use the format attribute to assert that the formats of these functions should be checked when they are not enabled as intrinsics.

style

Determines how the format string is interpreted, and should be either printf or scanf.

format-index

Specifies which argument is the format string argument (starting from 1).

first-to-check-index

The number of the first argument to check against the format string.

For functions where the arguments are not available to be checked (such as vprintf), specify the third parameter as zero. In this case the compiler only checks the format string for consistency. For example, the following declaration causes the compiler to check the arguments in calls to your_printf for consistency with the printf style format string argument your_format:

extern int
your_printf (void *your_object, const char *your_format, ...);
#pragma assert func_attrs(your_printf) format (printf, 2, 3)
 
 

The format string (your_format) is the second argument of the function your_printf, and the arguments to check start with the third argument, so the correct parameters for the format attribute are 2 and 3.

This form of the #pragma assert directive must appear at file scope.

The identifiers in the identifier-list must have declarations that are visible at the point of the #pragma assert directive.

A function can appear on more than one #pragma assert func_attrs directive as long as each directive specifies a different assertion about the function. For example, the following is valid:

#pragma assert func_attrs(a) nocalls_back 
#pragma assert func_attrs(a) file_scope_vars(noreads)

But the following is not valid:

#pragma assert func_attrs(a) file_scope_vars(noreads)
#pragma assert func_attrs(a) file_scope_vars(nowrites)

3.1.2    #pragma assert global_status_variable

Use this form of the #pragma assert directive to specify variables that are to be considered global status variables, which are exempt from any assertions that #pragma assert func_attrs file_scope_vars directives give to functions.

This form of the pragma has the following syntax:

#pragma  assert global_status_variable(variable-list)

The variable-list is a list of variables.

This form of the #pragma assert directive must appear at file scope.

The variables in the variable-list must have declarations that are visible at the point of the #pragma assert directive.

3.1.3    #pragma assert non_zero

This form of the #pragma assert directive has the following syntax:

#pragma  assert non_zero(constant-expression) "string-literal"

When the compiler encounters this directive, it evaluates the constant-expression. If the expression is zero, the compiler generates a message that contains both the specified string-literal and the compile-time constant. For example:

#pragma assert non_zero(sizeof(a) == 12) "a is the wrong size"
 

If the compiler determines that the sizeof a is not 12, it generates the following message:

cc: Warning: a.c, line 4: The assertion "sizeof(a)==12" was
    not true, a is the wrong size. (assertfail)

Unlike the assert options func_attrs and global_status_variable, #pragma assert non_zero can appear either inside or outside a function body. When it is used inside a function body, the #pragma can appear where a statement can appear, but it is not treated as a statement. When it is used outside a function body, the #pragma can appear where a declaration can appear, but it is not treated as a declaration.

Any variables in the constant-expression must have declarations that are visible at the point of the #pragma assert directive.

Because #pragma assert does not perform macro replacement on the pragma, it is often necessary to use the #pragma assert_m directive. Consider the following program that verifies both the size of a struct and the offset of one of its elements.

#include <stddef.h>
typedef struct {
   int a;
   int b;
} s;
#pragma assert non_zero(sizeof(s) == 8) "sizeof assert failed"
#pragma assert_m non_zero(offsetof(s,b) == 4) "offsetof assert failed"

Because offsetof is a macro, the second pragma must be assert_m so that offsetof will expand correctly.

3.2    The #pragma environment Directive

The #pragma  environment directive allows you to set, save, and restore the state of all context pragmas. The context pragmas are:

#pragma  extern_model
#pragma  extern_prefix
#pragma  member_alignment
#pragma  message
#pragma  pack
#pragma  pointer_size

A context pragma can save and restore previous states, usually before and after including a header file that might also use the same type of pragma.

The #pragma  environment directive protects include files from compilation contexts set by encompassing programs, and protects encompassing programs from contexts set in header files that they include.

This pragma has the following syntax:

#pragma  environment [ command_line  |  header_defaults  |  restore  |  save ]
        

command_line

Sets the states of all of the context pragmas set on the command line. You can use this pragma to protect header files from environment pragmas that take effect before the header file is included.

header_defaults

Sets the states of all of the context pragmas to their default values. This is equivalent to the situation in which a program with no command-line options and no pragmas is compiled, except that this pragma sets the pragma message state to #pragma  nostandard, as is appropriate for header files.

restore

Restores the current state of every context pragma.

save

Saves the current state of every context pragma.

Without requiring further changes to the source code, you can use #pragma environment to protect header files from things such as language enhancements that might introduce additional compilation contexts.

A header file can selectively inherit the state of a pragma from the including file and then use additional pragmas as needed to set the compilation to nondefault states. For example:

#ifdef _ _pragma_environment
#pragma _ _environment save  [1]
#pragma _ _environment header_defaults [2]
#pragma member_alignment restore [3]
#pragma member_alignment save [4]
#endif
.
.    /*contents of header file*/
.
#ifdef _ _pragma_environment
#pragma _ _environment restore
#endif

In this example:

  1. Saves the state of all context pragmas. [Return to example]

  2. Sets the default compilation environment. [Return to example]

  3. Pops the member alignment context from the #pragma member_alignment stack that was pushed by #pragma _ _environment save, restoring the member alignment context to its pre-existing state. [Return to example]

  4. Pushes the member alignment context back onto the stack so that the #pragma _ _environment  restore can pop the entry. [Return to example]

Therefore, the header file is protected from all pragmas, except for the member alignment context that the header file was meant to inherit.

3.3    The #pragma extern_model Directive

The #pragma extern_model directive controls how the compiler interprets data objects that have external linkage. With this pragma you can select one of the following global symbol models to be used for external (extern) objects:

relaxed_refdef

In this model, some declarations are references and some are definitions. Multiple uninitialized definitions for the same object are allowed, and the linker resolves them into one. However, a reference requires that at least one definition exists. C compilers on most UNIX systems use this model; it is the default model on Compaq C.

strict_refdef

In this model, some declarations are references and some are definitions. There must be exactly one definition in the program for any symbol that is referenced. This model is the only one guaranteed to strictly conform to all ANSI C implementations.

Note

Compaq C on OpenVMS platforms supports two other external models named common_block and globalvalue, but these are not supported on Tru64 UNIX.

After a global symbol model is selected with the extern_model pragma, all subsequent declarations of objects that have external storage class are treated according to the specified model until another extern_model pragma is specified.

For example, consider the following pragma:

#pragma extern_model strict_refdef "progsec3"

After this pragma is specified, the following file-level declarations are treated as declaring global symbols according to the strict_refdef model:

int x = 0; 
extern int y;

Regardless of the external model, the compiler uses ANSI C rules to determine if a declaration is a definition or a reference. An external definition is a file-level declaration that has no storage-class keyword, or that contains the extern storage-class keyword, and is also initialized. A reference is a declaration that uses the extern storage-class keyword and is not initialized. In the previous example, the declaration of x is a global definition and the declaration of y is a global reference.

A stack of the compiler's external model state is kept so that #pragma extern_model can be used transparently in header files and in small regions of program text. See Section 3.3.4 and Section 3.3.5 for more information.

The following sections describe the various forms of the #pragma extern_model directive.

3.3.1    Syntax

The #pragma extern_model directive has the following syntax:

#pragma  extern_model model_spec [attr[,attr]...]

model_spec

One of the following:

relaxed_refdef
strict_refdef "name"

where "name" is the name of the program section (psect) for any definitions.

[attr[,attr]...]

Optional psect attribute specifications. Choose only one from each of the following sets of attribute specifications:

shr|noshr

The psect can be shared in memory (shr) or cannot be shared in memory (noshr). The default is noshr.

wrt|nowrt

The psect contains data that can be modified (wrt) or data that cannot be modified (nowrt). The default is determined by the first variable placed in the psect. If the variable has the const type qualifier (or the readonly modifier), the psect is set to nowrt. Otherwise, it is set to wrt.

ovr|con

The psect is concatenated with other psects with the same name (con) or overlaid on the same memory locations (ovr). The default is con for strict_refdef, and over for relaxed_refdef.

4|octa|5|6|7|8|9|10|11|12|13|14|15|16|page

These denote numeric alignment values. The default alignment is octa. If a number is specified, the psect is given an alignment of two raised to the power indicated by that number.

The strict_refdef extern_model can also take the following psect attribute specification:

noreorder

Causes variables in the section to be allocated in the order they are defined. This attribute specification is off, by default.

In the following example, the initialized variables are to be aligned on a 64K-byte (2**16) boundary. The noreorder attribute specification means that the variables will be allocated in the order they are declared:

#pragma extern_model save 
#pragma extern_model strict_refdef "progsecA" 16,noreorder
int var1 = 5;
int var2 = 6;
#pragma extern_model restore 
 
 

In the following example, the (non-writable) variables are to be aligned on a data cache line boundary:

#pragma extern_model save 
#pragma extern_model strict_refdef "progsecB" 3,noreorder,nowrt
const long c_v1 = 1;
const long c_v2 = 2;
const long c_v3 = 2;
const long c_v4 = 2;
#pragma extern_model restore

Under the relaxed_refdef model, psect atttributes do not affect variables that are declared with tentative definitions. Consider the following code:

#pragma extern_model relaxed_refdef 5
int a;
int b=6;
#pragma extern_model strict_refdef 5
int c;
 
 

Variable a is given the default octaword (2**4 or 16-byte) alignment because it is a tentative definition. But b is given 32-byte (2**5) alignment because it is initialized. Although c is a tentative definition, it is 32-byte (2**5) aligned because it is under the strict_refdef model.

Note

The psect attributes are normally used by system programmers who need to perform declarations normally done in macro. Most of these attributes are not needed in normal C programs.

3.3.2    #pragma extern_model relaxed_refdef

This pragma sets the compiler's model of external data to the relaxed_refdef model, which is the one used on UNIX systems.

The #pragma extern_model relaxed_refdef directive has the following syntax:

#pragma  extern_model relaxed_refdef [attr[,attr]...]

3.3.3    #pragma extern_model strict_refdef

This pragma sets the compiler's model of external data to the strict_refdef model. Use this model for a program that is to be an ANSI C strictly conforming program.

The #pragma extern_model strict_refdef directive has the following syntax:

#pragma  extern_model strict_refdef "name" [attr[,attr]...]

The name in quotes, if specified, is the name of the psect for any definitions.

3.3.4    #pragma extern_model save

This pragma pushes the current external model of the compiler onto a stack. The stack records all information that is associated with the external model, including the shr/noshr state and any quoted psect name.

This pragma has the following syntax:

#pragma  extern_model save

The number of entries that are allowed in the #pragma extern_model stack is limited only by the amount of memory that is available to the compiler.

3.3.5    #pragma extern_model restore

This pragma pops the external model stack of the compiler. The external model is set to the state popped off the stack. The stack records all information that is associated with the external model, including the shr/noshr state and any quoted psect name.

This pragma has the following syntax:

#pragma  extern_model restore

On an attempt to pop an empty stack, a warning message is issued and the compiler's external model is not changed.

3.4    The #pragma extern_prefix Directive

The #pragma  extern_prefix directive controls the compiler's synthesis of external names, which the linker uses to resolve external name requests.

When you specify #pragma  extern_prefix with a string argument, the C compiler attaches the string to the beginning of all external names produced by the declarations that follow the pragma specification.

This pragma is useful for creating libraries where the facility code can be attached to the external names in the library.

This pragma has the following syntax:

#pragma  extern_prefix "string" [(id,...)]

#pragma  extern_prefix save

#pragma  extern_prefix restore

The quoted string is attached to external names in the declarations that follow the pragma specification.

You can also specify a prefix for specific external identifiers using the optional list [(id,...)].

You can use the save and restore keywords can be used to save the current pragma prefix string and to restore the previously saved pragma prefix string, respectively.

The default prefix for external identifiers, when none has been specified by a pragma, is the null string.

The recommended use is as follows:

#pragma extern_prefix save
#pragma extern_prefix " prefix-to-prepend-to-external-names "
...some declarations and definitions ...
#pragma extern_prefix restore

When an extern_prefix is in effect and you are using #include to include header files, but do not want the extern_prefix to apply to extern declarations in the header files, use the following code sequence:

#pragma extern_prefix save
#pragma extern_prefix ""
#include ...
#pragma extern_prefix restore

Otherwise, the prefix is attached to the beginning of external identifiers for definitions in the included files.

Notes

The following notes apply when specifying optional identifiers on #pragma extern_prefix:

3.5    The #pragma inline Directive

Function inlining is the inline expansion of function calls, replacing the function call with the function code itself. Inline expansion of functions reduces execution time by eliminating function-call overhead and allowing the compiler's general optimization methods to apply across the expanded code. Compared with the use of function-like macros, function inlining has the following advantages:

The following preprocessor directives control function inlining:

#pragma  inline (id, ...)

#pragma  noinline (id, ...)

Where id is a function identifier:

If a function is to be expanded inline, you must place the function definition in the same module as the function call (unless you also use the -ifo option, which allows inlining across modules). The definition can appear either before or after the function call.

The cc command options -O3, -O4, -inline  size, -inline  speed, or -inline  all cause the compiler to attempt to expand calls to functions named in neither a #pragma  inline nor a #pragma  noinline directive as inline code whenever appropriate, as determined by the following function characteristics:

For optimization level -O2, the C compiler inlines small static routines only.

The #pragma  inline directive causes inline expansion regardless of the size or number of times the specified functions are called.

3.6    The #pragma intrinsic and #pragma function Directives

Certain functions can be declared to be intrinsic. Intrinsic functions are functions for which the C compiler generates optimized code in certain situations, possibly avoiding a function call.

Table 3-1 shows the functions that can be declared to be intrinsic.

Table 3-1:  Intrinsic Functions

abs fabs labs
printf fprintf sprintf
strcpy strlen memcpy
memmove memset alloca
bcopy bzero  

To control whether a function is treated as an intrinsic, use one of the following directives (where func_name_list is a comma-separated list of function names optionally enclosed in parentheses):

#pragma  intrinsic [(] func_name_list [)]

#pragma  function [(] func_name_list [)]

#pragma  function  ()

The #pragma  intrinsic directive enables intrinsic treatment of a function. When the #pragma  intrinsic directive is turned on, the compiler understands how the functions work and is thus able to generate more efficient code. A declaration for the function must be in effect at the time the pragma is processed.

The #pragma  function directive disables the intrinsic treatment of a function. A #pragma  function directive with an empty func_name_list disables intrinsic processing for all functions.

Some standard library functions also have built-in counterparts in the compiler. A built-in is a synonym name for the function and is equivalent to declaring the function to be intrinsic. The following built-ins (and their built-in names) are provided:

Function Synonym
abs _ _builtin_abs
labs _ _builtin_labs
fabs _ _builtin_fabs
alloca _ _builtin_alloca
strcpy _ _builtin_strcpy

Several methods are available for using intrinsics and built-ins. The header files containing the declarations of the functions contain the #pragma  intrinsic directive for the functions shown in Table 3-1. To enable the directive, you must define the preprocessor macro _INTRINSICS. For alloca, all that is necessary is to include alloca.h.

For example, to get the intrinsic version of abs, a program should either include stdlib.h and compile with -D_INTRINSICS or define _INTRINSICS with a #define directive before including stdlib.h.

To enable built-in processing, use the -D switch. For example, to enable the fabs built-in, the proc.c program is compiled with one of the following:

% cc -Dfabs=_ _builtin_fabs prog.c
% cc -Dabs=_ _builtin_abs prog.c

Optimization of the preceding functions varies according to the function and how it is used:

3.7    The #pragma linkage Directive

The #pragma  linkage directive allows you to specify linkage types. A linkage type specifies how a function uses a set of registers. It allows you to specify the registers that a function uses. It also allows you to specify the characteristics of a function (for example, the registers in which it passes parameters or returns values) and the registers that it can modify. The #pragma  use_linkage directive associates a previously defined linkage with a function (see Section 3.13).

The #pragma  linkage directive affects both the call site and function compilation (if the function is written in C). If the function is written in assembler, you can use the linkage pragma to describe how the assembler uses registers.

The #pragma  linkage directive has the following format:

#pragma  linkage linkage-name = (characteristics)

linkage-name

Identifies the linkage type being defined. It has the form of a C identifier. Linkage types have their own name space, so their names will not conflict with other identifiers or keywords in the compilation unit.

characteristics

Specifies information about where parameters will be passed, where the results of the function are to be received, and what registers are modified by the function call.

You must specify a register-list. A register-list is a comma-separated list of register names, either rn or fn. A register-list can also contain parenthesized sublists. Use the register-list to describe arguments and function result types that are structures, where each member of the structure is passed in a single register. For example:

parameters(r0,(f0,f1))

The preceding example is a function with two parameters. The first parameter is passed in register r0. The second parameter is a structure type with two floating-point members, which are passed in registers f0 and f1.

The following list of characteristics can be specified as a parenthesized list of comma-separated items. Note, these keywords can be supplied in any order.

  • parameters (register-list)

    The parameters characteristic passes arguments to a routine in specific registers.

    Each item in the register-list describes one parameter that is passed to the routine.

    You can pass structure arguments by value, with the restriction that each member of the structure is passed in a separate parameter location. Doing so, however, may produce code that is slower because of the large number of registers used. The compiler does not diagnose this condition.

    Valid registers for the parameters option include integer registers r0 through r25 and floating-point registers f0 through f30.

    Structure types require at least one register for each field. The compiler verifies that the number of registers required for a structure type is the same as the number provided in the pragma.

  • result  (register-list)

    The compiler needs to know which registers will be used to return the value from the function. Use the result characteristic to pass this information.

    If a function does not return a value (that is, the function has a return type of void), do not specify result as part of the linkage.

    Valid registers for the register option include general-purpose registers r0 through r25 and floating-point registers f0 through f30.

  • preserved (register-list)
    nopreserve (register-list)
    notused (register-list)
    notneeded ((lp))

    The compiler needs to know which registers are used by the function and which are not, and of those used, whether they are preserved across the function call. To specify this information, use the preserved, nopreserve, notused, and notneeded options:

    • A preserved register contains the same value after a call to the function as it did before the call.

    • A nopreserve register does not necessarily contain the same value after a call to the function as it did before the call.

    • A notused register is not used in any way by the called function.

    • The notneeded characteristic indicates that certain items are not needed by the routines using this linkage. The lp keyword specifies that the Linkage Pointer register (r27) does not need to be set up when calling the specified functions. The linkage pointer is required when the called function accesses global or static data. You must determine whether it is valid to specify that the register is not needed.

    Valid registers for the preserved, nopreserve, and notused options include general-purpose registers r0 through r30 and floating-point registers f0 through f30.

The #pragma  linkage directive does not support structures containing nested substructures as parameters or function return types with special linkages. Functions that have a special linkage associated with them do not support parameters or return types that have a union type.

The following characteristics specify a simple-register-list containing two elements (registers f3 and f4); and a register-list containing two elements (register r0 and a sublist containing the registers f0 and f1):

nopreserve(f3,f4)
parameters(r0,(f0,f1))

The following example shows a linkage using such characteristics:

#pragma linkage my_link=(nopreserve(f3,f4),
                parameters(r0,(f0,f1)),
                notneeded (lp))

The parenthesized notation in a register-list describes arguments and function return values of type struct, where each member of the struct is passed in a single register. In the following example, sample_linkage specifies two parameters -- the first is passed in registers r0, r1, and r2 and the second is passed in f1:

struct sample_struct_t {
    int A, B;
    short C;
    } sample_struct;
 
#pragma linkage sample_linkage = (parameters ((r0, r1, r2), f1))
void sub (struct sample_struct_t p1, double p2) { }
 
main()
{
    double d;
 
    sub (sample_struct, d);
}

3.8    The #pragma member_alignment Directive

By default, the compiler aligns structure members on natural boundaries. Use the #pragma  [no]member_alignment preprocessor directive to determine the byte alignment of structure members.

This pragma has the following formats:

#pragma  member_alignment [ save  |  restore ]

#pragma  nomember_alignment

save  |  restore

Saves the current state of the member alignment (including pack alignment) and restores the previous state, respectively. The ability to control the state is necessary for writing header files that require member_alignment or nomember_alignment, or that require inclusion in a member_alignment that is already set.

Use #pragma  member_alignment to specify natural-boundary alignment of structure members. When #pragma  member_alignment is used, the compiler aligns structure members on the next boundary appropriate to the type of the member, rather than on the next byte. For instance, an int variable is aligned on the next longword boundary; a short variable is aligned on the next word boundary.

Where the #pragma  [no]member_alignment directives allow you to choose between natural and byte alignment, the pragma  pack directive allows you to specify structure member alignment on byte, word, longword, or quadword boundaries. See Section 3.11 for more information on #pragma  pack.

With any combination of #pragma  member_alignment, #pragma  nomember_alignment, and #pragma  pack, each pragma remains in effect until the next one is encountered.

3.9    The #pragma message Directive

The #pragma  message directive controls the issuance of individual diagnostic messages or groups of diagnostic messages. The use of this pragma overrides any command-line options that may affect the issuance of messages.

The #pragma  message directive has the following formats:

#pragma  message option1 (message-list)

#pragma  message option2

#pragma  message ("string")

3.9.1    #pragma message option1

This form of the #pragma message directive has the following format:

#pragma  message option1 (message-list)

The option1 parameter must be one of the following keywords:

enable

Enables issuance of the messages specified in the message list.

disable

Disables issuance of the messages specified in the message list. Only messages of severity Warning or Information can be disabled. If the message has a severity of Error or Fatal, it is issued regardless of any attempt to disable it.

emit_once

Emits the specified messages only once per compilation. Certain messages are emitted only the first time the compiler encounters the causal condition. When the compiler encounters the same condition later in the program, no message is emitted. Messages about the use of language extensions are an example of this kind of message. To emit one of these messages every time the causal condition is encountered, use the emit_always option.

Errors and Fatals are always emitted. You cannot set them to emit_once.

emit_always

Emits the specified messages at every occurrence of the condition.

error

Sets the severity of the specified messages to Error. Supplied Error messages and Fatal messages cannot be made less severe. (The exception is that a message can be upgraded from Error to Fatal, then later downgraded to Error again, but it can never be downgraded from Error.) Warnings and Informationals can be made any severity.)

fatal

Sets the severity of the specified messages to Fatal.

informational

Sets the severity of the specified messages to Informational. Note that Fatal and Error messages cannot be made less severe.

warning

Sets the severity of each message in the message-list to Warning. Note that Fatal and Error messages cannot be made less severe.

The message-list parameter can be one of the following:

Note

The default is to issue all diagnostic messages for the selected compiler mode except those in the check group, which must be explicitly enabled to display its messages.

3.9.2    #pragma message option2

This form of the #pragma message directive has the following format:

#pragma  message option2

The option2 parameter must be one of the following keywords:

save

Saves the current state of which messages are enabled and disabled.

restore

Restores the previous state of which messages are enabled and disabled.

The save and restore options are useful primarily within header files.

3.9.3    #pragma message ("string")

This form of the #pragma message directive is provided for compatibility with the Microsoft #pragma message directive, and it has the following format:

#pragma  message ("string")

The directive emits the specified string as a compiler message. For example, when the compiler encounters the following line in the source file:

#pragma message ("hello")

It emits:

cc: Info: a.c, line 10: hello (simplemessage)
#pragma message ("hello")
----------------^
 
 

This form of the pragma is subject to macro replacement. For example, the following is allowed:

#pragma message ("Compiling file " _ _FILE_ _)
 

3.10    The #pragma optimize Directive

The #pragma  optimize directive sets the optimization characteristics of function definitions that follow the directive. It allows optimization-control options that are normally set on the command line for the entire compilation to be specified in the source file for individual functions. This pragma has the following formats:

#pragma  optimize settings

#pragma  optimize save

#pragma  optimize restore

The settings is any combination of the following:

level settings

These set the optimization level. Specify the level as follows:

level=n

Where n is an integer from 0 to 5:

0

Disables all optimizations. Does not check for unassigned variables.

1

Enables local optimizations and recognition of some common subexpressions. The callgraph determines the order of compilation of procedures.

2

Includes level 1 optimizations. Enables global optimization. This includes data-flow analysis, code motion, strength reduction and test replacement, split lifetime analysis, and code scheduling.

3

Includes level 2 optimizations. Enables additional global optimizations that improve speed (at the cost of extra code size), for example: integer multiplication and division expansion (using shifts), loop unrolling, and code replication to eliminate branches.

4

Includes level 3 optimizations. Enables interprocedural analysis and automatic inlining of small procedures (with heuristics limiting the amount of extra code). This is the default.

5

Includes level 4 optimizations. Activates software pipelining, which is a specialized form of loop unrolling that in certain cases improves run-time performance. Software pipelining uses instruction scheduling to eliminate instruction stalls within loops, rearranging instructions between different unrolled loop iterations to improve performance.

Loops chosen for software pipelining are always innermost loops and do not contain branches or procedure calls. To determine whether using level 5 benefits your particular program, you should time program execution for the same program compiled at level 4 and level 5. For programs that contain loops that exhaust available registers, longer execution times may result with level 5.

unroll settings

These control loop unrolling. Specify as follows:

unroll=n

Where n is a nonnegative integer. unroll= n means to unroll loop bodies n times, where n is between 0 and 16. unroll=0 means the optimizer will use its own default unroll amount. Specify unroll only at level 3 or higher.

ansi-alias settings

These control ansi-alias assumptions. Specify one of the following:

ansi_alias=on
ansi_alias=off

intrinsic settings

These control recognition of intrinsics. Specify on of the following:

intrinsics=on
intrinsics=off

Whitespace is optional between the setting clauses and before and after the "=" in each clause. The pragma is not subject to macro replacement.

Example:

#pragma optimize level=5 unroll=6

The save and restore options save and restore the current optimization state (level, unroll count, ansi-alias setting, and intrinsic setting).

Usage Notes

3.11    The #pragma pack Directive

The #pragma  pack directive changes the alignment restrictions on all members of a structure. The pragma must appear before the entire structure definition because it acts on the whole structure. The syntax of this pragma is as follows:

#pragma  pack (n)

The n is a number (such as 1, 2, or 4) that specifies that subsequent structure members are to be aligned on n-byte boundaries. If you supply a value of 0 (zero) for n, the alignment reverts to the default, which may have been set by the -Zpn option on the cc command.

3.12    The #pragma pointer_size Directive

The #pragma  pointer_size directive controls pointer size allocation for the following:

This pragma has the following syntax:

#pragma  pointer_size { long  |  short  |  64  |  32 } | { save  |  restore }
        

long  |  64

Sets all pointer sizes as 64 bits in all declarations that follow this directive, until the compiler encounters another #pragma  pointer_size directive.

short  |  32

Sets all pointer sizes as 32 bits in declarations that follow this directive, until the compiler encounters another #pragma  pointer_size directive.

save  |  restore

Saves the current pointer size and restores the saved pointer size, respectively. The save and restore options are particularly useful for specifying mixed pointer support and for protecting header files that interface to older objects. Objects compiled with multiple pointer size pragmas will not be compatible with old objects, and the compiler cannot discern that incompatible objects are being mixed.

For example:

 #pragma pointer_size long
   /* pointer sizes in here are 64-bits */
 #pragma pointer_size save
 #pragma pointer_size short
   /* pointer sizes in here are 32-bits */
 #pragma pointer_size restore
   /* pointer sizes in here are again 64-bits */

The use of short pointers is restricted to Compaq C++ and Compaq C compilers residing on a Tru64 UNIX system. Programs should not attempt to pass short pointers from C++ routines to routines written in any language other than the C programming language. Also, Compaq C++ may require explicit conversion of short pointers to long pointers in applications that use short pointers. You should first port those applications in which you are considering using short pointers, and then analyze them to determine if short pointers would be beneficial. A difference in the size of a pointer in a function declaration is not sufficient to overload a function.

The C compiler issues an error level diagnostic if it encounters any of the following conditions:

3.13    The #pragma use_linkage Directive

After defining a special linkage with the #pragma  linkage directive, as described in Section 3.7, use the #pragma  use_linkage directive to associate the linkage with a function.

This pragma has the following syntax:

#pragma  use_linkage linkage-name (id1, id2, ...)
        

linkage-name

Specifies the name of a linkage that the #pragma linkage directive previously defined.

id1, id2, ...

Specifies the names of functions, or typedef names of function type, that you want to associate with the specified linkage.

If you specify a typedef name of function type, then functions or pointers to functions that are declared using that type will have the specified linkage.

The #pragma  use_linkage directive must appear in the source file before any use or definition of the specified routines. Otherwise, the results are unpredictable.

The following example defines a special linkage and associates it with a routine that takes three integer parameters and returns a single integer result in the same location where the first parameter was passed:

#pragma linkage example_linkage (parameters(r16, r17, r19), result(r16))
#pragma use_linkage example_linkage (sub)
int sub (int p1, int p2, short p3);
 
main()
{
    int result;
 
    result = sub (1, 2, 3);
}

In this example, the result(r16) option indicates that the function result will be returned in register r16 instead of the usual location (r0). The parameters option indicates that the three parameters that are passed to sub should be passed in registers r16, r17, and r19.

In the following example, both the function f1 and the function type t are given the linkage foo. The invocation through the function pointer f2 will correctly invoke the function f1 using the special linkage.:

#pragma linkage foo = (parameters(r1), result(r4)) 
#pragma use_linkage foo(f1,t) 
 
int f1(int a); 
typedef int t(int a); 
 
t *f2; 
 
#include <stdio.h> 
 
main() { 
    f2 = f1; 
    b = (*f2)(1); 
}

3.14    The #pragma weak Directive

The #pragma  weak directive defines a new weak external symbol and associates this new symbol with an external symbol. The syntax for this pragma is as follows:

#pragma  weak (secondary-name, primary-name)
        

See Section 2.8 for information on strong and weak symbols.