PC-lint Plus supports several predefined macros including those defined by ISO C and those supported by various compilers. The special behavior of any of these macros will be removed for the remainder of the module if the macros are explicitly defined or undefined using #define or #undef and permanently removed if defined of undefined with the -d /+d /++d or -u /–u .
_lint – The special preprocessor symbol _lint is pre-defined with a value representing the version of
PC-lint Plus. The primary purpose of this symbol is to enable the programmer to determine whether
PC-lint Plus is processing the file.
For example, if you have a section of code that is unacceptable to PC-lint Plus for some reason (such
as in-line assembly code), you can use _lint to make sure that PC-lint Plus doesn’t see it. Thus,
#ifndef _lint ... Unacceptable coding sequence ... #endif
will cause PC-lint Plus to skip over the elided material.
The value of _lint is 1000 * Major Version Number + 10 * Minor Version number + the Patch Level.
| Version | Value of _lint |
| 1.4.1 | 1041 |
| 2.1 | 2010 |
| 2.2 | 2020 |
| 2025 | 2025000 |
E.g.
#if _lint >= 2020 // use Version 2.2 feature #endif #if _lint != 2010 // not for Version 2.1 #endif
__cplusplus – This symbol is defined for each module that is interpreted as being a C++ module and is otherwise undefined. The value that this symbol expands to is dependent on the C++ language mode: the value is 201402L for C++14, 201103L for C++11, and 199711L for C++03. C++ modules are determined by extension and possibly by option. See Chapter 3 The Command Line .
__COUNTER__ – This macro expands to an integer that automatically increments every time the macro is expanded within a module. The first result of the first expansion in a module is 0, the second expansion is 1, etc. When used with the ## operator, this macro provides a mechanism to generate unique identifiers.
__BASE_FILE__ – Expands to a string literal that contains the name of the module being processed, as the name was provided to PC-lint Plus.
__INCLUDE_LEVEL__ – Expands to a non-negative integer representing the #include nesting depth in which the macro appears. A value of 0 indicates a non-header location.
__TIMESTAMP__ – Expands to a string literal that contains the last modification date and time of the file in which the macro appears, as returned by the asctime function. If the modification time information cannot be determined, expands to the string literal "??? ??? ?? ??:??:?? ????".
The following pre-defined identifiers begin and end with double underscore and are ANSI/ISO compatible.
__TIME__ – The current time
__DATE__ – The current date
__FILE__ – The current file
__LINE__ – The current line number
__STDC__ – Defined to be 1.
__STDC_VERSION__ – This is undefined for C++. It is defined for C by default as ‘199901L’. If you
select
an earlier version of C using the -std option as in -std=c90 this will be undefined.
__STDC_HOSTED__ – This is defined whenever __STDC_VERSION__ is defined. When defined it is
defined
to be 0.
Compiler-dependent preprocessor symbols may also be established as described in Section 4.12 Compiler Adaptation .
When a #include "filename" directive is encountered
-idirectory
in the order in which the options were presented. If this fails we go to step 3.
If the include directive is of the form
#include <filename>
then the processing is the same except that step 1 is bypassed.
The INCLUDE environment variable may specify a search path in which to search for header files (#include files). For example:
set INCLUDE=b:\include;d:\extra
specifies that, should the search for a #include file within the current directory fail, a search will be made in the
directory b:\include and, on failing that, a search will be made in the directory d:\extra. This searching is done
for modules as well as #include files. You may select an environment variable other than INCLUDE. See the -incvar
option.
Notes:
ANSI/ISO preprocessing is assumed throughout. If the K&R preprocessor flag is set (+fkp ) the use of ANSI/ISO (over K&R) is flagged.
A C/C++ preprocessor may place #line directives within C/C++ source code so that compilers (and other static
analyzers such as PC-lint Plus) can know the original file and original line numbers that produced the text actually
being read. In this way, these processors can report errors in terms of the original file rather than in terms of the
intermediate text.
By default, #line directives are processed. To ignore #line directives use the option -fln . Some systems support # as an abbreviation for #line; these are treated equivalently by PC-lint Plus.
Preprocessor commands in this section need to be activated via the +ppw option. Also, their semantics may be copied via the ppw_asgn option.
This preprocessor directive is intended to support the Microsoft preprocessor directive of the same name. For example:
#import "c:\compiler\bin\x.lib"}
will determine the base name (in this case "x") and attempt to include, as a header file, basename.tlh. Thus, for linting purposes, this directive is equivalent to:
#include "x.tlh"
Options that may accompany #import are ignored. When the (Microsoft) compiler encounters a #import directive it
will generate an appropriate .tlh file if a current one does not already exist. PC-lint Plus will not generate this
file.
When compiling, it is possible to place the generated .tlh file in a directory other than the directory of the
importing file. If this option is chosen, then when linting, this other directory needs to be identified with a -i
option or equivalent.
This preprocessor word is not enabled by default. It can be enabled via the +ppw(import) option. This option has been placed into the various compiler options files for the Microsoft C/C++ compiler.
#include_next is supported for compatibility with the GNU C/C++ compiler. It uses the same arguments as
#include but starts the header file search in the directory just after the directory (in search order sequence) in
which the including file was found. See Section 18.2 include Processing for a specification of the search
order.
For example; suppose you place a file called stdio.h in a directory that is searched before the compiler’s directory. Thus you could intercept the #include of stdio.h and effectively augment its contents as follows:
stdio.h: #include_next <stdio.h> ... augmentation
This directive takes a single argument, a string constant. This directive will cause some compilers to copy the string into an implementation defined portion of the resulting object file. PC-lint Plus processes but ignores this directive.
This is treated identically to #ident.
The #warning directive is used by some compilers to emit a user-defined warning when the directive is reached during preprocessing. It is similar to #error but doesn’t terminate processing. If this keyword is enabled, PC-lint Plus will issue warning 490 along with the contents of the line that follows the #warning directive, in the same manner as for #error. In particular, the text that follows is emitted as written except that multiple space characters are collapsed into a single space and macros are not expanded. The text does not need to be a string constant. If your compiler calls this directive #warn, you can use
+ppw(warning) -ppw_asgn(warn, warning)
to cause PC-lint Plus to support the alternate spelling.
PC-lint Plus might stumble over strange preprocessor commands that your compiler happens to support. For
example, some Unix system compilers support #assert. Since this is something that can NOT be handled by a
suitable #define of some identifier we have added the +ppw(command-name) option (’ppw’ is an abbreviation for
PreProcessor Word). For example, +ppw(ident) will add the preprocessor command alluded to above. PC-lint Plus
recognizes and ignores the construct.
The non-standard use of sizeof in a preprocessor conditional is supported by some older and embedded compilers
but not directly supported by PC-lint Plus because the information necessary to evaluate a sizeof is not available
during the preprocessing phase. For portability reasons, such constructs should not be used in new code, favoring
static assertions or similar mechanisms instead.
For legacy code, we provide a work-around using the new -pp_sizeof(Text, Value) option that can be used to direct PC-lint Plus on how to evaluate a particular sizeof expression appearing in a preprocessor conditional. Text is the text of the expression appearing inside of the sizeof and Value is the integral value to apply to the evaluation of the sizeof expression. The new warning 2491 is issued when a preprocessor sizeof is encountered with an expression that has not been registered with -pp_sizeof. This message can be used to identify expressions that need to be registered as well as the text to use for Text. For example:
#if sizeof(int) < 4 #error "int is too small" #endif
will elicit:
test_ppsizeof.c 1 warning 677: sizeof used within preprocessor statement #if sizeof(int) < 4 ^ test_ppsizeof.c 1 warning 2491: unknown expression 'int' in sizeof will evaluate to 0, use -pp_sizeof to change the value used for evaluation test_ppsizeof.c 2 error 309: #error "int is too small" #error "int is too small" ^
The 677 message warns of the use of sizeof in the preprocessor, warning 2491 alerts the programmer that
PC-lint Plus doesn’t know how to handle sizeof(int) in the preprocessor and provides direction for using the
-pp_sizeof option. Message 309 is issued for the failed #error directive resulting from the fact that the unknown
sizeof expression was evaluated to be 0.
To employ the work-around, determine what the value of sizeof(int) is on the target platform and register the expression with -pp_sizeof. E.g. if int is 4 bytes, use -pp_sizeof(int, 4), which will cause the sizeof expression to be evaluated as expected. A separate -pp_sizeof option must be used for each expression that will appear inside of a preprocessor sizeof.