|
Compaq C V6.4 for OpenVMS VAX Release Notes
7 Compaq C for OpenVMS VAX Release Notes
7.1 New Features in Compaq C V6.4
In addition to the support for installing multiple compiler versions,
this version provides most of the language-feature support for the new
C99 standard that will be implemented for VAX. The C99 standard
(ISO/IEC 9899:1999) was published by ISO in December, 1999 and adopted
as an ANSI standard in April, 2000. An official copy of the standard
can be purchased and downloaded as a PDF file for less than $20US from
either
NCITS or
ANSI.
While Compaq C for OpenVMS Alpha will support all of C99, the VAX
version is intended to provide only those features whose implementation
is shared with Alpha. In particular, features that involve changes to
the VAX code generator or to VAX-specific run-time libraries are not
planned. Most notably, the new data types "_Complex" and "long long
int" are not planned for VAX, nor are the new C99 "type-generic" math
library functions, other new math functions, or the hexadecimal
notation for floating point values. [Note that since the new C99 "long
long int" data type is not implemented for VAX, there is no change to
the rules for determining the type of a decimal integer constant; only
the Alpha implementation is affected by the new C99 rules for decimal
integer constants.]
The following specific enhancements were made:
- Language modes,
/STANDARD=C99
, and message groups
The compiler's default language mode remains
/STANDARD=RELAXED_ANSI89, which accepts nearly all language extensions
as well as standard C89 and C99 features. It excludes only K&R
("common" mode), VAX C, and Microsoft features that conflict with
standard C. The /STANDARD=ANSI89 mode continues to implement strictly
the 1990 ANSI/ISO C standard (commonly called C89), issuing all
required diagnostics as well as a number of optional diagnostics that
help detect source code constructs that are not portable under the C89
standard (digraphs from the 1994 Amendment are also recognized in this
mode, even though they were not specified in the 1990 standard). The
ISOC94 keyword can still be added to any of the modes (except VAXC) to
predefine the macro __STDC_VERSION__, as specified in Amendment 1 to
the C89 standard.
The command line will recognize a new language mode qualifier,
/STANDARD=C99, but it will issue a warning and treat it exactly the
same as /STANDARD=RELAXED_ANSI89, which accepts all of the C99 features
that are implemented for VAX.
Since the standard is quite new, use of C99 features is not really
portable in a practical sense yet. Also, the term "ANSI C" or "standard
C" will be ambiguous for some time to come (i.e. do you mean C89 or
C99). To help with this situation, the compiler has added three new
message groups for messages that report the use of features in the
following categories:
noc89 - features not in C89
noc99 - features not in C99
newc99 - features that are new in C99.
|
The existing group,
noansi
, which is now somewhat ambiguous in name, is retained as a synonym for
noc89.
-
#pragma names
This pragma offers the same kinds of control over the mapping of
external identifiers into object module symbols as does the command
line qualifier /NAMES, and it uses the same keywords (except that the
"lowercase" keyword is not supported). But as a pragma, the controls
can be applied selectively to regions of declarations. The pragma has a
save/restore stack that is also managed by
#pragma environment
, and so it is well-suited to use in header files. The effect of "
#pragma environment header_defaults
" is to set NAMES to "uppercase,truncated", which is the compiler
default.
One important use for this feature is to make it easier to use command
line option
/NAMES=AS_IS
. Both the C99 standard and the C++ standard require that external
names be treated as case-sensitive, and 3rd party libraries and Java
native methods are starting to rely on case-sensitivity (C99 requires a
minimum of 31 characters significant, while C++ requires all characters
significant). Therefore we expect the use of /NAMES=AS_IS to become
much more widespread.
The Compaq C run-time library was implemented with all symbols
duplicated and spelled both in uppercase and lowercase to allow C
programs compiled with any of the /NAMES= settings to work. But
traditional practice on OpenVMS combined with compiler defaults of
/NAMES=UPPER has resulted in nearly all existing object libraries and
shared images to contain all uppercase names (both in references and in
definitions), even though C source code using these libraries typically
declares the names in lowercase or mixed case. Usually, the header
files to access these libraries contain macro definitions to replace
lowercase names by uppercase names to allow client programs to be
compiled /NAMES=AS_IS. But macro definitions are problematic because
every external name has to have a macro.
The new pragma allows header files to specify just once that the
external names they declare are to be uppercased in the object module,
regardless of the NAMES setting used in the rest of the compilation.
The NAMES setting in effect at the first declaration of an external
name is the one that takes effect, thus the setting specified in a
header file will not be overridden by a subsequent redeclaration in the
user's program (which might specify a different NAMES setting). Note
that the automatic Prologue/Epilogue header file inclusion feature
described in section 1.7.4 of the User's Guide (in connection with
pointer_size pragmas) can also be used to specify the NAMES setting for
all headers in a given directory or text library, without having to
edit each header directly.
Syntax:
#pragma names <stack-option>
#pragma names <case-option>[, <length-option>]
#pragma names <length-option>[, <case-option>]
Where <stack-option> is one of:
save - save the current names state
restore - restore a saved names state
<case-option> is one of:
uppercase - uppercase external names
as_is - do not change case
and <length-option> is one of
truncated - truncate at 31 characters
shortened - shorten to 31 using CRC
|
- New "
_m
" suffix forces pragmas to expand macros
As specified in the
Language Reference Manual, there is a fixed "grandfathered" list of
#pragma
directives that always undergo macro expansion in the preprocessor
before being translated. No other
#pragma
directives normally undergo macro expansion. But since there are
sometimes circumstances where macro expansion is needed on a particular
instance of a pragma, a general mechanism has been added such that
spelling the name of a
#pragma
directive with a trailing "
_m
" suffix will cause that directive to undergo macro expansion. An
example of use follows in the next bullet item for
#pragma assert non_zero
. The suffix is permitted on all pragmas, including those that are
already specified as undergoing macro expansion (in which case it has
no effect).
- New
non_zero
keyword for
#pragma assert
This new keyword allows you to assert that a particular
constant-expression must be non-zero at compile time, and supply a text
string to be output if the assertion proves false. The text string is
output with a warning message that includes the source text of the
expression.
Syntax:
#pragma assert non_zero(<constant-expression>) <string-literal>
|
Note that the constant-expression is a C language constant-expression,
not just a preprocessor
#if
expression. And while
#pragma assert
itself does not perform macro expansion, the alternate form
#pragma assert_m
can be used to cause macro expansion to take place, which is most often
what is desired, as in the second example below (since "offsetof" is a
macro).
Example:
#pragma assert non_zero(sizeof(a) == 12) "wrong size a"
#pragma assert_m non_zero(offsetof(s,b) == 4) "wrong offset b"
|
If the sizeof a is not 12, and the offset of member b in the struct
named by type b is not 4, the following diagnostics are output:
CC-W-ASSERTFAIL, The assertion "(sizeof(a) == 12)" was not true.
wrong size a.
CC-W-ASSERTFAIL, The assertion "(offsetof(s,b) == 4)" was not true.
wrong offset b.
|
- New use of
static
keyword in array bounds.
C99 permits the keyword "
static
" to be used within the outermost array bound of a formal parameter in
a prototype function declaration. The effect is to assert to the
compiler that at each call to the function, the corresponding actual
argument will provide access to at least as many array elements as are
specified in the declared array bound. Consider the following two
function definitions:
void foo(int a[1000]){ ... }
void bar(int b[static 1000]) { ... }
|
The declaration of foo is absolutely equivalent to one that declares
"a" to be "int *". When compiling the body of foo, the compiler has no
information about how many array elements may exist. The declaration of
bar differs in that it asserts to the compiler that it may assume that
at least 1000 array elements exist and may be safely accessed. The
intent is to provide a hint to the optimizer about what can be safely
pre-fetched.
- New type
_Bool
This is the C99-specified boolean type. It is not recognized in
VAXC, COMMON, or the strict ANSI89 mode. An object of this type
occupies one byte and is an unsigned integer, but its value can only be
either 0 or 1. It is permitted to use _Bool as the type for a
bit-field. When a value of any scalar type (any arithmetic type
including floating point and the new complex types, or any pointer
type) is converted to _Bool, the result is zero if the value would
compare equal to 0 (e.g. if the pointer is NULL), and otherwise the
result is 1. It is intended to be used in conjuction with a new
standard header, <stdbool.h>, but that is not required. The
content of the new header is simply as follows:
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
|
- New type keywords
_Complex
and
_Imaginary
Although neither of these C99 types will be implemented on VAX,
their use will be diagnosed. Since these names begin with an underscore
followed by an uppercase letter, they are in the namespace reserved to
the C implementation and should not be used even in strict ANSI89 mode.
7.2 New Features in Compaq C V6.2
This release primarily contains a number of new language features from
the in-process revision to the C standard, C9X (expected to be C99),
and from the gcc compiler (to aid compatibility with source code from
Linux systems). It also has diagnostic message improvements, as well as
bug fixes and miscellaneous improvements.
The following specific enhancements were made:
- more html-format documentation
The Compaq C manuals, help, and
release notes are now installed in html form in a subdirectory of
SYS$HELP. They can be accessed from a locally-running browser through
file:/sys$common/syshlp/cc$vax_help_062/index.htm
|
To access these documents from a browser running on a different
system, you can copy the entire directory contents to a directory or
server system that is accessible to your browser.
- diagnostic for unbalanced pragma state save/restore
The
compiler now issues a diagnostic when a #pragma stack is not empty at
the end of a compilation (i.e. when the program issues a
#pragma <pragma-name> save
directive without ever issuing a corresponding
#pragma <pragma-name> restore
- additional diagnostics to help locate unmatched braces
When a
closing brace is omitted, the parser error is generally reported
against a location far from the point of the actual coding error.
Additional diagnostics now attempt to find which opening brace was not
matched, based on heuristic observation of the indentation style used
in the rest of the source code. In testing, these messages have proved
quite accurate, but if the source code is very inconsistent in this
style, or uses an unusual style, the messages may not be very
effective. We would appreciate feedback on this feature, particularly
testcases where the diagnostic misidentified which brace was unmatched.
- new keywords for /accept qualifier
New keywords for the
/accept command line qualifier:
- [no]c99_keywords
Controls whether or not the new keywords
being introduced in the C standard that are in the C89 namespace for
user identifiers (inline and restrict) are accepted without double
leading underscores.
- [no]gccinline
The gcc compiler implements an inline function
qualifier for functions with external linkage that gives similar
capabilites to the C9X feature described below, but the details of
usage are somewhat different (basically the combination of extern and
inline keywords makes an inline definition, instead of the exlusive use
of the inline keyword without the extern keyword). This option controls
which variation of the feature is implemented.
- extern inline functions (C9X and gcc)
A new keyword,
inline
, has been introduced which can be used as a declaration specifier in
the declaration of a function. With static functions, this has the same
effect as applying
#pragma inline
to the function. When the specifier is applied to a function with
external linkage, besides suggesting to the compiler that calls within
that translation unit be inlined, there are additional rules that allow
calls to the function also to be inlined in other translation units or
else called as an external function at the compiler's discretion:
- If the inline keyword is used on a function declaration with
external linkage, then the function must also be defined in the same
translation unit.
- If all of the file scope declarations of the function use the
inline keyword but do not use the extern keyword, then the definition
in that translation unit is called an inline definition, and no
externally-callable definition is produced by that compilation unit.
Otherwise, the compilation unit does produce an externally-callable
definition.
- An inline definition must not contain a definition of a modifiable
object with static storage duration, and it must not refer to an
identifier with internal linkage. These restrictions do not apply to
the externally-callable definition.
- As usual, at most one compilation unit in an entire program can
supply an externally-callable definition of a given function.
- Any call to a function with external linkage may be translated as
a call to an external function, regardless of the presence of the
inline qualifier. It follows from this and the previous point that any
function with external linkage that is called must have exactly one
externally-callable definition among all the compilation units of an
entire program.
- The address of an inline function with external linkage is always
computed as the address of the unique externally-callable definition,
never the address of an inline definition.
- A call to an inline function made through a pointer to the
externally-callable definition may still be inlined, or translated as a
call to an inline definition, if the compiler can determine the name of
the function whose address was stored in the pointer.
- intermixed declarations and code, "for" loop declarations (C9X and
gcc)
The C++ language has always allowed these, and they are now
being added to C. The rules are the same as for C++. Within a compound
statement, statements and declarations may be freely interspersed. This
allows declarations to be placed nearer to their point of first use
without introducing additional nested compound statements. And in
the
for
statement, the first clause may be a declaration whose scope includes
the remaining clauses of the
for
header and the entire loop body. This is normally used to declare and
initialize a local loop control variable, e.g.
for (int i=0; i<10; i++)
printf("%d\n", i);
|
- __func__ predeclared identifier (C9X and gcc)
Anywhere within
the body of a function definition, code can assume that there is
visible an identifier named __func__ that is declared as a static array
of char initialized with the spelling of the function's name. E.g a
function defined as
void foo(void) {printf("%s\n", __func__);}
|
will print "foo".
- compound literals (C9X and gcc)
A compound literal is a new
form of expression that constructs the value of an object, including
objects of array, struct, or union type. In C89, passing a struct value
to a function typically involves declaring a named object of the type,
initializing its members, and passing that object to the function. A
compound literal is an unnamed object specified by syntax consisting of
a parenthesized type name (i.e. the same syntax as a cast operator)
followed by a brace-enclosed list of initializers. Note that the
initializer list can use the recently-introduced designator syntax.
E.g. to construct an array of 1000 ints that are all zero except
for array element 5, which is to have a value of 7, you can write: (int
[1000]){[5] = 7}. A compound literal object is an lvalue. The
object it designates has static storage duration if it occurs outside
of all function definitions, and otherwise has automatic storage
duration associated with the nearest enclosing block.
- comment introducers optionally detected within comments, to help
find unterminated comments
The new message "nestedcomment" can be
enabled to report occurrences of "/*" inside of a comment introduced by
"/*". This often indicates that a terminating "*/" was omitted,
although certain coding practices may also produce many occurrences
that are harmless. The message is also enabled by enabling the
"level4", "unused", or "questcode" groups.
- __align synonym for _align (ANSI namespace)
The long-supported
_align storage class modifier is in the namespace reserved for users'
identifiers in some contexts under the C standard, and so it could not
be recognized as a keyword in strict ANSI mode (/standard=ansi89). An
alternate spelling with two leading underscores (putting it in the
namespace reserved to the C implementation) is now recognized in all
modes so that the feature can be used when compiling in strict ANSI
mode.
- __typeof__ unary operator (gcc)
The gcc compiler provides an
operator named "__typeof__" that can be used much like the standard C
operator "sizeof", except that instead of producing a value (the size
of an expression or type) it produces a type (the type of the
expression or type that is its single operand). It can be convenient to
use in macros for generating declarations or casts that use the same
type as some expression or typename supplied as an argument to the
macro.
- pointer arithmetic on void and function pointers (gcc)
Pointer
arithmetic on void* pointers or pointers to functions formerly produced
hard errors. The gcc compiler allows this, treating both as if they
were char* pointers. This behavior has been adopted, with an
appropriate warning instead of an error.
- string initializers optionally enclosed in parentheses (gcc)
In standard C, a string literal ordinarily has type char *. A
special case is made when a string literal is the initializer for an
array of char, in which case it is essentially treated as an array
object that provides the values (and, in the case of an incomplete
array, the size) of the array of char being initialized. Also in
standard C, a string literal enclosed in parentheses is not itself a
string literal, and so this special case would not apply - instead the
parenthesized literal would be treated as a single pointer of type char
*, which is not a valid initializer for an object of type array of
char. The gcc compiler allows a parenthesized string literal to
initialize a char array, and the construct commonly appears in Linux
source code. So that behavior has been adopted, with an appropriate
warning.
- difference of addresses in same object are constants (gcc)
If
the & operator is used to obtain the addresses of two lvalues
within the same object, and the lvalues are specified with integral
constant expressions, then the result depends only on the layout of the
object, and for practical purposes can be computed at compile time much
like the integral constant expressions that are required to be produced
by sizeof and offsetof. E.g. for any array "a" of int, the value of
&a[4] - &a[3] must be sizeof(int), and sizeof(int) is an
integral constant expression. But the C standard's specification of
expressions that must be treated by the compiler as integral constant
expressions does not include use of the & operator, and so
&a[4] - &a[3] is not required to be treated as such, and Compaq
C has not previously done so. But the C standard also explicitly
recognizes that implementations may treat additional forms of
expressions as constant expressions, and gcc and other compilers do
treat these cases as integral constant expressions. Now Compaq C does
as well.
7.3 New Features in DEC C V6.0
- New command line qualifier /[NO]PROTOTYPES:
/[NO]PROTOTYPES=(FILE=<filename>,
[NO]IDENTIFIERS,
[NO]STATIC_FUNCTIONS)
default is /[NO]PROTOTYPES
Syntax Description:
/[NO]PROTOTYPES
Creates an output file containing function
prototypes for all global functions defined in
the module which is being compiled.
keywords:
IDENTIFIERS
negatable optional parameter, which indicates
that identififer names are to be included in
the prototype declarations that appear in the
output file. The default is NOIDENTIFIERS
STATIC_FUNCTIONS
negatable optional parameter, which indicates
that prototypes for static function
definitions are to be included in the output
file. The default is NOSTATIC_FUNCTIONS
FILE=<filename>
an optional parameter specifying the output
file name. When not specified the output file
name will be have the same defaults as listing
file, except that the .CH file extension is
used instead of the .LIS extension.
|
- New command line qualifier,
/SHOW=MESSAGES
. This qualifier adds a new section to the listing file showing all of
the compiler's diagnostic messages that are enabled at the start of the
compilation, after the command line has been processed. The listing
shows the message identifer, the severity, and the parameterized text
of each enabled message, reflecting the effects of the /standard and
/warnings command line qualifiers (except that severity-based
suppression, /warnings=noinformationals or /nowarnings, is not
reflected). The /warnings=verbose qualifier causes this listing to be
expanded with the "Description" and "User Action" text following the
text for each enabled message.
- New informationals to report apparently unnecessary #include files
and CDD records. The most useful of these, UNUSEDTOP, reports only
headers explicitly #included at the top level in the compilation unit
that did not provide anything used by the rest of the compilation. This
message is enabled at level4. Other diagnostics to report on the
effects of #includes nested within other headers, and on CDD records,
are enabled at level5. All of these messages can be enabled by the
message group UNUSED. Unlike any other messages, these messages must be
enabled on the command line in order to be effective. The processing
that analyzes the dependencies on included files is signficant, and it
must be started before processing of the input files begins. Any
#pragma message directives within the source have no effect on these
messages, their state is determined only by processing the command line.
- The builtin function __ALLOCA(), which has been available on Alpha
since the earliest releases, has been implemented for VAX. Either
#include <builtins.h> or use #pragma builtins to enable it.
- Variable length arrays from the C9X review draft have been
implemented. This feature permits array objects with auto storage
class, and array typedefs declared at block scope, to have bounds that
are runtime-computed expressions. It also permits the declaration and
definition of functions whose parameters are arrays dimensioned by
other parameters (similar to Fortran assumed-shape arrays). The
following example illustrates both uses. Note that the definition of
function sub() uses prototype syntax and that the dimension parameters
precede the array parameter that uses them. In order to define a
function with the dimension parameters following the array parameter
that uses them, it is necessary to write the function definition using
K&R syntax (since that syntax allows the declarations of the types
of the parameters to be written in a different order from the
parameters themselves). K&R function definitions should generally
be avoided.
#include <stdio.h>
#include <stdlib.h>
void sub(int, int, int[*][*]);
int main(int argc, char **argv)
{
if (argc != 3) {
printf("Specify two array bound arguments.\n");
exit(EXIT_FAILURE);
}
{
int dim1 = atoi(argv[1]);
int dim2 = atoi(argv[2]);
int a[dim1][dim2];
int i, j, k = 0;
for (i = 0; i < dim1; i++) {
for (j = 0; j < dim2; j++) {
a[i][j] = k++;
}
}
printf("dim1 = %d, dim2 = %d.",
sizeof(a)/sizeof(a[0]),
sizeof(a[0])/sizeof(int));
sub(dim1, dim2, a);
sub(dim2, dim1, a);
}
exit(EXIT_SUCCESS);
}
void sub(int sub1, int sub2, int suba[sub1][sub2])
{
int i, j, k = 0;
printf("\nIn sub, sub1 = %d, sub2 = %d.",
sub1, sub2);
for (i = 0; i < sub1; i++) {
printf("\n");
for (j = 0; j < sub2; j++) {
printf("%4d", suba[i][j]);
}
}
}
|
Finally, note that variable length arrays can often be used in
place of the non-standard __ALLOCA() builtin function, an important
difference being that the storage allocated by __ALLOCA is not normally
freed until return from the function containing the call, while the
storage allocated for a variable length array is freed on exit from the
block in which it is allocated. If __ALLOCA is called within the scope
of a declaration for a variable length array object, an error is issued
(MIXALLOCAVLAV). On the Alpha platform, such usage produces a warning
and causes the storage allocated by __ALLOCA to be freed when the block
containing the variable length array declaration is exited.
|