[an error occurred while processing this directive]

HP OpenVMS Systems

C Programming Language
Content starts here Compaq C

Compaq C
User's Guide for OpenVMS Systems


Previous Contents Index

5.4.7 #pragma function Directive (ALPHA ONLY)

Specifies that calls to the specified functions are not intrinsic but are, in fact, function calls. This pragma has the opposite effect of #pragma intrinsic .

The #pragma function directive has the following format:


#pragma function (function1[, function2, ...])

5.4.8 #pragma [no]include_directory Directive

The effect of each #pragma include_directory is as if its string argument (including the quotes) were appended to the list of places to search that is given its initial value by the /INCLUDE_DIRECTORY qualifier, except that an empty string is not permitted in the pragma form.

The #pragma include_directory directive has the following format:


#pragma include_directory <string-literal>

This pragma is intended to ease DCL command-line length limitations when porting applications from POSIX-like environments built with makefiles containing long lists of -I options specifying directories to search for headers. Just as long lists of macro definitions specified by the /DEFINE qualifier can be converted to #define directives in a source file, long lists of places to search specified by the /INCLUDE_DIRECTORY qualifier can be converted to #pragma include_directory directives in a source file.

Note that the places to search, as described in the help text for the /INCLUDE_DIRECTORY qualifier, include the use of POSIX-style pathnames, for example "/usr/base" . This form can be very useful when compiling code that contains POSIX-style relative pathnames in #include directives. For example, #include <subdir/foo.h> can be combined with a place to search such as "/usr/base" to form "/usr/base/subdir/foo.h" , which will be translated to the filespec "USR:[BASE.SUBDIR]FOO.H"

This pragma can appear only in the main source file or in the first file specified on the /FIRST_INCLUDE qualifier. Also, it must appear before any #include directives.

5.4.9 #pragma [no]inline Directive

Function inlining is the inline expansion of function calls; it replaces 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:

  • Arguments are evaluated only once.
  • The overuse of parentheses is not necessary to avoid problems with precedence.
  • The actual expansion can be controlled from the command line.

Also, the semantics are exactly the same as if inline expansion had not occurred. You cannot get this behavior using macros.

Use the following preprocessor directives to control function inlining:


#pragma inline ( id,... )


#pragma noinline ( id,... )

The id is a function identifier.

If a function is named in an inline directive, calls to that function will be expanded as inline code, if possible.

If a function is named in a noinline directive, calls to that function will not be expanded as inline code.

If a function is named in both an inline and a noinline directive, an error message is issued.

For calls to functions named in neither an inline nor a noinline directive, Compaq C expands the function as inline code whenever appropriate as determined by a platform-specific algorithm.

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

In the following example of function inlining, the functions push and pop are expanded inline throughout the module in which the #pragma inline appears:


void push(int);
int pop(void);

#pragma inline(push, pop)

int stack[100];
int *stackp = &stack;

void push(int x)
{
    if (stackp == &stack)
        *stackp = x;
    else
        *stackp++ = x;
}

int pop()
{
    return *stackp--;
}

main()
{

  push(1);
  printf("The top of stack is now %d \n",pop());
}

By default, Compaq C for OpenVMS Systems attempts to provide inline expansion for all functions, and uses the following function characteristics to determine if it can provide inline expansion:

  • Size
  • Number of times the function is called
  • Conformance to the following restrictions:
    • The function does not take the address of a parameter.
    • The function does not use an index expression that is not a compile-time constant in an array that is a field of a struct argument. An argument that is a pointer to a struct is not restricted.
    • The function does not use the varargs or stdarg package to access the function's arguments because they require arguments to be in adjacent memory locations, and inline expansion may violate that requirement.
    • The function does not declare an exception handler.

If a function is to be expanded inline, you must place the function definition in the same module as the function call. The definition can appear either before or after the function call.

5.4.10 #pragma intrinsic Directive (ALPHA ONLY)

The #pragma intrinsic preprocessor directive specifies that calls to the specified functions are intrinsic. An intrinsic function is an apparent function call that could be handled as an actual call to the specified function, or could be handled by the compiler in a different manner. By treating the function as an intrinsic, the compiler can often generate faster code. (Contrast with a built-in function, which is an apparent function call that is never handled as an actual function call. There is never a function with the specified name.)

This pragma has the opposite effect of #pragma function .

The #pragma intrinsic directive has the following format:


#pragma intrinsic (function1[,function2, ...])

Functions that can be handled as intrinsics are:


Main Group - ANSI:

  abs     atan2   ceilf   cosl    floorl   memset  sinl
  atan    atan2f  ceill   fabs    labs     sin     strcpy
  atanf   atan2l  cos     floor   memcpy   sinf    strlen
  atanl   ceil    cosf    floorf  memmove

