-qlanglvl

Description

Selects the language level and language options for the compilation.

Syntax

Read syntax diagramSkip visual syntax diagram                    .-:---------.
                    V           |
>>- -q--langlvl--=----suboption-+------------------------------><

where values for suboption are described below in the Notes section.

See also #pragma langlvl and #pragma options.

Default

The default language level varies according to the command you use to invoke the compiler:

Invocation
Default language level
xlC/xlc++
extended
xlc
extc89
cc
extended
c89
stdc89
c99
stdc99

Notes

C only You can also use either of the following pragma directives to specify the language level in your C language source program:

#pragma options langlvl=suboption
#pragma langlvl(suboption)

The pragma directive must appear before any noncommentary lines in the source code.

C only For C programs, you can use the following -qlanglvl suboptions for suboption:

classic Allows the compilation of non-stdc89 programs, and conforms closely to the K&R level preprocessor. This language level is not supported by the AIX(R) v5.1 and higher system header files, such as math.h. If you must use the AIX v5.1 or higher system header files, consider compiling your program to the stdc89 or extended language levels.
extended Provides compatibility with the RT compiler and classic. This language level is based on C89.
saa Compilation conforms to the current SAA(R) C CPI language definition. This is currently SAA C Level 2.
saal2 Compilation conforms to the SAA C Level 2 CPI language definition, with some exceptions.
stdc89 Compilation conforms to the ANSI C89 standard, also known as ISO C90.
stdc99 Compilation conforms to the ISO C99 standard.
Note:
Not all operating system releases support the header files and runtime library required by C99.
extc89 Compilation conforms to the ANSI C89 standard, and accepts implementation-specific language extensions.
extc99 Compilation conforms to the ISO C99 standard, and accepts implementation-specific language extensions.
Note:
Not all operating system releases support the header files and runtime library required by C99.
[no]ucs Under language levels stdc99 and extc99, the default is -qlanglvl=ucs

This option controls whether Unicode characters are allowed in identifiers, string literals and character literals in program source code.

The Unicode character set is supported by the C standard. This character set contains the full set of letters, digits and other characters used by a wide range of languages, including all North American and Western European languages. Unicode characters can be 16 or 32 bits. The ASCII one-byte characters are a subset of the Unicode character set.

When this option is set to yes, you can insert Unicode characters in your source files either directly or using a notation that is similar to escape sequences. Because many Unicode characters cannot be displayed on the screen or entered from the keyboard, the latter approach is usually preferred. Notation forms for Unicode characters are \uhhhh for 16-bit characters, or \Uhhhhhhhh for 32-bit characters, where h represents a hexadecimal digit. Short identifiers of characters are specified by ISO/IEC 10646.

The following -qlanglvl suboptions are accepted but ignored by the C compiler. Use -qlanglvl=extended, -qlanglvl=extc99, or -qlanglvl=extc89 to enable the functions that these suboptions imply. For other values of -qlanglvl, the functions implied by these suboptions are disabled.

[no]gnu_assert GNU C portability option.
[no]gnu_explicitregvar GNU C portability option.
[no]gnu_include_next GNU C portability option.
[no]gnu_locallabel GNU C portability option.
[no]gnu_warning GNU C portability option.

C++ only For C++ programs, you can specify one or more of the following -qlanglvl suboptions for suboption:

compat366 Compilation conforms to some, but not all, IBM C and C++ Compilers V 3.6 features.
extended Compilation is based on the strict98, with some differences to accommodate extended language features.
strict98 Compilation conforms to the ISO C++ standard for C++ programs.
[no]anonstruct This suboption controls whether anonymous structs and anonymous classes are allowed in your C++ source.

By default, the compiler allows anonymous structs. This is an extension to the C++ standard and gives behavior that is compatible with the C++ compilers provided by Microsoft(R) Visual C++.

Anonymous structs typically are used in unions, as in the following code fragment:

union U {
   struct {
      int i:16;
      int j:16;
   };
   int k;
} u;
// ...
u.j=3;

