-------------------------------------------------- --- Manual Additions/Modifications --- -------------------------------------------------- PC-lint for C/C++ Version 7.50ad This read.me supplements the document entitled "Reference Manual for PC-lint/FlexeLint -- Version 7.5", Gimpel Software, Feb. 1998. ------ Additional Options ------ The following options have been added. o +fnn (new can return Null) (default ON) Turning this flag OFF yields a new that does not return NULL but throws a bad_alloc exception when it runs out of storage. This is to conform with the C++ standard. According to Standard C++, there are two built-in functions supporting operator new: void *operator new( size_t ) throw( std::bad_alloc ); void *operator new[]( size_t ) throw( std::bad_alloc ); Rather than return NULL when there is no more allocatable space, these functions throw an exception as shown. o #import 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. lint 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. 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 co-msc50.lnt compiler options file. o .DSP processing If you are using Microsoft Visual Studio, then an abstract of each project is retained in a file whose extension is .DSP. (Alternatively, for some variants of Visual Studio the extension .VCP is used and this extension too is supported.) Such a file is in Ascii and can be viewed with your editor. The file contains module names, defines of pre-processor variables, and include paths. lint is able to process such files extract such information as would be related to linting, transform the information to lint directives and output the result to standard output. The resulting file, provided it has a .LNT extension, can be used as input to lint. For example, the following creates a lint project file from a .dsp file. lint-nt project.dsp >project.lnt The .dsp file is, among other things, inspected for SOURCE= lines. These lines contain not only modules (C and C++) files but headers, resource files, text files, etc. lint, of course, just wants the modules. By default, we select out any file whose extension is ".c" and any file that bears a C++ extension. By default C++ extension are ".cpp" and ".cxx" but this list of extensions can be controlled via the -cpp option. Note that if a programmer had an unusual C extension it could be dubbed a C++ extension just for the purpose of file extraction. This gives the user complete control over which files are selected as modules. To control the flow of processing through the .dsp file you may use the +d option to set variables (the -d option should not be used as it is subject to later change). In particular, variable CFG can be set to affect the debug/release conditional within the .dsp file. Since the value of CFG bears blanks, you will need quotes as in: +d"CFG= ... " In order not to have the quotes peeled off by the command processor you will likely need to place this into a .lnt file. To gain some insight into how the translation is being done you may use the verbosity option to trigger a message for each line. Thus: lint-nt -v1 project.dsp >project.lnt will provide a line-by-line account of the translation. o +linebuf This option doubles the size of the line buffer which is initially 600 bytes. The line buffer is used to hold the current line and must be as long as the longest line in whatever file you are reading. Macro expansion does not affect this value. If a line exceeding this value is detected, Error 91 is issued and you will be prompted to use this option. There is no intrinsic limit to the number of times the line buffer can be doubled. The option can be placed in a file (specifically in a .lnt file). When the line buffer is reallocated the old buffer is not released so that information in the old buffer is still processed even though the line buffer is changing under foot. o --ppw(word) This option removes any predefined meaning we may associate with the word as a preprocessor word. If this is followed by a +ppw(word) the word is entered as a no-op rather than one that has a predefined meaning. This is a necessary supplement to our options -ppw(word) and +ppw(word) which disable and enable preprocessor words respectively but do not change any predefined meaning that the word may have. o -cgnu This option is used for the gnu compiler. It ensures that the symbol _LANGUAGE_C_PLUS_PLUS is defined for C++ modules and the symbol LANGUAGE_C is defined for C modules. (This is difficult to accomplish with just a compiler options file since compiler options files do not support conditionals. You would have to use -header and place a conditional within the header. This avoids the complexity). o @ support Compilers for embedded systems frequently use the @ notation to specify the location of a variable. A technique to handle this is given in our manual in section 5.8.2 in the description of -cwh. Users have encountered some difficulty with this method when the location is given as a complex expression. We have since added direct support for the @ feature which consists of ignoring expressions to its right. To enable this just make sure you are NOT using -cwh. We then give a warning (430) when we see a '@' which you may suppress with a -e430. o 'asm' functions Some compilers support in-line assembly functions with a syntax that resembles: asm void funcname( arguments ) { assembly-code assembly-code ... } To support this we have extended the meaning of the _ignore_init reserved word so that it will ignore function bodies as well as initializers. As usual, you have to enable the reserved word and you have to equate 'asm' to '_ignore_init'. These options respectively are: +rw(_ignore_init) -dasm=_ignore_init Note that to support the '$' sign in the assembly code, you need to use the -$ option as usual. o C++ Builder support The option +ftr (the TRuncate Flag) has been added. The effect of this flag is to truncate long include file names if the original filename does not seem to be valid. For example, consider the following. #include If algorithms.h cannot be opened using the usual search procedures, and if the Truncate flag is set (+ftr), then there will be an attempt to open the file 'algorith.h'. o -template(2) When a template refers to itself recursively we normally presume this to be a self-reference or a mistake and in order to prevent run-aways, recursion is normally prohibited. The option -template(2) can be used to activate recursive template processing. The Rogue Wave library, for example, employs recursive template evaluation to implement two to the power of N. Therefore, this option has been placed into the file: LIB-RW.LNT. ------ Additional Error Messages ------ 37 Value of enumerator 'Symbol' inconsistent (conflicts with Location) -- An enumerator was inconsistently valued. 38 Offset of symbol 'Symbol' inconsistent (conflicts with Location) -- A member of a class or struct appears in a different position (offset from the start of the structure) than an earlier declaration. This could be caused by array dimensions changing from one module to another. 91 Line exceeds Integer characters (use +linebuf) -- A line read from one of the input files is longer than anticipated. By default the line buffer size is 600 characters. By using the +linebuf option you can double this size. The size can be doubled ad infinitum. 92 Negative array dimension or bit field length (Integer) -- A negative array dimension or bit field length is not permitted. 93 New-line is not permitted within string arguments to macros -- A macro invocation contains a string that is split across more than one line. For example: A( "Hello World" ); will trigger this message. Some compilers accept this construct and you can suppress this message with -e93 if this is your current practice. But it is more portable to place the string constant on one line. Thus A( "Hello World" ); would be better. 145 Type expected before operator, void assumed -- In a context in which a type is expected no type is found. Rather, an operator '*' or '&'. The keyword void was assumed to have preceded this operator. 147 sizeof takes just one argument -- An expression of the form sizeof(a,b) was detected. A second argument is non standard and has been used by some compilers to denote an option to the sizeof operator. If your compiler has a use for the second argument then suppress this message. 155 Ignoring {...} sequence within an expression, 0 assumed -- A braced sequence within an expression is a non-standard extension of some compilers (in particular GCC). Internally, we treat such a braced sequence as the equivalent of a constant 0. This means that we may be able to quietly lint such constructions if you merely suppress the message. 430 Character '@', taken to specify variable location, is not standard C/C++ -- Many compilers for embedded systems have a declaration syntax that specifies a location in place of an initial value for a variable. For example: int x @0x2000; specifies that variable x is actually location 0x2000. This message is a reminder that this syntax is non-standard (although quite common). If you are using this syntax on purpose suppress this message. 434 White space ignored between back-slash and new-line -- According to the C and C++ standards, any back-slash followed immediately by a new-line results in the deletion of both characters. For example: #define A \ 34 defines A to be 34. If a blank or tab intervenes between the back-slash and the new-line then according to a strict interpretation of the standard you have defined A to be a back-slash. But this blank is invisible to the naked eye and hence could lead to confusion. Worse, some compilers silently ignore the white-space and the program becomes non-portable. You should never deliberately place a blank at the end of a line and any such blanks should be removed. If you really need to define a macro with a terminal back-slash you can use a comment as in: #define A \ /* commentary */ The message could also be issued when you have a single line comment ending in a backslash followed by white space. By the rules of C/C++ the next line is absorbed into the comment only if white space is absent, and hence the blank becomes an invisible active ingredient in the program which is not good for long-term sanity. 683 function 'Symbol' #define'd -- This message is issued whenever the name of a function with some semantic association is defined as a macro. For example: #define strlen mystrlen will raise this message. The message will be issued for built-in functions (with built-in semantics) or for user-defined semantics. The message will not be issued if the function is defined to be a function with a similar name but with underscores either appended or prepended or both. For example, #define strlen __strlen will not produce this message. It will produce Info 828 instead. 828 Semantics of function 'Symbol' copied to function 'Symbol' -- A function with built-in semantics or user-defined semantics was #define'd to be some other function with a similar name formed by prepending or appending underscores. For example: define strcmp(a,b) __strcmp__(a,b) will cause Info 828 to be issued. 909 Implicit conversion from Type to bool -- A non-bool was tested as a Boolean. For example, in the following function: int f(int n) { if( n ) return n; else return 0; } the programmer tests 'n' directly rather than using an explicit Boolean expression such as 'n != 0'. Some shops prefer the explicit test. 1077 Could not evaluate default template parameter 'String' -- The evaluation of template parameters is deferred until needed. Thus: template< class T = abc > class A { /* ... */ }; will be greeted with an Error 1077 only if an instantiation of A requires evaluation of the default argument and if that evaluation cannot be made. In that event int is assumed for type parameters and 0 is assumed for object parameters. 1080 Definition for class 'Name' is not in scope -- This message would be issued whenever a class definition were required and it were not available. For example: class X; // declare class X X *p; // OK, no definition required X a; // Error 1080 1553 struct 'Symbol' declared as extern "C" contains C++ substructure 'Symbol' (Location) -- A C++ substructure was found in a structure or class declared as extern "C". Was this intended? A C++ substructure may contain private data or virtual functions or inherited classes which cannot be rendered naturally in C. This may require special attention to get right and may be compiler dependent. 1776 Converting string literals to char * is deprecated (Context) -- A string literal, according to Standard C++ is typed an array of const char. This message is issued when such a literal is assigned to a non-const pointer. For example: char *p = "string"; will trigger this message. This pointer could then be used to modify the string literal and that could produce some very strange behavior. Such an assignent is legal but "deprecated" by the C++ Standard. The reason for not ruling it illegal is that numerous existing functions have their arguments typed as char * and this would break working code. Note that this message is only given for string literals. If an expression is typed as pointer to const char in some way other than via string literal, then an assignment of that pointer to a non-const pointer will receive a more severe warning. 1561 Reference initialization causes loss of const/volatile integrity (Context) -- A reference initialization is resulting in a capability gain that can cause a loss of const or volatile integrity. Typically the message is given on initializing a non-const reference with a const. For example: void f( int &x ); const int n = 0; ... f(n); Here, function f() could assign a value to its argument and thereby modify n which is declared to be const. The message can also be issued when a pointer is initialized. Consider the following example. void h( const int *&q ); int *p; ... h(p); It might seem that passing a regular (i.e., non-const) pointer to a const int * could cause no harm. That would be correct if it were not for the reference. If function h() were to assign a pointer to const to its parameter q then upon return from the call, p could be used to modify const data. There are many subtle cases that can boggle the mind. See the commentary to Message 605. Gimpel Software May 2001