Main Group - Non-ANSI:

  alloca  atand   atand2  bcopy   bzero    cosd    sind

Printf functions:

  fprintf printf sprintf

Printf non-ANSI:

  snprintf

ANSI math functions that set errno,
thereby requiring /ASSUME=NOMATH_ERRNO:

  acos    asinl   expf    log10    powl   sqrtf  tanh
  acosf   cosh    expl    log10f   sinh   sqrtl  tanhf
  acosl   coshf   log     log10l   sinhf  tan    tanhl
  asin    coshl   logf    pow      sinhl  tanf
  asinf   exp     logl    powf     sqrt   tanl

Non-ANSI math functions that set errno,
thereby requiring /ASSUME=NOMATH_ERRNO:

  log2
  tand

Also see Section 1.3.4 for a description of the [NO]INTRINSICS option of the /OPTIMIZE qualifier, which controls whether or not certain functions are handled as intrinsic functions without explicitly enabling each of them as an intrinsic through the #pragma intrinsic directive.

Also, the asm , fasm , and dasm functions are intrinsics and require use of #pragma intrinsic . See Section 6.2.1.2 for a description of these functions.

5.4.11 #pragma linkage Directive (ALPHA ONLY)

The #pragma linkage preprocessor directive allows you to specify special linkage types for function calls. This pragma is used with the #pragma use_linkage directive, described in Section 5.4.22, to associate a previously defined special linkage with a function.

The #pragma linkage directive has the following format:


#pragma linkage linkage-name = (characteristics)

The linkage-name is the name to be given to 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.

The characteristics specify 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. Specify these characteristics as a parenthesized list of comma-separated items of the following forms:


parameters (register-list)
result (simple-register-list)
preserved (simple-register-list)
nopreserve (simple-register-list)
notused (simple-register-list)
notneeded (ai, lp)

You can supply the parameters , result , preserved , nopreserve , notused , and notneeded keywords in any order.

A simple-register-list is a comma-separated list of register names, either Rn or Fn, where n is a valid register number. A register-list is similar to a simple-register-list except that it can contain parenthesized sublists.

Valid registers for the preserved , nopreserve , and notused options include general-purpose registers R0 through R30, and floating-point registers F0 through F30. Valid registers for the result and parameters options include general-purpose registers R0 through R25 and floating-point registers F0 through F30.

For example, the following characteristics specify a simple-register-list containing two elements, registers F3 and F4; and a register-list containing two elements, the 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 (ai))

The parenthesized notation in a register-list is used to describe 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; 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);
}

You can pass arguments to the parameters of a routine in specific registers. To specify this information, use the following form, where each item in the register-list describes one parameter that is passed to the routine:


parameters (register-list)

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.

Compaq C does not support unions as parameters or function return types for a function with a special linkage.

When a function associated with a linkage type is declared or defined, the compiler checks that the size of any declared parameters is compatible with the number of registers specified for the corresponding parameter in the linkage definition.

The compiler needs to know the registers that will be used to return the value for the function. To specify this information use the following form, where the register-list must contain only a single register, or a parenthesized group of registers if the routine returns a struct :


result (register-list)

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

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


preserved (register-list)
nopreserve (register-list)
notused (register-list)

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. You can specify one or both of the following keywords:

  • ai ---Specifies that the Argument Information register (R25) does not need to be set up when calling the specified functions.
  • lp ---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 or not it is valid to specify that the ai or lp registers are not needed.

The #pragma linkage directive has the restriction that structures containing nested substructures are not supported as parameters or function return types with special linkages.

5.4.12 #pragma [no]member_alignment Directive

By default, Compaq C for OpenVMS VAX systems does not align structure members on natural boundaries; they are stored on byte boundaries (with the exception of bit-field members).

By default, Compaq C for OpenVMS Alpha systems does align structure members on natural boundaries.

The #pragma member_alignment preprocessor directive can be used to force natural-boundary alignment of structure members. The #pragma nomember_alignment preprocessor directive restores byte-alignment of structure members.

This pragma has the following formats:


#pragma member_alignment
#pragma member_alignment save
#pragma member_alignment restore
#pragma nomember_alignment [base_alignment]

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 example, a long variable is aligned on the next longword boundary; a short variable is aligned on the next word boundary.

Consider the following example:


#pragma nomember_alignment

struct x {
           char c;
           int b;
           };

#pragma member_alignment

struct y {
          char c;       /*3 bytes of filler follow c */
          int b;
          };

main ()

{
        printf( "The sizeof y is: %d\n", sizeof (struct y) );
        printf( "The sizeof x is: %d\n", sizeof (struct x) );
}

When this example is executed, it shows the difference between #pragma member_alignment and #pragma nomember_alignment .

Once used, the member_alignment pragma remains in effect until the nomember_alignment pragma is encountered; the reverse is also true.