When this suboption is set, you receive a warning if your code declares an anonymous struct and -qinfo=por is specified. When you build with -qlanglvl=noanonstruct, an anonymous struct is flagged as an error. Specify noanonstruct for compliance with standard C++.

[no]anonunion This suboption controls what members are allowed in anonymous unions.

When this suboption is set to anonunion, anonymous unions can have members of all types that standard C++ allows in non-anonymous unions. For example, non-data members, such as structs, typedefs, and enumerations are allowed.

Member functions, virtual functions, or objects of classes that have non-trivial default constructors, copy constructors, or destructors cannot be members of a union, regardless of the setting of this option.

By default, the compiler allows non-data members in anonymous unions. This is an extension to standard C++ and gives behavior that is compatible with the C++ compilers provided by previous versions of VisualAge(R) C++ and predecessor products, and Microsoft Visual C++.

When this option is set to anonunion, you receive a warning if your code uses the extension, unless you suppress the arning message with the -qsuppress option.

Set noanonunion for compliance with standard C++.

[no]ansifor This suboption controls whether scope rules defined in the C++ standard apply to names declared in for-init statements.

By default, standard C++ rules are used. For example the following code causes a name lookup error:

{
   //...
   for (int i=1; i<5; i++) {
      cout << i * 2 << endl;
   }
   i = 10;  // error
}

The reason for the error is that i, or any name declared within a for-init-statement, is visible only within the for statement. To correct the error, either declare i outside the loop or set ansiForStatementScopes to no.

Set noansifor to allow old language behavior. You may need to do this for code that was developed with other products, such as the compilers provided by earlier versions of VisualAge C++ and predecessor products, and Microsoft Visual C++.

[no]ansisinit This suboption can be used to select between old (v3.6 or earlier) and current (v5.0 or later) compiler object compatibility.

This suboption is useful for building an application that includes an existing shared library originally built with a v3.6 or earlier version of the IBM C/C++ Compilers. Specifying the noansisinit suboption ensures that the behavior of global (including static locals) objects with destructors in your newly-compiled objects are compatible with objects built with earlier compilers. The default setting is ansisinit.

[no]c99__func__ This suboption instructs the compiler to recognize the C99 __func__ identifier. The __func__ identifier behaves as if there is an implicit declaration like:
static const char __func__[] = function_name;
where function_name is the name of the function in which the __func__ identifier appears.

The effect of the __func__ identifier can be seen in the following code segment:

void this_function()
{
 printf("__func__ appears in %s", __func__);
}

which outputs the following when run:

__func__ appears in this_function

The c99__func__ suboption is enabled by default when -qlanglvl=extended is in effect. It can be enabled for any language level by specifying -qlanglvl=c99__func__, or disabled by specifying -qlanglvl=noc99__func__.

The __C99__FUNC__ macro is defined to be 1 when c99__func__ is in effect, and is undefined otherwise.

[no]c99complex This suboption instructs the compiler to recognize C99 complex data types and related keywords.
Note:
Support for complex data types may vary among different C++ compilers, creating potential portability issues. The compiler will issue a portability warning message if you specify this compiler option together with -qinfo=por.
[no]c99complexheader This suboption instructs the compiler to use the C99 complex.h header file.
[no]c99compoundliteral This suboption instructs the compiler to support the C99 compound literal feature.
[no]c99hexfloat This option enables support for C99-style hexadecimal floating constants in C++ applications. This suboption is on by default for -qlanglvl=extended. When it is in effect, the compiler defines the macro __C99_HEX_FLOAT_CONST .
[no]c99vla When c99vla is in effect, the compiler will support the use of C99-type variable length arrays in your C++ applications. The macro __C99_VARIABLE_LENGTH_ARRAY is defined with a value of 1.
Note:
In C++ applications, storage allocated for use by variable length arrays is not released until the function they reside in completes execution.
[no]compatzea The default is -qlanglvl=nocompatzea. Specifying -qlanglvl=compatzea has effect only if -qlanglvl=zeroextarray is also in effect.

