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:
#pragma assert
(Section 3.1)
#pragma environment
(Section 3.2)
#pragma extern_model
(Section 3.3)
#pragma extern_prefix
(Section 3.4)
#pragma inline
(Section 3.5)
#pragma intrinsic
and
#pragma function
(Section 3.6)
#pragma linkage
(Section 3.7)
#pragma member_alignment
(Section 3.8)
#pragma message
(Section 3.9)
#pragma optimize
(Section 3.10)
#pragma pack
(Section 3.11)
#pragma pointer_size
(Section 3.12)
#pragma use_linkage
(Section 3.13)
#pragma weak
(Section 3.14)
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
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.
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.
Determines how
the format string is interpreted, and should be either
printf
or
scanf
.
Specifies which argument is the format string argument (starting from 1).
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:
Saves the state of all context pragmas. [Return to example]
Sets the default compilation environment. [Return to example]
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]
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
andglobalvalue
, 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]...]
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
:
For each id there must not be a declaration of that id visible at the point of the pragma; otherwise a warning is issued, and there is no effect on that id.
Each id affected by a pragma with a nonempty prefix is expected to be subsequently declared with external linkage in the same compilation unit. The compiler issues a default informational if there is no such declaration made by the end of the compilation.
It is perfectly acceptable for the id list form of the pragma, or declarations of the ids listed, to occur within a region of source code controlled by the other form of the pragma. The two forms do not interact; the form with an id list always supersedes the other form.
There is no interaction between the
save
/restore
stack and the id lists.If the same id appears in more than one pragma, then a default informational message is issued, unless the prefix on the second pragma is either empty
(""
) or matches the prefix from the previous pragma. In any case, the behavior is that the last-encountered prefix supersedes all others.
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:
Arguments are evaluated only once.
Overuse of parentheses is not necessary to avoid problems with precedence.
Actual expansion can be controlled from the command line.
The semantics are as if inline expansion had not occurred. You cannot get this behavior using macros.
The following preprocessor directives control function inlining:
#pragma inline (id, ...)
#pragma noinline (id, ...)
Where id is a function identifier:
If a function is named in a
#pragma inline
directive, calls to that function are expanded as inline code,
if possible.
If a function is named in a
#pragma noinline
directive, calls to that function are not expanded as inline code.
If a function is named in both a
#pragma inline
and a
#pragma noinline
directive,
an error message is issued.
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:
Size
Number of times the function is called
Conformance to the following restrictions:
The function does not take a parameter's address.
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.
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:
The following functions are inlined:
abs
fabs
labs
alloca
The function call overhead is removed.
In certain instances, the
printf
and
fprintf
functions are converted to call
puts
,
putc
,
fputs
, or
fputc
(or
their equivalents), depending on the format string and the number and types
of arguments.
In certain instances, the
sprintf
function
is inlined or converted to a call to
strcpy
.
The
strcpy
function is inlined if the source
string (the second argument) is a string literal.
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)
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.
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")
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.
A single message identifier (within parentheses or not).
Use
the
-verbose
option on the
cc
command
to obtain the message identifier.
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.
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.
nonansi
Messages reporting the use of non-ANSI Standard features.
defunct
Messages reporting the use of obsolete features: ones that were commonly accepted by early C compilers but were subsequently removed from the language.
obsolescent
Messages reporting the use of features that are valid in ANSI Standard C, but which were identified in the standard as being obsolete 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 nonportable 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 nonrobust style.
returnchecks
Messages related to function return values.
uninit
Messages related to using uninitialized variables.
unused
Messages reporting expressions, declarations, header files, static functions, and code paths that are not used.
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. Level2 is the default for Compaq C.
level3
Less important messages.
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
#pragma
message
.
Referred to as message level0, 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
level0
(You cannot disable it,
enable it, change its severity, or change its
emit_once
characteristic).
However, you can modify individual messages in
level0
, provided such modification is allowed by the action.
For
example, you can disable a Warning or Informational in
level0
,
or you can change an error in
level0
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 message levels, freely mixed, enclosed in parentheses.
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:
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
.
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.
These control ansi-alias assumptions. Specify one of the following:
ansi_alias=on
ansi_alias=off
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
If the
level=0
clause is present, it must be the only clause present.The
#pragma optimize
directive must appear at file scope, outside any function body.The
#pragma environment
save
andrestore
operations include the optimization state.The
#pragma environment command_line
directive resets the optimization state to that specified on the command line.If
#pragma optimize
does not specify a setting for one of the optimization states, that state remains unchanged.When a function definition is encountered, it is compiled using the optimization settings that are current at that point in the source.
When a function is compiled under
level=0
, the compiler will not inline that function. In general, when functions are inlined, the inlined code is optimized using the optimization controls in effect at the call site instead of using the optimization controls specified for the function being inlined.
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:
References
Pointer declarations
Function declarations
Array declarations
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:
Two functions defined differ only with respect to pointer sizes.
Two functions differ in return type only with respect to pointer size.
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, ...)
Specifies
the name of a linkage that the
#pragma linkage
directive
previously defined.
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.