The optional base_alignment parameter can be used to specify the base-alignment of the structure. Use one of the following keywords for the base_alignment:

  • byte (1 byte)
  • word (2 bytes)
  • longword (4 bytes)
  • quadword (8 bytes)
  • octaword (16 bytes)

The #pragma member_alignment save and #pragma member_alignment restore directives can be used to save the current state of the member_alignment and to restore the previous state, respectively. This feature 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.

5.4.13 #pragma message Directive

The #pragma message directive controls the issuance of individual diagnostic messages or groups of messages. 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 (quoted-string)

5.4.13.1 #pragma message option1

The parameter option1 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
  • 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. (Exception: 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 can be any one of the following:

  • A single message identifier (within parentheses, or not). The message identifier is the name following the severity at the start of a line when a message is issued. For example, in the following message, the message identifier is GLOBALEXT:


    %CC-W-GLOBALEXT, a storage class of globaldef, globalref, or globalvalue
    is a language extension.
    
  • The name of a single message group (within parentheses, or not). Message-group names are:
    • ALL---All the messages in the compiler
    • ALIGNMENT---Messages about unusual or inefficient data alignment.
    • C_TO_CXX---Messages reporting the use of C features that would be invalid or have a different meaning if compiled by a C++ compiler.
    • CDD---Messages about CDD (Common Data Dictionary) support.
    • CHECK---Messages reporting code or practices that, although correct and perhaps portable, are sometimes considered ill-advised because they can be confusing or fragile to maintain. For example, assignment as the test expression in an "if" statement.
      The check group gets defined by enabling LEVEL5 messages.
    • DEFUNCT---Messages reporting the use of obsolete features: ones that were commonly accepted by early C compilers but were subsequently removed from the language.
    • NEWC99---Messages reporting the use of the new C99 Standard features.
    • NOANSI---This is a deprecated message group. It is an obsolete synonym for NOC89. Also see message groups NEWC99, NOC89, NOC99.
    • NOC89---Messages reporting the use of non-C89 Standard features.
    • NOC99---Messages reporting the use of non-C99 Standard features.
    • OBSOLESCENT---Messages reporting the use of features that are valid in ANSI Standard C, but which were identified in the standard as being obsolescent and likely to be removed from the language in a future version of the standard.
    • OVERFLOW---Messages that report assignments and/or casts that can cause overflow or other loss of data significance.
    • PERFORMANCE---Messages reporting code that might result in poor run-time performance.
    • PORTABLE---Messages reporting the use of language extensions or other constructs that might not be portable to other compilers or platforms.
    • PREPROCESSOR---Messages reporting questionable or non-portable use of preprocessing constructs.
    • QUESTCODE---Messages reporting questionable coding practices. Similar to the CHECK group, but messages in this group are more likely to indicate a programming error rather than just a non-robust style.

      Note

      Enabling the QUESTCODE group provides lint-like checking.
    • RETURNCHECKS---Messages related to function return values.
    • UNINIT---Messages related to using uninitialized variables.
    • UNUSED---Messages reporting expressions, declarations, header files, CDD records, static functions, and code paths that are not used.
      Note, however, that unlike any other messages, these messages must be enabled on the command line (/WARNINGS=ENABLE=UNUSED) to be effective.
  • A single message-level name (within parentheses, or not).
    Message-level names are:
    • LEVEL1---Important messages. These are less important than the level 0 core messages, because messages in this group are not displayed if #pragma nostandard is active.
    • LEVEL2---Moderately important messages.
    • LEVEL3---Less important messages.
      LEVEL3 is the default message level for Compaq C for OpenVMS systems.
    • LEVEL4---Useful check/portable messages.
    • LEVEL5---Not so useful check/portable messages.
    • LEVEL6---Additional "noisy" messages.

    Be aware that there is a core of very important compiler messages that are enabled by default, regardless of what you specify with /WARNINGS or #pragma message . Referred to as message level 0, it includes all messages issued in header files, and comprises what is known as the nostandard group. All other message levels add additional messages to this core of enabled messages.
    You cannot modify level 0 (You cannot disable it, enable it, change its severity, or change its EMIT_ONCE characteristic). However, you can modify individual messages in level 0, provided such modification is allowed by the action. For example, you can disable a Warning or Informational in level 0, or you can change an error in level 0 to a Fatal, and so on. (See restrictions on modifying individual messages.)
    Enabling a level also enables all the messages in the levels lower than it. So enabling LEVEL3 messages also enables messages in LEVEL2 and LEVEL1.
    Disabling a level also disables all the messages in the levels higher than it. So disabling LEVEL4 messages also disables messages in LEVEL5 and LEVEL6.
  • A comma-separated list of message identifiers, group names, and messages levels, freely mixed, enclosed in parentheses.


Previous Next Contents Index