Prior to XL C/C++ V7.0 for AIX, zero extent arrays on AIX had an underlying dimension of 1. Applying the sizeof operator to a zero extent array would return 1 times the size of its element type.

Starting with XL C/C++ v7.0 for AIX, the underlying dimension of zero extent arrays will change to support an underlying dimension of 0.

This change can influence the behavior of existing code. The -qlanglvl=compatzeaoption is a compatibility option that lets you continue to use a zero extent array with dimension of 1 in AIX applications compiled with XL C/C++ V7.0 for AIX.

[no]dependentbaselookup The default is -qlanglvl=dependentbaselookup.

This suboption provides the ability to specify compilation in conformance with Issue 213 of TC1 of the C++ Standard.

The default setting retains the behavior of previous XL C/C++ compilers with regard to the name lookup for a template base class of dependent type: a member of a base class that is a dependent type hides a name declared within a template or any name from within the enclosing scope of the template.

For compliance with TC1, specify -qlanglvl=nodependentbaselookup.

[no]gnu_assert GNU C portability option to enable or disable support for the following GNU C system identification assertions:
  • #assert
  • #unassert
  • #cpu
  • #machine
  • #system
[no]gnu_complex This suboption instructs the compiler to recognize GNU complex data types and related keywords.
Note:
Support for complex data types may vary among different C++ compilers, creating potential portability issues. The compiler will issue a portability warning message if you specify this compiler option together with -qinfo=por.
[no]gnu_computedgoto GNU C portability option to enable support for computed gotos. This suboption is enabled for -qlanglvl=extended, and defines the macro __IBM_COMPUTED_GOTO.
[no]gnu_explicitregvar GNU C portability option to control whether the compiler accepts and ignores the specification of explicit registers for variables.
[no]gnu_externtemplate This suboption enables or disables extern template instantiations.

The default setting is gnu_externtemplate when compiling to the extended language level, and nognu_externtemplate when compiling to the strict98 or compat366 language levels.

If gnu_externtemplate is in effect, you can declare a template instantiation to be extern by adding the keyword extern in front of an explicit C++ template instantiation. The extern keyword must be the first keyword in the declaration, and there can be only one extern keyword.

This does not instantiate the class or function. For both classes and functions, the extern template instantiation will prevent instantiation of parts of the template, provided that instantiation has not already been triggered by code prior to the extern template instantiation, and it is not explicitly instantiated nor explicitly specialized.

For classes, static data members and member functions will not be instantiated, but a class itself will be instantiated if required to map the class. Any required compiler generated functions (for example, default copy constructor) will be instantiated. For functions, the prototype will be instantiated but the body of the template function will not.

See the following examples:

template < class T > class C {
  static int i;
  void f(T) { }
};

template < class U > int C<U>::i = 0;
extern template class C<int>; // extern explicit 
                              // template
                              // instantiation
C<int> c;  // does not cause instantiation of
           // C<int>::i  or C<int>::f(int) in 
           // this file but class is 
           // instantiated for mapping
C<char> d; // normal instantiations

==========================

template < class C > C foo(C c) { return c; }

extern template int foo<int>(int); // extern explicit 
                                   // template
                                   // instantiation
int i = foo(1);    // does not cause instantiation 
                   // of body of foo<int>
 
