** This is our Bug Fix list for Patches to ** ** PC-lint / FlexeLint Version 8.00 ** *************** Version 8.00x 5/30/2008 *************** * There was a scenario in which the use of +macros on the command line could be coming too late to serve and that would be when a LINT environment variable, which takes precedence over the command line, requires it. This was fixed so that +macros on the command line get priority attention. MALE, 7/30/07 * When an enumeration type is made a strong type we could crash in some scenarios involving the typedef appearing separately from the underlying enumeration. NWMS, 8/14/07 * There was an outside chance that a second module would think that a class did not have members when it really did. The class in question was a template class embedded in a template class RPUS, 8/14/07 * We were complaining about a type mismatch for a default argument of a member function when the argument was a literal 0L. TMDA, 8/15/07 * We issued a spurious type redeclaration warning (452) when processing struct A below: typedef struct { struct S {} m; } B; struct A { A(B); }; CUCE, 8/20/07 * Our messages 604 and 789 which report when auto's bind to references has been fixed to include parameters. RBRI, 8/22/07 * A number of fixes were made to curly brace initializer processing. An undefined struct could cause an infinite loop; also, data-memberless struct's need curly braces with nothing in them rather than plain nothingness. UTIL, 9/4/07 * When an expression used as an initializer for a struct type did not begin with an identifier, an undeserved type mismatch could result. EETM, 9/5/07 * We were issuing an unjustified Warning 633 when passing an argument typed as a strong Bool to a parameter typed const Bool CSBP, 9/14/07 * A crash could occur under unusual circumstances always involving a default value for a member function argument. E.g. class A { A( char *dir="" ); }; A::A( char *dir ) {} NEDA, 10/4/07 * A using declaration could lead to a corrupt lob. CLEU, 10/25/07 * We were not handling the string arguments properly when it came to semantic constraints. For example, //lint -sem( f, 1P < 4 ) ... f( "abcde" ); was not drawing the proper complaint. NULS, 11/1/07 * Treating non-type template parameters were flawed in many cases. In particular non-type template arguments were not being converted to the types of their corresponding parameters. ACNA, 11/8/07 * We no longer believe that passing a NULL pointer to fflush is bad practice. FANP, 11/13/07 * When a definition of a function appeared in a library header and this function was passed a strong type and the strong type used the flag sequence 'Xl' the strong type mismatch was not suppressed as it should have been. LFNL, 11/13/07 * We were not issuing Info 701 (shift left of signed quantity) when the value being shifted had no sign but would have a sign after the shift. We now issue a 701 for: (unsigned short) n << 16 SIRT, 11/14/07 * A Specific Walk does not give some of the end-of-block messages for the outer block of a function with an implied return NCIR, 11/19/07 * When processing a default argument within a member function of a class which is represented by a macro which had been emacro'ed led to an incorrect synchronization of -save -restore states. PLCP, 11/30/07 * We lost some pointer information when the -epp option was used. For example, int k; ... memset( &k, 0, sizeof(k) ); results in Warning 419: Apparent data overrun, 4 bytes vs. 1 byte. EMUP, 11/30/07 * When the address of an overloaded function was taken and the functions were declared in different scopes and the address was passed to an overloaded operator we could issue Error 64 NUOB, 11/30/07 * We were not issuing return mode incompatibility for some namespace functions. E.g. namespace Q { int f(){} } A complaint is now issued about the lack of a return statement. ICRM, 12/4/07 * We now report on, as suspicious, any option of the form -x(y)z where z is non null except for known options where this is expected. ASIT, 12/7/07 * A user could accidentally imply all errors with a misplaced comma. For example -e{58,} would inhibit all messages in the next statement. The null inhibition pattern now properly implies no messages. NEPA, 12/7/07 * (Microsoft compiler) Our built-in fake function ___type_traits() had been mistyped as returning void. It now correctly returns bool. TSRB, 12/11/07 * Uses of operator= in derived classes could result in problems with lob's. IAEL, 12/11/07 * (Microsoft compiler) Visual Studio 2008 headers have constructors whose declarations use attributes; like "[in]". These were not understood as such. IMAC, 12/11/07 * We no longer issue a 760 "Redundant macro" Informational if the macro in question has no content (i.e. a null pointer). If redundant defines to NULL are of interest, Elective Note 962 can be enabled. RNMA, 12/13/07 * We now recognize a common idiom as normal. E.g. #define f(x) ... // define macro f void (f)(int x) ... // declare function f That is, the name of a function-like macro may appear in parentheses and will be taken as a non-use of the macro. In this way a macro f() can co-exist with a function f(). This is normal and will no longer be given the dreaded Error 123. PFMN, 12/13/07 * The sequence of references used to justify assertions in value tracking messages has been improved. ITIS, 12/14/07 * We added tentative support for the draft MISRA C++ Standard to the extent the MISRA C counterparts of such cases were already detected by Lint. EMVO, 12/20/2007 ROMI, 12/20/2007 MTEC, 12/20/2007 * In a call to a member function found through using declarations we would issue undeserved overload resolution errors if the functions referred to by using declarations were members of a private base class. AMPB, 12/21/12 * Added support for type trait operators. These are not yet standard but are widely used in libraries. E.g. struct A { int i; }; template< bool b > struct B { /* ... */ }; template< > struct B { }; B< __is_pod(A) > x; // picks primary template of B ITTO, 1/8/08 * We now support extremely long -D options within .vcproj files by decomposing the -D option at ';' separators and forming separate lint options. DOLV, 1/30/08 * We now support the Microsoft handle declaration syntax MHDS, 2/7/08 * Added a +rw option "*type_traits" that will activate all the type trait keywords. ITT03, 2/7/08 * When using the tentative Misra C++ standard we had issued an undeserved 1960 Elective Note. ECDS, 2/20/08 * A recent fix caused strcpy( p, ... ) to remove the custody property from p. This could have resulted in the loss of an error leak message. SKOC, 2/29/08 * Since GCC no longer uses namespace std by default (i.e. it had an implied "using namespace std") we no longer set the +fus flag when we see a -cgnu option. UNSN, 2/28/08 * A verbosity frequency of zero caused a divide by zero exception. VFNZ, 3/14/08 * We were incorrectly issuing Internal Error 1201 and 1202 when recovering from a user syntax error. MNIE, 3/14/08 * When a union employed a constructor which contained a ctor initializer we were issuing an undeserved 1927 (Symbol did not appear in the constructor initializer list) for each union member not explicitly initialized. UIOM, 3/18/08 * We were not associating an explicit specialization of a function template with the correct function template. Example: template< class T > void f( T ) { } // #1 template< int N > void f( ) { } // #2 template<> void f<42>(); // explicitly specializes #2 FTSP, 3/25/08 * We were not finding the correct function template to associate with a call that used explicit template arguments. Example: template< class T > void f( T ) { } // #1 template< int N > void f( ) { } // #2 void h() { f<42>(); /* calls #2 */ } FTSP, 3/25/08 * We were not explicitly complaining about apparent ctor initializers for non-constructor function definitions. UCIE, 3/25/08 * The option -A (note not -A(...) which identifies a standard) now causes the character @ to be illegal outside of a string/ character literal. M@IC, 3/25/08 * We were previously issuing an error message 58 when comparing enumerators from two different enumerations. We now issue appropriate warnings. EPRO, 3/25/08 * Inside class templates (or indeed any class temploid) a friend function declaration was handled in such a way that it could cause trouble later (possibly an Interal Error 1241). UFSS, 4/16/08 * When an extra const preceded a qualified name of a type used in a function prototype of a member function, spurious errors could result (including Error 1039 and 18). PMAD, 4/16/08 * If a function template was first forward declared and then later defined with the template parameters renamed, we could issue unjustified errors about undeclared identifiers during instantiation. TPLS, 4/17/08 * We were ignoring the 'extern' keyword in the following: template< class T > void f(){}; extern template void f(); This is now given the C++0x interpretation, i.e. do not instantiate here. IETF, 4/17/08 * We were incorrectly calculating line numbers after a multi-line macro that appeared as an argument to a function that was subject to ADL (Argument Dependent Lookup). ELFM, 4/18/08, GSRN-HP-080312-1 * A regression was fixed that resulted in some cases with a 593 message that read "comment within comment" where there were no comments. PNFRa, 4/24/08 * Fixed a bug whereby we were not issuing message 970 when activating the Misra 1 checks FSWPa, 5/9/08 * Fixed a regression involving LOB's. This was first fixed in IAEL which introduced a regression of its own. That fix was withdrawn in favor of this one. DLSC, 5/9/08 * Adjusted the underlying type for "effectively Boolean expressions" under the Misra scheme. Rather than a bool the type of a Boolean expression is now an int. Use +fmb to reverse to prior state. EBUT, 5/13/08 * We now detect (as an Elective Note) uses of wide chars and wide strings in adherence of Misra 1 guidelines. WCSM, 5/14/08 * We now report on the use of hexadecimal and octal escape sequences in accordance with the Misra 2 guidelines. HESM, 5/14/08 * Fixed a flaw in our handling of right angle brackets for C++0x and Microsoft that was revealed with: template struct A { }; A> aai; // spurious Errors at '>>' IRAB, 5/20/08 * We no longer report that a source file with the UTF-8 byte order mark is unconditionally an error. NEUU, 5/22/08 * We now have built-in semantics for the C99 built-in functions fwprintf, fwscanf, swprintf, swscanf, wprintf, and wscanf. MOWE, 5/28/08 * In MS .vcproj files we were not supporting file-specific include directories. We now support them. VADM, 5/28/08 *************** Version 8.00w 7/27/2007 *************** * We were complaining about the failure to have a case for an enumerator in a switch even when the enumerator had the same enumeration value as some other enumerator. DEIS * We now recognize Byte Order Marks (UTF-8 and friends) and make appropriate comments. BOMS * Overloaded operators from two different namespaces could result in an unjustified Error 55. IUSO * We would issue an unjustified 685 (Relational operator always evaluates to false) when comparing an enum variable > an enum constant even with the integer model for enumerations (+fie). This warning is now not given for the integer model. IMVT * Template instantiation verbosity messages were improved by (1) the end message now names the specialization that was just completed and (2) the instantiation depth is noted. IIVM * We were not able to handle deeply nested template id's. E.g B > > > > > > > > > > > > > > > RQAP * Class member enumerators encountered in different modules would result in spurious messages suggesting that they were not previously defined. HEMR * When overload resolution involving a template could cause template instantiation the instantiation could have triggered a recursive overload resolution causing the first to fail. PORD * During overload resolution involving a function template and the template function candidate is being synthesized from deduced template arguments, we could fail to find parameter names of an enclosing class template specialization. TPAS * There was an incorrect association of message 64 with Misra 1998 Rule 29 and Misra 2004 Rule 5.4. ILMM * The -A option was decoupled from the -A(C...) option. ASOA * Internal Error 1207 was being issued during the template function deduction phase of E::operator= in the example: class E { template< class T > typename A<(C::d)>::v operator=(T); }; ETOS * The probability that variable i in the following example could exceed the array bound was getting lost in the following example: void f( int i, int j ) { int a[10]; if( i > 30 ) {} while( j-- ) i = 0; a[i] = 0; } DCVS * A number of Microsoft pre-defined symbols are no longer predefined for Visual Studio 6 and later. These include: MSDOS, M_I86, LINT_ARGS, M_I86LM, M_I86CM, M_I86MM, M_I86SM EPCM * We no longer treat p - q where p and q are pointers as having any of the properties of the constituent pointers. (such as auto, new, etc.) MPDA * Our using declaration support was not adhering to the letter of the standard; we now support a mix of functions and using declarations which import functions, plus many other intricate and elaborate using declaration combinations. RIUD * The malloc suspicous argument checking has been extended from malloc( strlen(s+1) ) to include malloc( strlen(s-1) ) and malloc( strlen(1+s) ) ASMA * In some cases we would not find names of entities with internal linkage when the same scope contains identical names with external linkage. E.g. struct A{}; static int A( struct A * ); struct A q; int n = A( &q ); The use of A in the last statement is now taken correctly to be the function not the struct. SSTE * We issued a spurious 616 for namespace alias definitions appearing after the beginning of a switch block. NASS * We were issuing a 522 ("expected a void type, assignment, increment or decrement") rather than a 534 ("ignoring the return value of a function") for the following statement: ptr-to_function( arguments ); Where the pointed to function returns a non-void. The 534 is a better fit and was the original message but was inadvertently altered to a 522. Hence we are returning back to issuing a 534. IRVP * We no longer issue a 533 for main() not returning a value provided the main() function is found in a C++ program or in a C program and the version of C is 1999 or greater. NRMF * We now issue an Error message (1093) when a pure specifier is given for a non-virtual function. PSRV * We no longer report as unreferenced virtual overriders when the context of a call to an overridden function could not rule out calls to such overrides. PCTO * We no longer issue not-referenced messages for member functions that are declared private and not defined. FILU * We were misprocessing default arguments for member functions when they would refer to class members that have not yet been seen. E.g. class A { void f( int = abc ); int abc; }; DAV * We were not always properly handling non-deducable array dimensions, such as: template void f( int (&)[N+1] ); RDDA * During function name lookup after the unqualified name lookup phase, we were not searching the global namespace during the argument dependent lookup phase. E.g. class A{}; void g(A); namespace N { void g(int); void f() { g( A() ); } } N::g would be found in the unqualified name lookup but ::g would not be found in the ADL. MGAA * We are now aware of the C99 format specifiers %t, %j, %z (ptrdiff_t, intmax_t, size_t types). We also now recogize %l[ as meaning pointer to wide char. ERFS * During unqualified lookup, a using directive of a given namespace kicks in when the lookup reaches a namespace which encloses both the using directive and the namespace. NNUE * We would issue an undeserved Error 1053 for a member function whose class was defined identically in different file locations and in different modules. BCDC * We did not recognize tagless types as having associated namespaces during ADL. TTAN * We fixed a bug involving using declarations inside unnamed classes, e.g. the following was not parsed correctly: struct B { int f(); int f(int); }; typedef struct : public B { using B::f; } A; UUDC * We were issuing an undeserved 1030 in a situation in which default arguments were being provided by two different declarations for the same function. ADAF * Support was added for split default arguments. This is the situation where default arguments within a declaration are supplemented by additional default arguments added in the definition * We now suppress message 122 (digit too large for radix) while processing unknown pragmas. SEUP * Destructors now inherit the virtual property even though the base class did not have an explicit destructor. Also non-copy assignment operators were discovered to have not inherited the virtual property. APSP * An undeserved 1545 (value of ... used previously to initialize ...) could be issued for a function as a result of it having been used in a dynamic initialization of a static variable. UCIM *************** Version 8.00v 12/9/2006 *************** * We had been looping when processing a class that has both a declaration of a nested subclass followed by the definition of that subclass. LWAM * Variables declared as selectany (Microsoft __declspec extension) were being reported as multiply defined. SVNM * Fixed a problem that occurred when a member function template with the same name as a member function in the same class (and appearing physically after it). The template was presumed not to exist when an explicit template argument list was provided for the template. E.g.: template< class T > struct A { void f(int); template< class T > void f(T); }; A ac; Later ... ac.f<>(1); // undeserved Error EFTA * The use of tmpname() has been discredited on at least one operating system and the remedy offered was neither standard nor portable and so the obscure portion of FlexeLint that employed a temporary file name was rewritten to avoid its use. RUOT * The template keyword was confusing us. E.g. p->template f(n); is now processed correctly TKMA * When an overloaded function name is passed to a template whose parameter is a non-type template parameter typed as a function pointer, we were not doing a proper overload selection to determine the right function. E.g. void f(char); void f(int); template< void (*pf) (int) > struct A { ... }; A< &f > a; // should be OK FONT * We no longer report MISRA Rule 16.3 for generated class members. GMEM * In some cases the names of embedded subclasses were not fully qualified when presented in error messages. NCMQ * We were issuing undeserved Misra 2 complaints when dealing with Boolean expressions (those of the form A<=B, A && B, !B etc.). When such expressions were assigned to variables whose underlying type is signed integer we would issue Note 960, violation of required rule 10.1. MBUI * We were not supporting fully externally defined nested classes of class templates. E.g. template< class T > class A { class B; }; template< class T > class A::B { }; A::B b; // 1080, definition for B not found EDNC * We fixed an infinite recursion in the context of ill-formed code where a function definition was misinterpreted as a curly braced initializer of a struct that contained itself as a member. DRII * Messages 1024 and 1025 ( "No function matches ..." ) could be inaccurate or misleading when the overload candidate list included a function template. FTMT * When member of a class template partial specialization is defined externally to its class, we now use a procedure for selecting the specialization which is simpler and more exact. SPFD * In some cases we were attempting to instantiate a class template even though an explicit specialization existed to handle the case. DIES * In some cases we were not deducing the correct partial specialization from a template-id. This was particularly noticeable when there were many partial templates to choose from. FTRP * We were not distinguishing an nUL constant from nL nor an nULL constant from an nLL constant. As a result overload discrimination may not have resolved correctly when using UL constants or ULL constants. In addition passing an LL constant to an overloaded function could cause a crash. Technically LL constants are not supported in official C++ and overloaded functions are not supported in C so theoretically this should not have occurred. ICBM * We did not have full support for function template function parameters of the form A< e > where A is a class template and e is a complex expression involving template non-type parameters. E.g. template< int i > class A { }; template< short s > void g( A ); A<1> x; ... g<0>( x ); We now properly deduce that the intended specialization of g is g( A<1> ). CTAT * We were not handling namespace alias definitions at block scope. NABS * A fully qualified name encountered as the mem-initializer-id within a ctor-initializer was treated as a constructor whereas it should be regarded as a type. CNCI * The following sequence created a syntax error within a non-static member function even though A::m was a legitimate object of class type having a 'c' member. We were confused thinking the intent was an address of member operation. &(A::m.c) CPMR * The instantiation of a function member of a class template would not parse properly if it contained a function-style cast where the name was the unadorned name of the template. We would complain that the result of the cast was a template. WNCI * We were not giving access permission to nested classes to private and protected members of the enclosing class(es). NCAE * A modification was made to support the non-standard syntax of GCC's asm statement. For example the following is valid in GCC: asm volatile ( "..." : "..." (foo) ) The standard does not allow for the volatile keyword and requires a single string constant as an argument to asm(). When the -cgnu option is used we now automatically support the non-standard asm syntax. To obtain the old syntax (perhaps so as to find deviations from the standard) and still use -cgnu you may follow that option with -rw(asm) +rw(asm). GVAK * We were not excluding objects, functions and enumerator names during resolution of a name preceding the scope operator within a class. Such exclusion is required by the standard. E.g. struct A { struct B { typedef char C; }; int B; B::C x; }; Such exclusion is required to drill down and find the right 'B'. ECNL * When we encountered more than 255 self-canceling esym sequences, e.g. -esym(number,name) ... +esym(number,name) we would crash. RECC * When a template has a dependent type as a base class and the dependent type is some variation of the deriving class the potential existed for an infinite loop. Such a construct appeared in boost::mpl::plus. DLIL2 * Single line suppression did not apply to the if, while, and for expressions during the Specific Walk. For example: if( some-expression ) //lint !e413 { ... would suppress a 413 on the given line during the General Walk but would not inhibit a 413 during a Specific Walk. SLSE * When a class name is qualified by itself and used as a nested name specifier (E.g. A::A::x) the 2nd "A" will no longer be recognized as a construct or name but as simply the class itself. In the example this would be equivalent to A::x. AISN * The GCC __null (for null pointer) is now supported automatically with the use of the -cgnu option. As a reserved word __null can be activated for any compiler. BTNP * When a nested-name specifier contained the name of a member function, we would issue an Error even though further searching might find a perfectly suitable qualification at some lower priority scope. Eg. class A { void std(); std::B x; }; is valid if std contains B. CMFS * We now take into account that external calls could modify static variables. Eg. int n; int g() {n=0; f(); return 100/n; } A divide-by-zero message is undeserved if f() modifies n. FMSV * We issue a spurious 1078 for namespace N { template< class T > struct A{ }; } template< class T > struct A : N::A { }; We erroneously retrieved the ::A rather than the N::A as the base class. UTDC * During heavy usage of look-ahead we could issue an Internal Error 1214 VROS * We were not handling C99 array designator inversions such as: int a[2] { [1] = 1, [0] = 0 }; DMAO * We reduce the certainty of our knowledge of auto variables when entering a loop because possible changes within the loop that have not been seen yet. This does not apply to const int variables for obvious reasons. But it erroneously did apply to const pointer variables. We now retain our certainty of all const variables. CRNC * The current instantiation was not always recognized as such while instantiating a template. As an example: namespace N { template< class T > class C { class D { C e(); }; }; } The "C" within class D can either be suffixed with a "" or not and both would refer to the current instantiation and not to the template named C. If the "" were absent as in the example we would mistake the "C" for the template and later claim that the template was not defined. CINC * We were issuing an undeserved Error 36 (redefining the storage class of A) with the following friend declaration: template< class T > friend class A; when the definition of A was subsequently found. SCFT * We were not handling an elaborated type specifier within a 'new' expression in a flawless fashion. For example: A * a = new struct A; would be greeted with Errors 84 and 64. ETNE * We were issuing a spurious 1058 error when returning a class that had a copy constructor whose parameter was ref as opposed to const ref. NUIC * When an R-value is used as an implicit non-const class parameter in a call to a member operator function we issued an undeserved Error 1058. RMBI * When argument-dependent lookup found more than one associated namespace only the first was considered. FAAS * In an initializer expression for a static data member we would issue an undeserved access violation when a protected base member was accessed. E.g. int C::m(B::f()); is OK if B::f() is protected provided B is a base class of C. ECSM * Formerly dependent base classes should not be employed during unqualified name lookup. For some cases formerly dependent base classes were so employed. These were relatively obscure cases involving non-template temploids such as nested subclasses of class templates. INL4 * We were not recognizing locally formerly dependent base classes within a function template as such. OPFB * We now support C99's compound literal. Eg. ( int [3] ) { 6,5 } is an array of two int's initialized as given. CPLS * Argument deduction would erroneously fail to select the partial specialization in the following: template< class T, class U > struct A; template< class T > struct A < T, const T & > { ... } typedef int const B[2]; A< B, B& > x; QAAE * The dimension of an array needs to be determined by its highest index when using C99 array designators. HIDD * Added C99's hexadecimal floating point constants. HFCC * We were not triggering argument dependent lookup in all cases that we should have. In particular if a name for the function was found we would not trigger it. The standard indicates several conditions in which ADL would be triggered such as when the initial search finds unqualified ID's at the global scope. ADLC * The following excerpt from the boost headers produced an infinite loop. The problem was traced to an overexuberant search of dependent base classes. template struct A : A{}; template struct A< const T > : A { int f(); }; DBDT * We no longer issue Warning 528 ('not referenced') for static inline functions found in headers. SIFH * An unbounded recursive loop could cause a crash. The loop involved a dependent base class of the form X where D is a dependent type and X is a template and is also the derived class. EBDT * We give a better diagnostic on misspelled versions of -esym, -efile, -etemplate, etc. MEOM * We were issuing an Error rather than just a Warning for a statement of the form: "false;" TFIC * We were giving an undeserved Warning 1516 about a derived class member hiding a base class name; A common idiom, however, is designed to do this exact thing such as: struct A { typedef T M; }; struct B : A { typedef A::M M; }; We now recognize this case and do not issue a 1516 when the derived class name is a typedef and has the same type as the base member type name. DCTM * ofstream operators when used for the first time with a type that triggers instantiation (of ofstream itself) could cause spurious bad type errors. MORS * We were not handling the following example of a template template parameter, a dependent template name and a partially specialized class template. struct C { template struct B { }; }; template class F, class T> struct A; // #1 template struct A< T::template B, T > {}; // #2 A< C::B, C > a; // spurious error 1080 HDTN * C99 allows the use of _Bool as a bit field as in: struct A { _Bool b : 3; }; Under certain circumstances the use of that bit field had caused an infinite loop. SFB2 * We gave an undeserved 571 (Suspicious Conversion) for the following example where us is unsigned short. u = (unsigned) (-(int) ( (unsigned) us ) ); // 571 UOSC * There was a bug in the macro expansion that failed under certain circumstances to protect a macro from expanding twice. The situation always involved the concatenation operator. For example: #define G(a,b) a ## b #define D(x) G(x,C) #define A A.B D(A) would yield A.B.BC rather than the expected A.BC PPMN * We did not support explicit specializations for operator conversion templates. E.g. class { template< class T > operator T (); }; template<> A::operator char() { ... } OTNM * We were issuing an undeserved Info 759 (declaration can be moved from header to module) for a namespace symbol. FPND * We now detect 'short long' (accepted by some compilers) and issue a distinct error message (109) which can be suppressed by the user. SFSL * We were not printing line number information for all messages. In particular we were not printing out line number information when there was no file. This could mess up front end's. DLNI * The compiler option -cgnu introduced a wrinkle (starting in 8.00o) in the lookup procedure for names of the form std::xxx, in order to conform with gcc's use of std. The wrinkle is now obsolete (applying only to GCC 2.95.x) and is now only available as an option (+fsg). GSGW * Within .vcproj files, we were automatically converting all commas within an include path to semi-colons. However some users were using commas in their directory names (why not?). This would result in errors. We now do not convert commas, if they are found within quotes. PCED *************** Version 8.00u 1/4/2006 *************** * An internal error (298) was being issued when using the obscure :> operator. E.g. //lint -compiler(base_op) void foo( int a, int *b ) { int j = a:>b; } would produce the unjustified 298. UTBP * We were issuing an undeserved 714 for functions that were declared with __declspec(dllexport). CDDR * A function declared/defined with the non-standard keywords: _interrupt, __interrupt, or __declspec(dllexport) no longer have the messages 714 (not referenced) or 765 (could be made static) issued on their behalf. SNUI and CDDR * static function templates, e.g.: template static void f( T ); when instantiated could draw unjustified messages 528 (not referenced) and 401 (not previously declared static). QFST * Messages that were part of a Specific Walk that arose at function wrap up time (such as 429, Custodial pointer has not been freed) did not have an associated line number. MLN * A function's name is available only after the prototype is scanned. Thus the following is legal: typedef int A; void A(A); We did not recognize the legality of the construct. NHAD * We previously issued an undeserved 1053 (cannot distinguish between declarations) when a function declaration followed a function template with exactly the same function prototype. E.g. template< class T > void f( int, double ); void f( int, double ); // complaint DFTF * The use of the xml option which produces error messages in an XML format (through the use of the file env-xml.lnt) was marred by the fact that if a catastrophic error occurred the output file was not closed off with the proper . ACXE * Repeated Specific Walks of the same function during the same pass could give undeservd warnings because of an unanticipated value retention between walks. SLGZ * The MISRA 2 warning against the use of octal constants in escape sequences is now not issued in the case of octal 0. Thus '\0' is not deserving of a warning. AZOE * When a function template returns a specialization of a member class template we previously looked within the global space for a name of the class template which produced a confusing diagnostic. E.g. struct A { template< class T > struct C{}; }; template< class T > A::C f(void); A::C x = f(); MFNC * A strange crash, difficult to describe and more difficult to reproduce, was traced to retaining a pointer to a data structure that was growing. The entire system was examined for similar malretentions. SDTC * We were issuing an undeserved Error 1024 (no function has same argument count) for the following example: template< class T, int u > struct A {}; template< class T > int f( A ); A a int i = f(a); The problem stems from comparing a function template call argument of type A with call parameter A. The problem was not matching the T with the int, that's old stuff, but comparing 0 with 0 really threw us, we didn't realize they were the same. PEMC * In the example: ... template int B::i = A::f(2,3); during the external definition and initialization of static member i, we made the mistake of interpreting the comma in "2,3" as an operator rather than a function argument separator owing to a lack of symbolic information concerning the dependent A::f. SFFD * Inconsistent results were obtained for ellipsis in the function parameter list of a function template: template< class T > int f( T, ... ); int i = f( 1, 2 ); NSGI * In MS .vcproj files we were not supporting a case-insensitive style of specifying tool names. In particular 'VCCCompilerTool' can also be rendered as 'VCCcompilerTool' CIXP * In the one line suppression of the form: unsigned u = -1; //lint !e570 loss of sign is OK the blank after 'lint' is necessary. But the following worked halfway. unsigned v = -1; //lint!e570 Bad It suppressed 570 but never unsuppressed it. This has now been fixed so that the first half doesn't work either. RWLC * We were not reporting as an error the taking of the address of a non-static data member in a context where there is no implied this. ANSM * In an expression P op Q // op is an operator If P is non-class type but Q is class-type we incorrectly search the scope of Q's class for member operators. This was a regression from 8.00s to 8.00t. ACOO2 * Circumstances could lead us to deduce that a variable typed unsigned something was less than zero. UDNZ * A member function within a local class could cause a crash by referencing auto variables in the outer function. FFRC * We no longer regard as uninitialized a member of a struct whose type has no constructor but is mentioned in an initializer list of a constructor with empty parentheses. Instead this is considered to be zero initialized. EPZI * The output of parsing MS .net *.vcproj files contain -i options. In the past we would quote these options if blanks appear within the argument to -i. Some users had blank-containing environment variables specified within the -i option and these caused problems. Now all -i options produced from *.vcproj files contain quotes. EIOX * Message 511 (size incompatibility) was enhanced to display the relative magnitudes of the source and destination. INMI * If a class with nested classes was defined (identically) in different modules (not at the same header location but at physically different positions in source files) and if a member of a nested class was accessed and if this were a C++ program we would issue an unjustified Error 115 (struct/union not defined). MPID * With Misra(2) enabled we were issuing an undeserved 16.3 violation for exception specifications. NIES * We were issuing undeserved Error 64 (type mismatch) while processing the definition of a class template and upon encountering an expression of the form: sizeof( f( g() ) ) within a constant initializer. The error was attributed to an overzealous attempt at overload resolution for g(). QFAE * If a class with nested classes was defined (identically) in different modules (not at the same header location but at physically different positions in source files) and if a member of a nested class was accessed and if this were a C program we would issue an unjustified Error 115 (struct/union not defined). RNTS * We were issuing undeserved Error 64 (type mismatch) while processing the definition of a class template and upon encountering an expression of the form: sizeof( f( (PF) 0 ) ) within a constant initializer where PF is a dependent type. TCTD * We did not report on anomolies of variables defined within for, while, if and switch clauses at block wrap-up time. CRCD * We did not support definitions of variables within switch clauses. ADSC * We now warn when the Microsoft Visual Studio version is 6 or earlier and there is an attept to initialize without parentheses a member (in a member initializer list) that has no constructor. LIMS * The location recorded for a macro had previously been the location of the last physical source line of its definition. It is now the first line. LFPL * We now support syntactically MSC 8.0's __type_trait predicates. TTTP * Support was added for MSC 8.0's __identifier(id) option. SMIK * An option of the form -dname(param)=replacement was being reported as a 750 (macro not referenced). Other macros introduced with -d do not get such a report. This was disturbing in as much as the -d option was issued within a .lnt file that the programmer had not written. DOCM * When we complain (Error 30) that we expected an integer constant we sometimes would place a trailing '%s' on the message. EHSP *************** Version 8.00t 10/10/2005 *************** * Some compilers allow offsetof() to be regarded as a constant permitting, for example, the declaration: int a[ offsetof(X,member) ]; This is now allowed. Also we now allow int casts of pointer casts of constants to serve as constants. E.g. int b[ (int)(char *)10 ]; CBPE * We were not issuing messages 729 (not explicitly initialized) and 552 (not accessed) for static data members even though such messages were being issued for other data with static storage duration. These messages are now issued for static members. USDM * Within base class specifiers, we presume a type even in the absence of typename. This is fine unless it's a template argument as in: template struct B : public D< (A::m) > {}; Here A::m should not be presumed to be a type although by context it is safe to assume that D< ... > is a type. Similar modifications were made in the case of ctor initializers and in typedef contexts. DIBG * static member function templates when defined out of class were given a type consistent with their being non-static members. NDMT * Prior to an unqualified name lookup for an overloaded operator function, we did not request complete types for all operands which resulted in our not finding friend functions declared only within would-be instantiated templates. template< class T > struct A { friend bool operator !=( const A &, const A & ); } void f( const A& a ) { if( a != a ) // can't find friend operator ... } OLRC * We should have been but were not suppressing message 534 for a templated operator=. IRTA * A tagless struct within a macro within a C program could produce extraneous tokens. TSWM (follow on to IETD) * We now append a dialect denotation (C or C++) for each module in a module verbosity message. ADMV * We were issuing an undeserved message about an un-C-like structure when within a C++ module, a function, within an extern "C" scope contained distinctly C++ components. The extern "C" is now regarded as pertaining to the interface and not the implementation of the function. TIDC * Owing to a recent change, we were not allowing the construct B::N in the example below. template< class T > struct A { typedef int N; }; template< class T > struct B : A { B::N m; } This would occur if the nested name specifier (B) is the current instantiation and the name (N) is not found and the current instantiation (B) has a dependent base class. By the rules of qualified name lookup, the formerly dependent base classes are examined for names during template instantiation giving this qualified name another chance for success. QMRB * When a header contained a tag-less struct which contained a doubly nested substructure, e.g. typedef struct { struct A { struct B {} b; } a; } X; we would issue an unjustified Error 18 that X was redeclared when a 2nd module included the header. TSDN * There was a problem with identical structs being defined in (at least two) modules (not in headers). This is bad practice in any case. During class wrap-up there was in some circumstances a noticable delay in processing. IDCH * We failed to give a message when a pointer to auto is transferred to an array in an outer block. APTA * We were issuing undeserved Error messages when classes were able to participate in expressions with built-in operators when the types expected by the operators were lvalues (e.g. increment, decrement) and the classes did provide conversion functions returning references to integral. ACOO * The message that typedef's are inconsistent has now been given Warning status with a separate message (452) as it strictly speaking is not an Error. CTNE * We were previously looking only inside the global namespace for the name 'type_info' which was valid at some time in the past but is no longer standard. We now look in namespace 'std' (by the current standard) for this classname. If not found, we then search the global namespace. A search for 'type_info' implicitly occurs wherever typeid is used. HCST * Wherever typeid(arg) is used a complete type is required for the argument whether it is a typename or an expression. We previously were not requiring a complete type and we were not reporting that a complete type did not exist. CACD * We were losing the predeclaration of namespace std in the 2nd and subsequent modules RSBS * A recent 'fix' introduced an irregularity in the value-tracking of nul-terminated strings embedded within arrays. Our earlier fix protected our knowledge of arrays lengths across function calls (and after they have been assigned to pointers to non-const). But this protection went too far and retained our knowledge of the content as well. PFAI * A friend function explicitly declared to be at global scope could find its way into the nearest namespace. E.g. void f(); namespace N { class A { friend void ::f(); }; } now properly treats the global f() as a friend. FFDG * A member template function with an explicit template argument list is called relying on an implied this could result in an undeserved 1032 (member needs an object). E.g. struct A { template void f(); void g() { f(); /* 1032 */ }; SRGS * An option of the form -e{...} within an inline function within a library header (but not within a class) would by default not turn itself off at the end of the function. AAFB * If a variable known not to be 0 is then determined to be < 1 or > -1 we erroneously deduced that it could be 0. INKV *************** Version 8.00s 8/18/2005 *************** * A recent fix in 8.00r created a problem in the interpretation of scoped names within templates. Before that fix we had interpreted T::N in the following example template< class T > class A { T::N x; }; as a type; this is not standards conforming. The standard requires the use of the keyword 'typename' before the 'T::N' and 8.00r enforces this rule too strictly. Many compilers were all to happy to accept T::N as a type without a preceding 'typename'. The current fix deduces when such scoped names can only be types, but issues a new Informational message (1710) to alert the user. ICTM, 8/11/05 * A recent 'fix' involving a parameter typed as reference to a pointer to function had the nasty side-effect that we began not to recognize that a pointer so passed in could be initialized. This has been refixed correctly. PPFI, 8/12/2005 * We were complaining (Warning 504) that the right side of a shift was not parenthesized even when the operation in question was the assignment shift '<<='. USNU, 8/12/05 * Added a warning message for the use of +cpp(.C) in a Windows environment suggesting the use of -fff. CUCE, 8/12/05 * When a C++ module containing a using declaration at file scope such as ... using std::printf; and is followed by a C module with an identically named function at file scope such as ... void printf( ... ); undeserved type clashes were being reported. CMUL, 8/15/05 * Added the -Aidentifier=state form of assertion equivalent to -A#identifier(state) PFAO, 8/16/05 *************** Version 8.00r 8/5/2005 *************** * We were issuing a spurious 151 and 1054 for the following template< class T, int b > struct X; template< class T > struct X< T, 1 > { X(); }; namespace N { struct G { struct H { X hx; }; }; } The message occured while generating a copy constructor when instantiating X. NSNC, 11/16/04 * We were interpretting square brackets intended to represent an array dimension as a .NET attribute. E.g. void f( unsigned [10] ); APAR, 12/2/04 * Strong (typedef) types defined in classes and namespaces and templates are now appropriately qualified when presented as part of error messages. SCTD, 12/3/04 * Template class names will no longer use default template arguments in their presentation in messages. E.g., given template< class T, class A = Allocator > class S; S x; A diagnostic about the type of x will use the designation "S" and not "S" SLTC, 12/6/04 * Added support for the Misra II diagnostic (at most one break statement used for loop termination) * There were some subtleties in the processing of C99 designators. In particular we could not handle designator lists of length more than 1. E.g. struct A { int y; int x[4]; } a[3] = { [2].x[1] = 3 }; can now be processed successfully. DNJG, 12/13/04 * In our messages that reference types within a C program the Keywords 'struct', 'union' and 'enum' are almost always useful as prefixes for aggregate names (known as tags). In the past these keywords were sometimes but not always provided. No change was made for C++ programs. CNCC, 12/10/04 * We now report when a '{' is encountered within an initializer at a location where a scalar value was expected. EBNS, 12/14/04 * Dependent names were undeservedly being equated making overload function call resolution in some cases problematic. TMD, 12/14/04 * It was possible to loop while processing the size_t class template from the Boost MPL library. OAIH, 12/15/04 * We were losing information about the size of a (nul-terminated) string in an array. CVLV, 12/17/04 * We were complaining (Elective Note 971) about the use of char without 'signed' or 'unsigned' when the fdc flag (Distinguish plain char from char) was turned off. Clearly the note is not appropriate in this case. CDWS, 12/20/04 * A function template containing a function parameter whose type is a qualified-name whose nested-name-specifier is dependent could result in a spurious 1024. E.g. template< class T > void f( T::M, T ); ... struct A { typedef double M; }; ... f( 3.5, A() ); // undeserved 1024 SNDC, 12/20/04 * An undeserved 1039 was issued when there was a textual inconsistency in a type that was used in the prototype of a member function declaration and its corresponding definition. E.g. template< class T > struct A { }; template< class T > struct B { typedef A M; void f(M); }; template< class T > void B::f( A ); // undeserved 1039 DTOF, 12/22/04 * We issue an undeserved 1763 (member function marked as const indirectly modifies class) when the address of the member function is passed to a non-const function. E.g. B::g in the example below does not modify its class even indirectly. struct B; typedef void (B::*PMF)(void) const; struct A { PMF &h(); }; struct B { A a1; void f() { a1.h() = &g; } void g() const {} }; 12/27/04 * A macro with arguments but separated from its argument list by a lint-comment would not invoke the macro. E.g. max(a,b) in: max /*lint -restore */ ( n, m ) would not be expanded. Users would not normally type such a thing but through the workings of -emacro such a construct could be generated. This has now been fixed. LCIE, 12/27/04 * Passing the address of a member function resulted in our thinking that the member function deeply modifies the this object and we were issuing an undeserved 1763. * We now suppress message 970 (using a raw type outside of a typedef) in the case of a bit field to bring this into conformance with Misra 2. BTAB, 1/4/05 * We had not been supporting the C99 feature of allowing an incomplete array (i.e. one without a dimension) as the last component of a struct. IASE, 1/4/05 * We were unable to coherently display the type for U where U is a template template parameter. TPSB, 1/6/05 * We did not report on a failure to deduce all template parameters for a function template. E.g. template< class T > int f(int); int n = f(0); DTDF, 1/11/05 * We were failing to deduce the correct template when an actual argument to a function template was a template specialization and the corresponding parameter involved the use of a template template parameter. E.g. template< template class U > int f( U ); template< class T > struct A { }; A a; int n = f( a ); // deduce that U is A CDTT, 1/11/05 * We were not complaining about the lack of certainty of variables after exiting a loop. E.g. n = 1; for( i = 0; i < 10; i++ ) ; if( n == 1 ) // No Info 774 (Boolean is always true) AFLI, 1/31/05 * We were instantiating member functions of class templates even though those members were not referenced for a given class template specialization. UMTI, 2/8/05 * We were sometimes taking the wrong effective parameter list when instantiating a member function of a partial template specialiation which could give unpredictable diagnostics and could possibly cause looping. The following example caused looping: template struct A { }; template struct A { ~A(); }; template A::~A() { } A a1; // loop * When deducing the type of a template parameter from an argument of a call to the template we did not always transfer const/volatile qualification of the argument to the type being deduced. In the following, g(b) should match the template but were rejecting it (Error 1025) because we didn't deduce T to be const. struct A { int b[10]; int f() const; }; template< class T, unsigned N > int g( T(&)[N] ); int A::f() const { return g(b); } // undeserved Error 1025 OFRA, 2/8/05 * An infinite loop could result at template wrap-up time (the time when we are attempting to compile function members of instantiated templates. The conditions require a partial template specialization. Example: template< class T > struct A{}; template< class T > struct A { ~A(); }; template< class T > A::~A() {} A a1; WPTI, 2/8/05 * We were issuing an Elective Note 957 (definition given without a prototype in scope) for a function template. It was argued that whereas function definitions should always have prototypes in scope that argument is harder to make with function templates which often serve more as a declaration than a definition. FDNP, 2/11/05 * When a member function calls a non-const member function we didn't completely drop value information for non-static data members resulting in undeserved complaints. E.g. struct A { int a; int g() { a = 0; f(); return 10/a; } // undeserved "divide by 0" msg void f() { a = 1; } }; COCT, 2/15/04 * We did not always force type completion at places required by the standard. In the following example the use of i with the operator == should force instantiation making the use of the operator quite legal. Instead we gave a "bad type" message. template< class T > struct C; template< class T > struct I { bool operator==( const C & ); }; template< class T > struct C { C( const I & ) {} }; int f( I & i ) { return i == i; } // unjustified bad type ORRI, 2/18/05 * We would report an error when calling a reference to a function pointer. E.g. typedef void (*PF)(int); void f( PF & pf ) { pf( 0 ); // undeserved error } RFCE, 2/16/05 * When a volatile variable is acquired a value we normally reduce the certainty of its retaining that value. But this was not happening when values were acquired in other ways such as through value inference. IOVV, 2/21/05 * We were getting caught in a recursive loop when a template was using a dependent instance of itself as a base class. E.g. template< typename N1 , typename N2 > struct C : C< C< N1,int >, int> { }; Such a construct was employed in the Boost Library. HEBM, 3/12/05 * We were issuing undeserved Error messages while processing objects of dependent types (within templates). For example: template< class T > void f() { A a; a == a; } would draw a complaint that a was inappropriate for use with the operator==(). This would be fine if it were given at instantiation after it is decided that A has no such operator but is not appropriate after just seeing the template. UCDG, 3/15/05 * There is a finite limit (though very large) to the length of a template id (for the purpose of error reporting). The limit still exists but can be increased by using the +macros option. ETEF, 3/17/05 * We sometimes do not deduce the correct type when the parameter of a function template has a dependent type of the form: D::name const. In particular the 'const' drops off. E.g. template struct A { typedef T u; }; template int f( typename A::u const & ); int i = f(0); // spurious 1058 QCXD, 3/29/05 * We did not tolerate simultaneously a function and a function template that took identical arguments: template int f( int, double ); int f( int, double ); // legal FOFT, 3/28/05 * Dependent types in base clauses have led to infinite loops (unjustifiably). In particular the Boost library contained several such constructs. DLIL, 4/4/05 * Upgraded our Misra 2004 support by allowing comments following null statements and allowing (null) macros before a null statement. MTNS, 4/14/05 * We added support for the MISRA "underlying type" construct and adjusted the au-misra2.lnt file accordingly. * Fixed a memory leak that affected programs containing lots of do statements. * We were not precomputing the value of enumerator comparisons. For example we did not know that the if condition below was always true enum { false, true }; ... if( false == false ) ... SAEI, 4/20/05 * For a typedef of a tagless struct (or enum or union) e.g. typedef struct { int a; } A; the typedef name is now considered a kind of tag that will identify the type uniquely even in the absence of other information such as found in the same code location. IETD, 5/2/05 * In some contexts we failed to distinguish between a dependent type and a template partial specialization with the same template-id name resulting in undeserved Error messages. E.g. template< class T, class U = int > struct B { typedef B BT; }; template< class T > struct B; // spurious Error 36 This necessitated a fundamental change in our representation of a dependent type like B. STSR, 5/18/05 * We erroneously regarded static data members of a template as being defined when they are explicitly specialized. E.g. template< class T > struct A { static int i; }; template<> int A::i; // not a definition SDDI, 5/18/05 * #including a header file whose name has trailing whitespace, e.g. #include "alpha.h " would result in an attempt to open precisely that name which would have the effect on some operating systems/libraries (Windows/MS) of opening the name without the trailing whitespace "alpha.h". This could give obscure messages owing to the fact that we think the files are different but they're really the same. We now remove trailing whitespace for the Wintel architecture. SWIF, 5/19/05 * We were not always supporting array initializers with empty parentheses in constructors. AIIC, 5/23/05 * Our value tracking now takes into account the size of arrays even though we are not actually tracking the value contained therein. E.g. struct A { int a[10]; }; void f( A *p ) { p->a[10] = 0; } will register a complaint. * We were getting a crash within a tagless enum while parsing a template-id of dependent type (Boost library). CITE, 5/25/05 * When within a template a template id would match a partial template specialization an inadvertent context change could occur that lead us to think that we were not in a template definition. TOKA, 5/25/05 * The gcc variable-argument-macro convention allows for a null list to absorb a comma prior to any ## that precedes a name representing the list. E.g. #define A(fmt,a...) printf(fmt,##a) ... A("hello world\n") now works as expected. GVMN, 5/24/05 * When a base class within a template is a dependent type but it can be considered to represent a set of symbols we previously would search that set during unqualified name lookup. This we no longer do (by default) owing to a recent change in the standard (2003). It is necessary to obtain the old behavior for compiler libraries. For this purpose ++template(40) can be used. ++template(40) is automatically switched on when we see the compiler code options: -cmsc and -cbc. FLBD, 5/31/05 * For overloaded binary operators (like cout << n) the operator must be looked up both as a member function and as a global. When looked up as a member function we now follow the standard and employ qualified name lookup rather than unqualified name lookup. The latter cannot find names in base classes that result from dependent types. MSLC, 6/1/05 * A call to a member template using both the dot operator and explicit template arguments could result in a crash. ETAC, 6/2/05 * We further refined our notion of what it means to be a formerly dependent base class. We were relying on the use of template parameters to indicate this but as the following example shows this is not conclusive. template struct A { typedef int G; }; struct B : public A<> { int f(G); // OK, G should be found in A<> }; ILIB, 6/2/05 * In processing template functions certain dependent expressions were assumed to have type 'int' rather than some unknown dependent type and as a result spurious messages would be given owing to a suspected conflict of types. CDDE, 6/3/05 * When a static data member of a template is initialized (out of line) we did not always recognize when a nested name specifier nominated the current instantiation which led to undeserved errors. E.g.: template struct A { typedef typename T::M M; static const M n; }; template const typename A::M A::n = (A::M)(-1); ICID, 6/3/05 * In an explicit specialization the original template parameters are not supposed to be visible. By default they no longer are. We require a special template bit (400) to make them visible as some compilers recognize the parameters in this context. E.g. template< class T > struct A { T n; }; // OK template< > struct A { T n; }; // T should not be in scope An option of ++template(400) would make the above behave as expected. With the compiler option -cmsc, the 400 template bit is set automatically. ESLP, 6/6/05 * Our name lookup of an elaborated (unqualified) type (eg struct A) failed to take into account nominated namespaces. Thus using namespace NS; struct A *p; did not always pick up a struct A that might be declared within NS. UNET, 6/7/05 * The dependent base classes of a template should not be considered as formerly dependent base classes of an explicit specialization since the latter contains no dependencies. EFDB, 6/6/05 * Corrected a problem involving Boost headers. We locked up when attempting name lookup inside a base class with a dependent type of the form A::M where T is a template parameter (such lookups are technically non-standard but some compilers support this). CLDB, 6/7/05 * Running the Boost time headers through multiple passes resulted in a crash. OILC, 6/14/05 DBKI, 6/15/05 * In determining whether one function template is more specialized than another we were inadvertently triggering an instantiation of one of the template arguments. DUCI, 6/16/05 * When a stringize operator (#) was used in a macro and the argument to be stringized contains two or more escaped quotes we did not escape the second escape. Thus #define S(s) #s S( "\"quoted\"" ) resulted in "\"\\\"quoted\\"\"" rather than the expected "\"\\\"quoted\\\"\"" NEBS, 6/20/05 * With some partial template specializations the parsing of the template-id representing the partial template name having an argument which itself is a template-id could lead to obscure errors. This occurs in Gnu's STL. TIWI, 6/21/05 * Under conditions of deferred instantiation we did not reconsider the set of template partial specializations that might match the actual template argument list. This occurs in the Rogue Wave interator headers. PPPF, 6/27/05 * Under situations of extreme duress (owing to a lack of a lack of a critical namespace) it was possible to enter into an infinite recursion. IRIC, 6/28/05 *************** Version 8.00q 11/10/2004 *************** * A gratuitous new-line appeared in message 309 (#error encountered). The new-line was the character terminating the #error line. It is now removed. * We may have given an undeserved 1749 (base class need not be virtual) at global wrap-up when two or more modules process the same class definitions. * We now support the Exclude_From_Build feature of .dsp files. * We were not issuing a 1962 (contains a deep modification) when a function not declared as const indirectly modifies its class. E.g. struct X { int *p; void f() { *p = 0; } }; now issues a 1962 * We were stumbling over Microsoft [in] [out] attributes in function prototypes (with the -cmsc compiler specified). E.g. class S { void f( [in] x ); }; * In the declaration: template< typename A::B(*pf)() > void g(); we were interpreting the template parameter as a template type parameter and getting confused. * A tagless struct defined within a typedef is now considered to be a different type than any other tagless struct defined in some different location. Thus after the declarations: typedef struct { int n; } A, B; typedef struct { int n; } C; A and B are considered to be the same type both different from C. One of the motivations for making the change was that the lob processing would consider A and C different whereas processing the original source files considered them the same. This change only affects typedef definitions. The declarations: struct { int n; } a; struct { int n; } b; still regards a and b to be the same type even if declared in different modules. * A recursive template in the boost library (rational.hpp) was sending our template parser into infinite recursion. * There were some examples of function templates containing ellipsis that we were not handling properly. We would not find a match. * The type of a suffixed constant of high precision (greater than a long) was in rare cases not properly determined. * When constants were larger than the precision that could be handled internally we would issue the confusing diagnostic "Error 30 Expecting a constant". This has been upgraded to show the reason we did not like a constant. * The value-tracking analysis could regard a variable constant (such as const int n = 0;) as not necessarily equal to its original value as in: k = 3; if( n == k ) { ... shook our confidence that n was still 0. * We now print the location of the left curly when it is unmatched by a right curly. * We now support early modifiers in situations other than at global scope. E.g. void f() { huge int *p; ... } * We now support .net attributes within prototypes. Thus void f( [in] int k ); now produces no syntax error. Our support for attributes can be turned off using the -fat option (do not support bracketed attributes). * We now support extremely long -i options within .vcproj files by decomposing the -i option at ';' separators and forming separate lint options. * We were generating an undeserved 762 (redundantly declared symbol) in the following C code //lint +fmd allow multiple definitions extern int i; // declare i int i; // define i --> Info 762 This info 762 will now be supressed. Subsequent tentative definitions in the same module will still draw the Info 762 * When the maximum negative integer (0x80000000)was cast to long long and involved in multiplication there was danger of a stack overflow owing to unbounded recursion. * The internal type used to compute values for the purpose of value-tracking has been increased internally to 64 bits for PC-lint. The number of bits for FlexeLint is determined by a pair of compile-type typedef's MAX_INT_t and MAX_UINT_t in custom.h. By default these are long's. * Assigning a negative integer to an unsigned long long variable, or assigning large unsigned integers to a long long variable, if the computation precision is only 32 bits, could have resulted in the value tracking system getting wrong values for these variables. * We were issuing an erroneous report (message 793) of 'too many identifiers in one block' when what we really had was an unusually large number of -esym options. The count of identifiers was not accurately reported either. * We were issuing an undeserved 952 (variable could be declared const) in the case of an enum using the integer model for enumeration (fie) * We were issuing an undeserved warning about a strong type violation within a template function that was specialized with a strong type. * We were insisting on a typename when in context a typename would be implied. E.g. template class A; template A::x f(); * We were not able to pass a function template to an overloaded operator. E.g. class X { public: X operator<<(X (*)(X)); X operator<<(bool); }; template X g( V); X ac; void f() { ac << g; } This is a model in some libraries for manipulators such as endl. * We were not always successful in passing an overloaded function to an overloaded operator. E.g. class X{}; int operator+(int,X); int operator+(int (*)(int),X); double g(double); int g(int); int h() { X x; return g+x; } * During some look-ahead operations (for C++ overload resolution) temporary error suppression via -save -e... ... -restore was not having an effect. This generally would occur when the save-restore sequence occured within the parentheses of the function call. * We were too aggressive in extracting information from templates specified via template-id with dependent argument lists. In many cases these should be regarded as dependent types and not element of some template. E.g. template struct B { typedef T type; }; template class Test {}; template class Test::type> {}; template class Test::type,T> {}; we would brand the last of these a redefinition whereas the arguments are which is not the same as in the line just above * A friend reference to a class or template in an enclosing namespace other than the current namespace could not be found. * We now allow floating constants within preprocessor conditions. E.g. #if 3.0 > 1.5 * In the example: struct A { enum { red }; } a; template< int > class B {}; ... B< a.red + 20 > we were issuing an error to the effect that a constant was required. * We were sometimes issuing a 1023 when attempting to use manipulators in the MSVC7 library. E.g. cout << endl; * We were issuing an undeserved 734 (loss of precision) with the following: int s; unsigned char u; ... u = 1 << (s&7); * We were not supporting multiple error numbers in the braced version of -emacro. Thus -emacro({1,2,3},name) didn't work. * We were not supporting an unparenthisized complex expression to sizeof. E.g. sizeof(A)[0] should be treated as sizeof((A)[0]). * We had some problems in dealing with the cross product of overloads. E.g. void g(int); void g(double); void f( void(*)double ); void f( int(*)(long) ); ... f( g ); * We were issuing an undeserved 1762 (could be made const) when a member function modifies an anonymous union member. * We were not selecting the correct class template partial specialization when const was used to specify the discrimination. E.g. template class X { }; template class X { }; X a; previously selected X; it now selects X. * We were issuing a spurious Warning 550 (not accessed) for a pointer, p, where the pointer actually had been used in the expression: typeid(*p).name() Since p's indirect type was a polymorphic class the pointer would indeed have been accessed. * For the Sun compiler (option -csun) we are supporting the unique aspects of the -I- option. See readme. * To support the notion of compiler header files having less priority than user header files, there is a new variant of the -i option. --iDirectory specifies an include directory with less than normal priority. This can be employed to specify compiler header directories. See readme. * We now allow intermixed declarations and statements in C99 source code * Through the magic of "using namespace" we were reporting (578) that a symbol was hiding itself. We now check for identity before issuing the message. * We were issuing an undeserved Error 304 (Corrupt object file, code 28, class-name, member-name ) when processing a lob file containing a class template (name provided) that contained a member function (name provided) where the member was overloaded with another member both taking a dependent type where one was const and the other not. * We were issuing an undeserved 541 (excessive size) for the string constant "\00610". Since octal are limited to 3 digits the string is well defined. * The #asm ... #endasm sequence employed by the Cosmic compiler and others to delimit assembler regions would not work properly if they were embedded within #if directives. * Our determination of what is an aggregate has been upgraded to reflect the fact that merely having a constructor does not make a class a non-aggregate; the constructor must be user-declared (i.e. not generated) as well. * Type arguments bearing namespace scoping could sometimes create an undeserved error 151 and 1054 during instantiation. E.g. the specialization X when accepted as corresponding to a partial specialization X< T, 1 > of template X causes spurious errors 151 and 1054. * We now support (for the most part) the Misra 2 (2004) standard. See au-misra2.lnt *************** Version 8.00p 5/26/2004 *************** * Added an extra clarifying clause to message 1711. * We were issuing an undeserved Warning 685 ( always evaluates to false ) for: if( a.b + a.c > 1 ) where b and c are one-bit bit fields. * Some error messages involving a member of a class which in turn is a member of a namespace did not include the namespace qualification. E.g. namespace N { class A { int n; }; } might refer to A::n not being used whereas the error message now correctly reports that N::A::n is not being used. * In our processing of .NET project files (.vcproj files) we were not excluding those source modules designated as "ExcludeFromBuild" * Using two or more -emacro({number},M) options for the same macro M could produce an undeserved Error 72 if the macro were used as an argument to another macro. For example: //lint -emacro({681},M) -emacro({912},M) #define M ... #define M ... #define x(a) ... x(M) * We were treating the sequence: extern "C" { struct A { struct B {}; }; } as though it were compiled in C; that is, struct A and struct B would be located on the same level. However a number of users had programs in which the inner B was referenced as A::B and the compilers accepted it whereas we issued an Error message. In this new patch by default B will be placed inside A (within an extern "C"). To get the old behavior use the option -fns (turn off nested structs within extern "C"). To obtain nested structs within pure C code use the option ++fns. * We now allow empty parens as initializers for non-class objects in constructor initializers. E.g. class A { int n; A() : n() { } }; * We fixed an anomoly in our invocation of a destructor. * We no longer issue a 1924 (C-style cast) when the cast is a cast to void. Even the advocates of using only C++ style casts would not want you to convert: (void) Function(arguments); to: static_cast(Function(arguments)); * We were not deducing that classes that contained no pure virtual functions but were derived from abstract classes could themselves be abstract if they did not provide an implementation for the pure virtuals they inherited. * We now consider a header to be used if it bears a definition of struct A and the module contains a reference to an implicit constructor for A. * We were issuing a complaint about a non-constant initializer when employing _ignore_init. E.g: _ignore_init bit n = a.1; * A macro which had a lint comment prepended via -emacro was experiencing strange effects when used in certain contexts such as just after a ## operator or just after a '/' . E.g. /*lint -emacro(774,Q) */ #define Q 2 #define R(r) (5/r) #define A(r) R(r) int n = A(Q); * We now support the printf/scanf formats %hhd, %hhu, %hhx, %hho introduced by C99. * Using the option -printf_code(something,char) we would complain when it was used because the type of promoted char within the argument list did not match char. We now promote the 2nd argument of the printf_code option. * We were not properly identifying a specialization of a template during the out of class definition of a member function of a template specialization. E.g. template struct A { A(int); }; template struct A< T* > { A(int); A(int, bool); }; template A< T* >::A(int,bool) {} would draw a complaint that A(int,bool) could not be found. We were not picking out the correct specializations. * Macros whose expansion contains the name of the macro were sometimes being expanded twice. E.g. #define n (i.n) #define m n #define b(v) (v) #define a(v) b(v) a(m) would erroneously be expanded to ((i.(i.n))) instead of ((i.n)) * Under some conditions a using declaration was reported as unreferenced when it actually was. E.g., in the code namespace N { void g(void) {} } void f() { using N::g; g(); } we reported that the g within f() was not used. * We were previously regarding a header as having been used if a member function were defined somewhere in the header. We now require the function to be defined outside the class to reach this conclusion. E.g. header.h: class X { void f(){} }; module.cpp: #include "header.h" Assuming there is no reference to X or X::f in module.cpp we now issue the message header not used. * When processing .DSP files (Microsoft project files) we were not converting portions of filenames of the form $(envar) to %envar% as we previously had done for /I (-i) options. * We were reporting an undeserved arithmetic overflow message (648) when the result of a multiplication was the most negative integer. E.g. (int) 0xC0000000 * 2 * We no longer produce a 961 (redundant cast) when issuing a delete. * We were giving unjustified 1401 (member not initialized by constructor) warnings for unions. * We were not allowing a conversion function that returned a pointer to be used in a context requiring a bool. E.g struct A { int *operator(); }; bool f(A a) { return a; } // Undeserved Error 64 * We were issuing an undeserved Info 1763 (const member function indirectly modifies class) when it returns a pointer to function. * If a #endif (or other pre-processing line) immediately followed a //lint comment within a member function defined inline we would an undeserved complaint about a missing '}' * We were incorrectly evaluating the precision of an expression of the form (c << n) where c is a constant and n is a variable. * We were failing to report (via Warning 427) that a backslash newline appeared within a // form of comment when the first nonblank character in the comment was an upper case letter. * A free or delete would result in a pointer variable being marked as uninitialized. This was done so that if the pointer were later reused we would issue a message. Unfortunately the message was sometimes confusing. We now give a more appropriate message (449). * We were giving an undeserved report (429) that a Custodial pointer has not been freed within a catch block parameterized by ellipsis. * The one-line error suppression was not being applied to Specific Walks. This has now been fixed. * The symbol-like arguments of messages 1023, 1703, 118 and 119, which were marked as 'String' are now treated as 'Name' and therefore can now be suppressed with -esym * A prior fix to support member function template specializations had a flaw which resulted in an undeserved redeclaration error. This has now been fixed. E.g. class C { template void f(T) { } }; template<> void C::f( int ) { } should now work properly. * We now support function try blocks. These are try blocks that can be used to define constructors so as to catch throws emanating from the constructor initializer list. * Our recursion detection halted template instantiation when the same physical template was provided with the same argument sequence. This condition was not precise enough as templates within templates could produce a false hit. We now check the types as well. * Message 826 (suspicious ptr to ptr conversion, area too small) was raised to the rank of a dynamic error (available by default in Specific Walks) since the areas in question were computed using dynamically obtained values. *************** Version 8.00o 1/16/2004 *************** * We were issuing an undeserved Error 304 Corrupt object file, code 4 when processing the lob file resulting from an unsuccessful attempt to pass an object to a function template having a parameter of the form A where T is a parameter of the function template. * Preprocessor variable __STDC_VERSION__ was being defined even though the option -A(C90) was given. This fix was scheduled to go into 8.00n but didn't quite make it. * For gcc (option -cgnu) we have a special mode in which std::name (where name is any identifier) refers either to a name within namespace std or a name in the global namespace. Instead of looking solely in the global namespace we were looking in all namespaces (unqualified name lookup) which opened the door to finding the wrong name. * We no longer issue warnings for objects of a class type when the class has no data members. * We added an additional parameter to message 1502 to designate the class so that the message may be suppressed by the class as well as by the object * We were complaining that an array (of classes) member was not initialized by a constructor when the array would have been initialized by the default constructor. * We were issuing an undeserved 1527 (static member not defined) for a constant static member that has a constant initializer. * We were issuing an undeserved 1540 (pointer member neither freed nor zero'ed by destructor) for a volatile pointer that is clearly zero'ed. * We were experiencing an infinite loop in the following code: template< typename T > struct F { template static bool g( void(U::*)(void) ); template static int g( ... ); enum { h = g(0) }; }; In general, the invocation of a member template function within an enum had the effect of creating a data loop. * The C99 keyword, restrict, is defined for all C programs (unless the -A(C90) option, or equivalent, is given). * We were not supporting member function template specializations defined outside of the class that were not declared inside the class. For example: class C { template void f(T) { } // template<> void f( int ); }; template<> void C::f( int ) { } was not previously accepted without the declaration shown commented out. This construction is specifically permitted by the C++ standard. * We would sometimes give an undeserved complaint to the effect that a member of an anonymous union was uninitialized. * We were issuing an undeserved Misra Rule 54 violation (null statement is not on a line by itself) when processing a null statement in an inline class member function. * We were issuing an undeserved 1918 (empty prototype for member declaration) for generated default constructors. * We were issuing an undeserved Warning 1540 (pointer member not freed in a destructor) for constant pointers. * We've added the inline keyword for C99. * We were not accepting pointer to member as a bool and conversion functions that return pointer to members are being ignored when a class containing same is used as a bool. * We were not promoting a protected member to public through a private derivation. E.g. class B{ protected: int b; }; class BB : private B { public: using B::b; } void f() { BB bb; bb.b = 3; } drew an undeserved complaint since this makes b a public member of BB. * We were issuing a confusing message after reporting an unreachable semi-colon. E.g. int f() { if( ... ) return 0; exit(1);; } would report that f() is not returning anything. We still report that the semi-colon is unreachable, but we assume what follows is also unreachable. (The double semi-colon was more likely to arise in connection with macros) * Our Misra Rule 47 check that guards against a reliance on C's operator precedence has been revised and improved. * The use of A::A rather than A to identify a constructor for A was giving us problems in expression contexts. For example: struct A { }; A a = A::A(); would give an unjustified Error 1032. * We were giving an undeserved warning (541, excessive character size) in wide-character literal strings where an escaped sequence produced a value that was too wide for a normal byte but was not wider than a wide character. * We were not reporting (under Unix and Linux which by default uses split options) that there is something amiss with the following /*lint -e */ * Parentheses are now allowed in split options. Thus "-elib(345)" when written as a split option previously had to be written as "-elib 345". Now it can also be written as "-elib (345)" * The -vo verbosity option was not accurately reflecting the value of split options. * When parsing a base class specifier we were supposed to ignore names that are not class names. E.g. we were giving error message 1016 for: enum A { C }; class C{}; class D : public C { }; // 1016 We now correctly pick out class C rather than enumerator C. * The -emacro option was creating a problem when it names a macro that is used directly after a '/' in the source code. For example: //lint -emacro(506,R) #define R 10 int n = 100/R; * Under certain circumstances the expression within an if clause could be mischaracterized as a declaration. E.g. the following works as expected: struct Q { Q(); }; struct L { L(); Q operator[]( unsigned i ) const; }; struct U { U( Q ); bool f(); }; L a; ... if( U( a[30] ).f() ) ... * We were not issuing a Misra Rule 63 violation for a C program containing a switch statement whose switch expression is a Boolean. E.g. switch( a < b ) /* should produce message 961, rule 63 */ * We were not allowing friend functions defined in-line special lookup privileges as in: struct T { enum E { r }; friend void f() { E e = r; } }; Here the E and r should be visible to the function f() since it is defined within the class T. * We were giving an undeserved initializer inversion Informational (1729) when a member typedef was used to specify a base class. E.g. class C : public B { int a; typedef B X; C() : X(), a(0) { ... * We were giving an undeserved 1063 (copy constructor parameter should be a reference) when the parameter is the ellipsis. E.g., class A { A(...); }; * Our macro processing was not adhering to the standard in a way that would show up in a macroized #include statement. As an example: #define Sep() / #define Dir() xxx #define Name() y.h #define Header #include Dir()Sep()Name() would induce us to open because the result of Dir() would be tacked onto "Sep()" yielding a name xxxSep with no macro association. The standard requires that the identifiers be kept separate so that now we would attempt to open There may be some folks (or programs) out there still using an ancient concatenation method exemplified as follows: #define Prefix() x int Prefix()y; This will no longer work by default as it is non-compliant. To get it to work you will need the option +fmc (macro concatenation). This is described in readme.txt. * We no longer issue Elective Notes 1917 and 1918 (vacuous argument list) for destructors as these never have arguments anyway. * We had a problem with Universal Naming Convention (UNC) pathnames. A file such as "//x.c" might have a "C:" (or whatever the current drive letter) prepended to it. This would normally affect only presentation purposes. It could also affect subsequent header searching if the misnamed file then includes other headers and if the +fdi (Directory of Including file) flag was set. * ANSI translation limits have been upgraded to reflect those of C99. To obtain the older limits use -A(C90). * An extra blank could appear in the expansion of a macro sequence. For example: #define f(a) #define t(a) a #define g f #define h g #define i h t(i)b previously would result in "f b". It now properly results in "fb" * An extra blank could appear in the expansion of a function like macro if the name of the macro is separated from the '('. E.g. #define A(b) b #define B A () #include B Attempted to open " c.h" instead of "c.h" * An unparenthesized '<' within a default value for a template parameter was throwing off our attempt to find a balancing '>' in the following example: template< class T, bool b = T(-1) < T(0) > struct A; *************** Version 8.00n 10/16/2003 *************** * We were not supporting anonymous unions under C at the global level but only within struct's. Though non-standard, anonymous unions are supported by the IAR compiler and even appear within IAR headers. Under C you will need the +fan option to activate anonymous unions. * We were not catching a fairly obvious null pointer usage: struct S { char a[10]; }; void f() { S *p = 0; p->a[0] = 0; ... } * The _Bool keyword is now built-in as per the C99 spec. * We were issuing an undeserved Error 64 when passing a reference to a constructorless class. E.g. struct X { int a; }; void f( X ); void g( X & y ) { f( y ); } * An option to modify the library flag was ineffective just after a function template definition. The sequence: template <...> type f(...){...} /*lint --flb */ read the option before processing the definition resulting in no change to the library flag. * We were issuing an undeserved header-not-used message (766) when the header would contain a template definition and the template was accessed through a typedef. * We were issuing template instantiation errors at wrap-up time for modules that did not declare the templates. * We were giving a false complaint about ignoring the return value of operator new even though it was clearly not being ignored. This could have occurred when the type being new'ed required instantiation. * We were not treating a member function within a class within a member function properly. Unqualified name lookup could find the wrong name. * We were issuing internal error 265 and stopping when the file consisted only of C::C : a(0) { } We now move on to the next declaration after issuing appropriate error messages. * We were not evaluating expressions involving strong Booleans properly if the strong Booleans were enum's. Thus: /*lint -strong(AJXB, B) */ enum E; typedef enum E B; #if ! ( 0 && 0 ) ... The if would be evaluated incorrectly as 0 rather than 1. * Under some circumstances when only a subset of a set of overloaded functions were redeclared for a new module leaving some undeclared there was the possibility of having some confusion between a more appropriate function not declared and a less appropriate function that was declared. * An inference that if( p - q ) were true where p and q were pointers might infer something improper about p or q. * The use of the +fct (Create Tag) flag could result in unjustified tag errors as some of the created tags could inadvertently conflict. * Preprocessor variable __STDC_VERSION__ was being defined even though the option -A(C90) was given. * We were issuing an undeserved 1926 (default constructor implicitly called) for an array member of a class. * When a user employed the -idlen(k) option to get reports on identifiers that were different but identical to within k characters (Warning 621) the programmer might receive information to the effect that some created symbols matched that description. Specifically static variables are placed in fictitious name spaces and the names of these spaces formed near collisions. We now suppress this message for internally generated names. *************** Version 8.00m 9/9/2003 *************** * Under certain conditions repeated use of the same semantic would not work. The semantic would have to involve allocation flags. For example: -sem( f, @P == malloc(1n) ) would work on the first invocation of f() but not on subsequent invocations the malloc flag would not be inserted. * When a modifier semantic is assigned to some new keyword as in -rw_asgn( shared, fortran ) we now use the new name ('shared' in this case) to designate types so modified rather than the original modifier name ('fortran' in this case). * Messages issued as the result of evaluating the control expression of a while or for statement were sometimes issued redundantly up to three times. This number has been sharply reduced. * When comparing two floating point constant literals we were not always accurately deducing the result. For example, the expression 1 / ( 1.3 > 0.0 ) would be regarded as a possible division by 0. * We were crashing when an option -passes was issued without the trailing parenthetical expression or if the '(' was separated from the -passes by a blank. * Under NT you were unable to use the convention that .C implies C++ processing whereas .c implies C processing. The reason for this is that filenames are normally folded so that alpha.h compares equal to ALPHA.H. However, you should have been able to accomplish this by turning off filename folding (option -fff). But some folding was still being done. This residual folding has been removed. * We were not catching out-of-bound array references when the reference was to an array within an array of structs. For example, assume all arrays are dimension 10. Assume a is an array of structs which bear a member array b. Then a[10].b[9] = 0; would not be caught. * The conditional operator e0 ? e1 : e2 might give undue favoritism to the first branch (e1) over the second branch (e2) when both branches were possible even though e2 was more probable than e1. * A bug was found in loop combinations that would give a bogus message. E.g. for( i = 0; i < n+1; i++ ) { } a[n] = 0; would give an undeserved "Conceivably negative value" for the subscript * A -d(name)= would be greeted with a complaint (Error 72) but since the option was deferred to the start of the module the complaint would refer to the wrong option. * We were not properly value-tracking variables having the non-standard type of _bit. Initialization values were honored but assignments were getting lost. E.g. void f() { _bit x = 1; x = 0; /* we think x is still 1 */ ... } * We were improperly flagging some array variables as having string like properties. * The combined options +fxa (exact array) and +fsc (strings are const) for a C program were working in such a way as to make string constants incompatible with pointers to const char across the : operator (i.e. the 2nd and 3rd operands of the ?: ternary operator). * We now support for( int i = 0; ... ) within C99 programs (C99 is the default for C in lieu of a -A(C90) option). * The first user-defined function with semantic properties was given some additional undeserved properties. In particular you might get an Unreachable Code (527) following its use. This normally wouldn't be experienced because the first function endowed with additional semantics was usually some library function specified with -wfprintf. * We were giving an undeserved 1058 (Initializing a non-const reference with a non-lvalue) when passing an lvalue class to a function whose parameter is a non-reference class and for which the required copy constructor is parameterized as non-const reference. E.g. struct X { X( X& ); }; void f( X ); void g( X a ) { f( a ); } * We were regarding a member template as the copy assignment operator. Copy assignment operators can never be specialized from a template. For example, template class A { A& operator =(A& ); template A& operator =(A& ); }; issued an unwarranted 1520 (multiple assignment operators). * During Specific Walks we were inhibiting inference, as too many undeserved warnings seemed to ensue from some inferences, especially string-related inferences. We have fixed a number of conditions that were giving us problems and we now track separately the buffer length and the string length of char * variables. This gives us a marked improvement in our ability to analyze strings. It also allows us to retain full value inference during Specific Walks. To revert to the old policy use the option +fii (Inhibit Inference during Specific Walks). * The Unreachable warning (527) now identifies the token which can't be reached. * The construct asm { ... } did not support balanced internal braces * We were not issuing the 730 Informational (Boolean argument to function) when false or true were passed to an int. * A symbol was added to error messages 133, 785 and 943 to indicate the name of the aggregate (if available) that was unusually initialized. * We were producing a strange diagnostic (Error 1054: template variable declaration expects a type) when the typedef name of an untagged struct was used as a class template argument. * A friend class declaration that references a class template specialization is causing a later definition of the specialization to complain of an earlier definition. E.g. template< class T > class C {}; class B { friend class C; }; template<> class C { }; // undeserved Error 39 * We were issuing undeserved error messages when a static const member of a class template is defined in terms of itself. The following example is a reduction of a construct that appears in the Metrowerks Standard Libary template< int b > struct C { static const int a = C< b>>1 >::a; }; * Using the -vo option (emit a verbosity message when an option is encountered) we did not previously issue a message for the one-line error suppression (!e...). * We were not always issuing a 970 Elective Note (use of modifier or type not in a typedef). * We were issuing an Error 206 (internal error) when processing a split string (over line boundaries) during look-ahead. E.g. A a( "start \ end" ); could emit a 206 if look-ahead was required in its parsing. * We were issuing an undeserved typedef not referenced message when the only use of the typedef was in a function-style cast notation. E.g. int f() { typedef int I; return I(3); } * We were issuing Elective Note "Octal constant used" while processing assembly code. * -esym( N, X::operator* ) suppressed message N for all operator member functions of X. It was the programmers intention to suppress the message only for member operator*. This has now been fixed so that the above applies only to member X::operator*. To refer to the set of all operator functions use the option -esym( N, X::operator?* ). In addition to "operator*" we are also on special alert for "operator*=" and "operator->*". * We were giving an undeserved complaint when assigning a base class member pointer to a derived class member pointer as in: class B { }; class D : public B {}; int D::* x; int B::* y; ... x = y; This is legal. * We were giving an undeserved error indicating that a function having a base class member pointer could not be matched in an overload situation. For example: struct A; void f ( int A::* ); void f ( int ); struct A { int ai; }; void g( ) { f( &A::ai ); } would result in a complaint that there was no matching function. * Our documentation on the processing of a .BPR (Borland PRoject file) indicated that you could define the location of the Borland's C Builder using an option such as -d"BCP=C:\program files... The comment has been corrected to -d"BCP=C:\\program files... That is, the backslashes need escapes. * We now deduce that the argument to functions that require that their arguments be non-NULL are in fact non-NULL after, of course, issuing any required Warnings. Thus, strcpy( s,"abc" ); if(s) ... gets flagged with Info 774, (Boolean always evaluates to true). * We were passing custody to a function even though the function takes custody flag was off (-ffc). *************** Version 8.00L 3/31/2003 *************** * Fixed a problem which began with 8.00j in which we do not always process member function instantiations. The result was that messages that should have been reported were not being reported. For example, all our 8.00 versions when examining the following code: template struct A { A() { unsigned n = -1; } }; A a; will dutifully report that n is being assigned a negative value. However under some circumstances including the placement of the template within a namespace under versions 8.00j and 8.00k no report was issued. The reason was that we misinterpreted the function as being library owing to a flag that was set but never reset. If you were to have used the +flf option (process LIbrary Functions) then the expected report would have been issued. * We were reporting an undocumented Informational message 1780. This message has been removed. * The #pragma message could be introduced into the preprocessor stream (with the -p option in effect) at places where the stream would normally be turned off. * We were issuing a syntax error (Error 10) for a non-type template parameter having an explicit pointer type as the last template parameter. E.g. template< int * > class A {}; * We were prematurely instantiating a template (i.e., instantiating before the standard required us to do so) and that resulted in runaway recursion while processing headers in the boost library. Instantiation is now more carefully controlled. * When a --e() option is used in an initialization expression there was often an unintended inhibition carryover to the next expression. Example: int *p = /*lint --e(910) */ 0; // Note about conversion is suppressed int *q; q = 0; // Note still suppressed. p = 0; // Note not suppressed. * A sequence of --e{} options within the same block could produce a performance hit. In one instance, through the magic of macros, 240 macro invocations produced 720 stack pushes that had to be examined on the way to producing an error message. We now coalesce similar inhibitions in the same scope. * The text of message 958 "Padding of __ bytes is required to align member ... " has been modified in the case that it is not a member that is being aligned. The word 'member' is replaced by what is being aligned. * If the name of a friend class is a template name of a template being instantiated we were not using the specialization (that is being instantiated) as the friend but rather the template itself. E.g. template< class T > class A { class B { friend class A; }; }; When this gets instantiated as A we were regarding the template A as a friend; we now properly regard A as the friend. * We were not always reporting when a template went unused. * We were giving an undeserved error 1065 (symbol not declared as "C") when a friend function not defined as "C" was found to have been previously defined as "C". E.g. extern "C" void f(int); class A { friend void f(int); ... }; * If two different modules contained a declaration of a symbol that was identical except that in the first module the symbol was declared with an extern "C" we would not notice the discrepancy and we would not issue the expected Error 1066. * We were not issuing the expected 1763 (Member function marked as const indirectly modifies class) in the case of returning an address from a member function. E.g., the following did not issue a 1763 for member function X::get(int). class X { char *pc; char & get( int i ) const { return pc[i]; } }; * When processing VC7 project files (.vcproj) we were producing null options: -u, -d, and -i for UndefinePreprocessorDefinitions="" PreprocessorDefinitions="" AdditionalIncludeDirectories="" respectively. These null options are usually ignored but could be a problem if the -split option is in effect. For this reason they are no longer produced. * When processing VC7 project files (.vcproj) we did not previously translate $(...) within string constants. We now translate strings containing $(...) into %...%. Thus: AdditionalIncludeDirectories="$(Library);$(Utility)" is now translated into -i%Library%;%Utility% * We now have minimal support in place for the Variable Length Arrays of C99. * Added support for the #pragma dictionary option of VAX C/C++ *************** Version 8.00k 1/29/2003 *************** * We were issuing undeserved Error messages 64 and 55 while processing the prototype of a function template having a parameter of a dependent type and a default value of a known type. Such constructs appeared in xstring, streambuf and istream within the Microsoft library. * We were issuing an Error 39 when we encountered an old-style class template specialization (one which failed to be preceded by "template<>"). For example: class A { ... }; Though obsolete, this form persists in older code. We now interpret this as a specialization and do not give the message. One such construct appeared in xlocale of the Microsoft library. *************** Version 8.00j 1/23/2003 *************** * An inline -sem() option would cause a parsing problem if placed just after an inline member function definition. * Owing to a recent change introduced in 8.00h, We were no longer processing subclasses defined out of line properly. The following would throw us: struct A { struct B; }; struct A::B { int f() { return k; } int k; }; * We were using the convention that the result of an assignment is not an lvalue. This is ok for C but not for C++ where assignment is an lvalue. We now properly assume an lvalue for assignments within C++ modules. * We were giving an unjustified 1764 (Reference parameter could be declared as const ref) when the parameter was passed to a const ref to a plain pointer. * Given the declarations: void f( int & ); void f( const int & ); we were reporting that f(10) was ambiguous. We now correctly deduce that the 2nd of the two functions is selected. * We were giving an undeserved 1762 (member function could be made const) when the member function was returning the this pointer as a non-const return value or returning *this as a non-const reference. * We were giving an undeserved 1762 (member function could be made const) when the member function contained an assignment to *this. * We were issuing an undeserved 564 (variable depends on order of evaluation) for: struct A { volatile int n, m; } a; ... ... a.n == a.m * We now support the C99 concept of designators. For example: struct point { int x, y; } P = { .y = 1, .x = 2 }; * Messages relating to the start of a loop were sometimes placed in such a way that they seemed to refer to the statement following the loop. This was causing confusion. We now employ the correct code location and if the statement is past it is simply not printed. * We were giving an undeserved 550 (q not accessed) even though q was being used in an expression of the form (q->*a). * We were giving an undeserved 818 (p could be declared as pointing to const) even though p was being used in an expression of the form p->*a = 0; * In the AdditionalIncludeDirectories attribute of a .vcproj file there was a possibility of a """ appearing as part of a quoted string. This represents a redundancy and is now ignored. * In the Microsoft conversion of a .dsp file to a .vcproj file the separator character for IncludeDirectories is retained as a comma. This is now correctly translated to a semi-colon. * We were reporting failure to open a file when an indirect file contained more that about 500 files and the --u option was being used. It seems that files were not being closed after being opened. Most of these files didn't have to be opened anyway and so it now not only operates correctly but is a lot faster. * Even though -ftg (don't translate trigraphs) was given we were nonetheless quietly processing many if not most trigraphs anyway. Now we give appropriate warnings. * We were not issuing the Misra complaint (Elective Note 960) about the lack of braces for the statement following an else. * Complex switch expressions could be misinterpreted as having a type smaller than the actual type with the result that we could give an unjustified range error when processing a case statement. * We no longer issue an Elective Note 950 (non-standard construct) when a C program contains a // comment unless the -A(C90) option has been issued. * We were giving an undeserved Elective Note 917 (prototype coercion) when a Boolean expression was passed to a parameter that was typed with a Strong Boolean type (using C) that was not some form of integer. * We were reporting in an Elective Note (953) that a label could be declared as const. * We were not allowing 'typename' to introduce a type within a using declaration within a template. * We were not properly processing the case when a template was instantiated within a member function. Member names would become visible and potentially interfere with the proper processing of the template. * The partial template specialization did not work properly through a typedef or other contexts in which an instantiation was not immediately required. E.g. template class A {}; template class A {}; typedef A X; When X would be instantiated we would find the general not the specific A. * We were issuing an undeserved Error 36 when processing a specialization of a function template that had a void argument list. * When the -cgnu option is set we now allow programs to specify std::name which picks up name within std:: if there and searches the global namespace if not. * We were issuing an undeserved 534 (Ignoring return value) when employing an assignment operator that was an explicit specialization of a template defining the assignment operator. This occured when using the COM libraries. * We were issuing an undeserved Error 26 (Expected an expression, found '>') while processing templates in the Boost Library. This could occur when a dependent type was used as a template subscript in a nested type-id. * We were giving a redefinition error (39) when an early use of a template specialization that did not require instantiation was followed by a template definition which was then followed by an explicit specialiation which matched the earlier use. We were triggering the instantiation prematurely. * When a template contains a second template, parameters of the first template were not available when the second template was instantiated. * Names of templates within template definitions and within template member definitions were not always being translated from the class template to the template class. For example the return value of f within A should be A and not A<<1>>. template struct A { template A f( A ); }; * We were issuing an undeserved 1521 (multiple copy constructors) when a template could match the prototype of a copy constructor. Templates, of course, can't serve as copy constructors. * We were not supporting conversions using template constructors. Thus the following code reported a type mismatch when b was defined. template struct A { }; struct B { template B( A ); }; A a; B b = a; * We were issuing unjustified Informational 754 (structure member non referenced) for members of template instantiations. * We were issuing unjustified Warning 1526 (member function not defined) for instantiations of member function templates. * When a #include is used where name does not include a .h it is possible to have a .h added automatically to the name by using the +fdh option. This feature has been extended so that if the name with the .h appended does not result in a found file then the original name was used. This was found to be necessary when using the Borland libraries in conjunction with some STL libraries. * We were not handling all the nuances of reference parameters for function templates. For example: the following gave an undeserved Error 64 (type mismatch): template void f( T const & ); void g() { f( "hello" ); } * The following gave an Error 36 (redefining A::B from template to class): struct A { template struct B; }; template< class T > struct A::B {}; * We were instantiating template member functions too quickly and too often. For example: template struct X { void f() { T a; } }; struct Y : public X { }; would result in Error 1080 (definition of Y not in class scope). We now follow the standard and do not instantiate a member function (of a template) until after it has been referenced. To force instantiation of all members of templates you may use the option ++template(80). * An undeserved Error 115 (struct/union not defined) would be issued in the second module of a two module program. It would be issued on the use of a const template class when an instantiation was required. * The STL Port library uses an unusual macro to form a #include which unfortunately contains blanks which we happened to squeeze out. We now retain the blanks. * We were not supporting template object parameters as dimensions of array parameters of function templates. Thus template< unsigned N > void f( int (&)[N] ); could not be invoked as expected. * With multiple (overloaded) function templates and explicit template arguments we were not always finding the right template. Thus for template< class U > void f( ); template< class U > int f( int ); ... int n = f(3); we would arbitrarily find f() and issue an error message. * We would not properly handle explicit template arguments for function template members. Thus, in: struct R { template< class U > int g( int ); }; R r; int n = r.g(3); we would treat the '<' following "r.g" as a comparator. * The following sequence did not always work. typedef B BI; template<> void BI:f() {} We might report erroneously that f was not a member of B if B was not yet instantiated. We now force an instantiation regarding this to be an instance in which the type must be complete. * We could under some circumstances erroneously take identically named templates from different namespaces to be the same. * We were sometimes not seeing a global scope operator when used on something that is supposed to render a type. For example the ::A in the following got confused with the class A in which it is embedded. namespace X { class A { T<::A::C> t; }; } * We were stumbling over the use of __declspec() following the start of an explicit template specialization. For example: template<> class __declspec(...) A<...> ... This particular combination required look-ahead that was too dumb to handle it. * We were having problems with the proper identification of the name of the template when instantiating a template class from a partial specialization. For example we would issue unjustified 1073 (insufficient number of template parameters) for the following: template struct C{}; template struct C { C (); }; C< float, double > x; * We were not supporting all cases of externally defined templates. E.g.: struct A { template struct B; }; template< class T > struct A::B { }; * We were issuing an unjustified Warning 512 when a symbol declared as static was later redeclared as non-static. For example: static void f(int); ... void f(int n) { ... is by now universally recognized as being valid. * We were not supporting explicit self-qualification of declared items within a class template. E.g. template< class X > class Y { void Y::f(); }; Y a; would result in undeserved Error 1040 (Y<<1>>::f not legal) * We would select an explicit specialization over the original template when explicit template parameters would indicate that the caller intended the original template. For example, in the following we previously would pick the specialization but now we revert to the template. template< class T, class U > T g( const U& u ); template< > int g( const unsigned& u ); ... g(4000u); * We were issuing an undeserved Error 114 (inconsistent definition) for a template definition during the 2nd and subsequent modules when the template contained an overloaded member function parameterized by dependent types. * We were getting confused by a member template that could serve as a copy constructor * An out-of-class definition of a member function of a template could cause an undeserved Error 36 (redefining the storage class). * We were not reporting that the following call is ambiguous void g(int); void g(const int &); int n; ... g(n); // ambiguous * In function overload circumstances involving function templates we were employing previously instantiated versions of a function template which the standard specifically excludes from consideration. This could result in the wrong function being found. * Error suppression options were not properly employed when function and template definitions were saved for later processing. For example, the 452 was not being inhibited in the function f() below. class A { //lint -e{452} void f() {} int n; }; * We were not finding some of the source files in a .vcproj file. Specifically we were not finding files within more that one filter. Thus we would not find the RelativePath in the following: ... ... ... ... ... * We now support the Borland project files (extension == .BPR) This is an XML oriented description similar in principle to the .vcproj files of MS .net. This allowed us to leverage off our prior work. *************** Version 8.00i 9/11/2002 ***************