[no]gnu_include_next GNU C portability option to enable or disable support for the GNU C #include_next preprocessor directive.
[no]gnu_labelvalue GNU C portability option to enable or disable support for labels as values. This suboption is on by default for -qlanglvl=extended, and defines the macro __IBM_LABEL_VALUE.
[no]gnu_locallabel GNU C portability option to enable or disable support for locally-declared labels.
gnu_membernamereuse GNU C++ portability option to enable reusing a template name in a member list as a typedef.
[no]gnu_suffixij GNU C portability option to enable or disable support for GNU-style complex numbers. If gnu_suffixij is specified, a complex number can be ended with suffix i/I or j/J.
[no]gnu_varargmacros This option is similar to -qlanglvl=varargmacros. The main differences are:
  • An optional variable argument identifier may precede the ellipsis, allowing that identifier to be used in place of the macro __VA_ARGS__ . Whitespace may appear between the identifier and the ellipsis.
  • The variable argument can be omitted.
  • If the token paste operator (##) appears between the comma and the variable argument, the preprocessor removes the dangling comma (,) if the variable argument is not provided.
  • The macro __IBM_MACRO_WITH_VA_ARGS is defined to 1.

Example 1 - Simple substitution:

#define debug(format, args...) printf(format, args)

debug("Hello %s\n", "Chris");     

preprocesses to:

printf("Hello %s\n", "Chris");     

Example 2 - Omitting the variable argument:

#define debug(format, args...) printf(format, args)

debug("Hello\n");       

preprocesses to the following, leaving a dangling comma:

printf("Hello\n",);    

Example 3 - Using the token paste operator to remove a dangling comma when the variable argument is omitted:

#define debug(format, args...) printf(format, ## args)

debug("Hello\n");       

preprocesses to:

printf("Hello\n");    
[no]gnu_warning GNU C portability option to enable or disable support for the GNU C #warning preprocessor directive.
[no]illptom This suboption controls what expressions can be used to form pointers to members. The XL C++ compiler can accept some forms that are in common use but do not conform to the C++ Standard.

By default, the compiler allows these forms. This is an extension to standard C++ and gives behavior that is compatible with the C++ compilers provided by earlier versions of VisualAge C++, its predecessor products, and Microsoft Visual C++.

When this suboption is set to illptom, you receive warnings if your code uses the extension, unless you suppress the warning messages with the -qsuppress option.

For example, the following code defines a pointer to a function member, p, and initializes it to the address of C::foo, in the old style:

struct C {
void foo(int);
};

void (C::*p) (int) = C::foo;

Set noillptom for compliance with the C++ standard. The example code above must be modified to use the & operator.

struct C {
void foo(int);
};

void (C::*p) (int) = &C::foo;
[no]implicitint This suboption controls whether the compiler will accept missing or partially specified types as implicitly specifying int. This is no longer accepted in the standard but may exist in legacy code.

With the suboption set to noimplicitint, all types must be fully specified.

With the suboption set to implicitint, a function declaration at namespace scope or in a member list will implicitly be declared to return int. Also, any declaration specifier sequence that does not completely specify a type will implicitly specify an integer type. Note that the effect is as if the int specifier were present. This means that the specifier const, by itself, would specify a constant integer.

The following specifiers do not completely specify a type.

  • auto
  • const
  • extern
  • extern "<literal>"
  • inline
  • mutable
  • friend
  • register
  • static
  • typedef
  • virtual
  • volatile
  • platform specific types (for example, _cdecl)

Note that any situation where a type is specified is affected by this suboption. This includes, for example, template and parameter types, exception specifications, types in expressions (eg, casts, dynamic_cast, new), and types for conversion functions.

By default, the compiler sets -qlanglvl=implicitint. This is an extension to the C++ standard and gives behavior that is compatible with the C++ compilers provided by earlier versions of VisualAge C++ and predecessor products, and Microsoft Visual C++.

For example, the return type of function MyFunction is int because it was omitted in the following code:

MyFunction()
{
   return 0;
}

Set -qlanglvl=noimplicitint for compliance with standard C++. For example, the function declaration above must be modified to:

int MyFunction()
{
   return 0;
}
[no]newexcp This suboption determines whether or not the C++ new operator throws an exception. If the -qlanglvl=newexcp option is specified, the standard exception std::bad_alloc is thrown when the requested memory allocation fails. This option does not apply to the nothrow versions of the new operator.

Class-specific new operators and new operators with placement arguments are not affected by this option.

The standard implementation of the new operators fully support exceptions. For compatibility with previous versions of VisualAge C++, these operators return 0 by default.

[no]offsetnonpod This suboption controls whether the offsetof macro can be applied to classes that are not data-only. C++ programmers often casually call data-only classes "Plain Old Data" (POD) classes.

By default, the compiler allows offsetof to be used with non-POD classes. This is an extension to the C++ standard, and gives behavior that is compatible with the C++ compilers provided by VisualAge C++ for OS/2(R) 3.0, VisualAge for C++ for Windows(R), Version 3.5, and Microsoft Visual C++

When this option is set, you receive a warning if your code uses the extension, unless you suppress the warning message with the -qsuppress option.

Set -qlanglvl=nooffsetnonpod for compliance with standard C++.

Set -qlanglvl=offsetnonpod if your code applies offsetof to a class that contains one of the following:

  • user-declared constructors or destructors
  • user-declared assignment operators
  • private or protected non-static data members
  • base classes
  • virtual functions
  • non-static data members of type pointer to member
  • a struct or union that has non-data members
  • references
[no]olddigraph This option controls whether old-style digraphs are allowed in your C++ source. It applies only when -qdigraph is also set.

By default, the compiler supports only the digraphs specified in the C++ standard.

Set -qlanglvl=olddigraph if your code contains at least one of following digraphs:

Digraph
Resulting Character
%%
# (pound sign)
%%%%
## (double pound sign, used as the preprocessor macro concatenation operator)

Set -qlanglvl=noolddigraph for compatibility with standard C++ and the extended C++ language level supported by previous versions of VisualAge C++ and predecessor products.

[no]oldfriend This option controls whether friend declarations that name classes without elaborated class names are treated as C++ errors.

By default, the compiler lets you declare a friend class without elaborating the name of the class with the keyword class. This is an extension to the C++ standard and gives behavior that is compatible with the C++ compilers provided by earlier versions of VisualAge C++ and predecessor products, and Microsoft Visual C++.

For example, the statement below declares the class IFont to be a friend class and is valid when the oldfriend suboption is set specified.

friend IFont;

Set the nooldfriend suboption for compliance with standard C++. The example declaration above causes a warning unless you modify it to the statement as below, or suppress the warning message with -qsuppress option.

friend class IFont;
[no]oldmath This suboption controls which versions of math function declarations in <math.h> are included when you specify math.h as an included or primary source file.

By default, the new standard math functions are used. Build with -qlanglvl=nooldmath for strict compliance with the C++ standard.

For compatibility with modules that were built with earlier versions of VisualAge C++ and predecessor products you may need to build with -qlanglvl=oldmath.

[no]oldtempacc This suboption controls whether access to a copy constructor to create a temporary object is always checked, even if creation of the temporary object is avoided.

By default, the compiler suppresses the access checking. This is an extension to the C++ standard and gives behavior that is compatible with the C++ compilers provided by VisualAge C++ for OS/2(R) 3.0, VisualAge for C++ for Windows, Version 3.5, and Microsoft Visual C++.

When this suboption is set to yes, you receive a warning if your code uses the extension, unless you disable the warning message with the -qsuppress option.

Set -qlanglvl=nooldtempacc for compliance with standard C++. For example, the throw statement in the following code causes an error because the copy constructor is a protected member of class C:

class C {
public:
   C(char *);
protected:
   C(const C&);
};

C foo() {return C("test");} // return copy of C object 
void f()
{
// catch and throw both make implicit copies of
// the thrown object
   throw C("error");   // throw a copy of a C object
   const C& r = foo(); // use the copy of a C object 
//                              created by foo()
}

The example code above contains three ill formed uses of the copy constructor C(const C&).

[no]oldtmplalign This suboption specifies the alignment rules implemented in versions of the compiler (xlC) prior to Version 5.0. These earlier versions of the xlC compiler ignore alignment rules specified for nested templates. By default, these alignment rules are not ignored in VisualAge C++ 4.0 or later. For example, given the following template the size of A<char>::B will be 5 with -qlanglvl=nooldtmplalign, and 8 with -qlanglvl=oldtmplalign :
template <class T>
struct A {
#pragma options align=packed
 struct B {
  T m;
  int m2;
 };
#pragma options align=reset
};
[no]oldtmplspec This suboption controls whether template specializations that do not conform to the C++ standard are allowed.

By default, the compiler allows these old specializations (-qlanglvl=nooldtmplspec). This is an extension to standard C++ and gives behavior that is compatible with the C++ compilers provided by VisualAge C++ for OS/2 3.0, VisualAge for C++ for Windows, Version 3.5, and Microsoft Visual C++.

When -qlanglvl=oldtmplspec is set, you receive a warning if your code uses the extension, unless you suppress the warning message with the -qsuppress option.

For example, you can explicitly specialize the template class ribbon for type char with the following lines:

template<class T> class ribbon { /*...*/};
class ribbon<char> { /*...*/};

Set -qlanglvl=nooldtmplspec for compliance with standard C++. In the example above, the template specialization must be modified to:

template<class T> class ribbon { /*...*/};
template<> class ribbon<char> { /*...*/};
[no]redefmac Specifies whether a macro can be redefined without a prior #undef or undefine() statement.
[no]trailenum This suboption controls whether trailing commas are allowed in enum declarations.

By default, the compiler allows one or more trailing commas at the end of the enumerator list. This is an extension to the C++ standard, and provides compatibility with Microsoft Visual C++. The following enum declaration uses this extension:

enum grain { wheat, barley, rye,, };

Set -qlanglvl=notrailenum for compliance with standard C++ or with the stdc89 language level supported by previous versions of VisualAge C++ and predecessor products.

[no]typedefclass This suboption provides backwards compatibility with previous versions of VisualAge C++ and predecessor products.

The current C++ standard does not allow a typedef name to be specified where a class name is expected. This option relaxes that restriction. Set -qlanglvl=typedefclass to allow the use of typedef names in base specifiers and constructor initializer lists.

By default, a typedef name cannot be specified where a class name is expected.

[no]ucs This suboption controls whether Unicode characters are allowed in identifiers, string literals and character literals in C++ sources. The default setting is -qlanglvl=noucs.

The Unicode character set is supported by the C++ standard. This character set contains the full set of letters, digits and other characters used by a wide range of languages, including all North American and Western European languages. Unicode characters can be 16 or 32 bits. The ASCII one-byte characters are a subset of the Unicode character set.

When -qlanglvl=ucs is enabled, you can insert Unicode characters in your source files either directly or using a notation that is similar to escape sequences. Because many Unicode characters cannot be displayed on the screen or entered from the keyboard, the latter approach is usually preferred. Notation forms for Unicode characters are \uhhhh for 16-bit characters, or \Uhhhhhhhh for 32-bit characters, where h represents a hexadecimal digit. Short identifiers of characters are specified by ISO/IEC 10646.

[no]varargmacros This C99 feature allows the use of a variable argument list in function-like macros in your C++ applications. The syntax is similar to a variable argument function, and can be used as a masking macro for printf.

For example:

#define debug(format, ...) printf(format, __VA_ARGS__)

debug("Hello %s\n", "Chris"); 

preprocesses to::

printf("Hello %s\n", "Chris"); 

The token __VA_ARGS__ in the replacement list corresponds to the ellipsis in the parameter. The ellipsis represents the variable arguments in a macro invocation.

Specifying varargmacros defines the macro __C99_MACRO_WITH_VA_ARGS to a value of 1.

[no]zeroextarray This suboption controls whether zero-extent arrays are allowed as the last non-static data member in a class definition.

By default, the compiler allows arrays with zero elements. This is an extension to the C++ standard, and provides compatibility with Microsoft Visual C++. The example declarations below define dimensionless arrays a and b.

struct S1 { char a[0]; };
struct S2 { char b[]; };

Set nozeroextarray for compliance with standard C++ or with the ANSI language level supported by previous versions of VisualAge C++ and predecessor products.

 

Exceptions to the stdc89 mode addressed by classic are as follows:

Tokenization Tokens introduced by macro expansion may be combined with adjacent tokens in some cases. Historically, this was an artifact of the text-based implementations of older preprocessors, and because, in older implementations, the preprocessor was a separate program whose output was passed on to the compiler.

For similar reasons, tokens separated only by a comment may also be combined to form a single token. Here is a summary of how tokenization of a program compiled in classic mode is performed:

  1. At a given point in the source file, the next token is the longest sequence of characters that can possibly form a token. For example, i+++++j is tokenized as i ++ ++ + j even though i ++ + ++ j may have resulted in a correct program.
  2. If the token formed is an identifier and a macro name, the macro is replaced by the text of the tokens specified on its #define directive. Each parameter is replaced by the text of the corresponding argument. Comments are removed from both the arguments and the macro text.
  3. Scanning is resumed at the first step from the point at which the macro was replaced, as if it were part of the original program.
  4. When the entire program has been preprocessed, the result is scanned again by the compiler as in the first step. The second and third steps do not apply here since there will be no macros to replace. Constructs generated by the first three steps that resemble preprocessing directives are not processed as such.

It is in the third and fourth steps that the text of adjacent but previously separate tokens may be combined to form new tokens.

The \ character for line continuation is accepted only in string and character literals and on preprocessing directives.

Constructs such as:

#if 0
  "unterminated
#endif
#define US "Unterminating string
char *s = US terminated now"

will not generate diagnostic messages, since the first is an unterminated literal in a FALSE block, and the second is completed after macro expansion. However:

char *s = US;

will generate a diagnostic message since the string literal in US is not completed before the end of the line.

Empty character literals are allowed. The value of the literal is zero.

Preprocessing directives The # token must appear in the first column of the line. The token immediately following # is available for macro expansion. The line can be continued with \ only if the name of the directive and, in the following example, the ( has been seen:
#define f(a,b) a+b
f\
(1,2)      /* accepted */
#define f(a,b) a+b
f(\
1,2)       /* not accepted */

The rules concerning \ apply whether or not the directive is valid. For example,

#\
define M 1   /* not allowed */
#def\
ine M 1      /* not allowed */
#define\
M 1          /* allowed */
#dfine\
M 1          /* equivalent to #dfine M 1, even
                   though #dfine is not valid  */

Following are the preprocessor directive differences between classic mode and stdc89 mode. Directives not listed here behave similarly in both modes.

#ifdef/#ifndef
When the first token is not an identifier, no diagnostic message is generated, and the condition is FALSE.
#else
When there are extra tokens, no diagnostic message is generated.
#endif
When there are extra tokens, no diagnostic message is generated.
#include
The < and > are separate tokens. The header is formed by combining the spelling of the < and > with the tokens between them. Therefore /* and // are recognized as comments (and are always stripped), and the " and ' do begin literals within the < and >. (Remember that in C programs, C++-style comments // are recognized when -qcpluscmt is specified.)
#line
The spelling of all tokens which are not part of the line number form the new file name. These tokens need not be string literals.
#error
Not recognized in classic mode.
#define
A valid macro parameter list consists of zero or more identifiers each separated by commas. The commas are ignored and the parameter list is constructed as if they were not specified. The parameter names need not be unique. If there is a conflict, the last name specified is recognized.

For an invalid parameter list, a warning is issued. If a macro name is redefined with a new definition, a warning will be issued and the new definition used.

#undef
When there are extra tokens, no diagnostic message is generated.
Macro expansion
  • When the number of arguments on a macro invocation does not match the number of parameters, a warning is issued.
  • If the ( token is present after the macro name of a function-like macro, it is treated as too few arguments (as above) and a warning is issued.
  • Parameters are replaced in string literals and character literals.
  • Examples:
    #define M()    1
    #define N(a)   (a)
    #define O(a,b) ((a) + (b))
    M();  /* no error */
    N();  /* empty argument */
    O();  /* empty first argument 
                and too few arguments */
Text Output No text is generated to replace comments.

Related information