This is our bug fix list for patches to FlexeLint/PC-lint Version 7.50 ********** Version 7.50a 9-25-97 ********** * When in C programs (this does not affect C++), calls were made through function pointers (without using the indirection) we would give a spurious Warning 534 that was unwarranted. Examples: void f( void (*fp)() ) { fp(); } void g( int (*fg)() ) { (void) fg(); } * When a C class contained a C++ component we gave an undecipherable message (Error 148, member ... previously declared at ...). * A function dubbed as equivalent to __assert() did not have the property that if its argument were 0 it would not return. * We were giving 613 on an OLE call that modified a pointer - added (documented) a new flag -/+fai * We were issuing a 424 (Inappropriate deallocation) for data that we hadn't seen merely because it was unknown and had been returned. * Even though a member pointer was zero'ed on each path within a try-catch sequence, we still reported Warning 1540, pointer member neither freed nor zero'ed by destructor. * We were not allowing a vacuous enumerator such as: enum color { }; This is explicitly permitted in the standard. * We were not allowing member arrays to specify their dimensions in a privileged manner. For example, Given the following: class A { enum { SIZE }; int a[SIZE]; }; int A::a[SIZE]; // couldn't find SIZE int A::a[A::SIZE]; // member not accessible. * We now issue an Error message (90) when someone uses -e(#) outside of a lint comment. * We were ignoring one-line error suppression when a string ended with a \\. E.g. int n = "\\"; //lint !e64 this didn't work. * We were complaining (Error 69) about casts from derived to base. These are legitimate. * With +feb set (allow enumerators as bit fields) we were erroneously reporting an error when we assigned an enumerator to the enumerator bit field. * we now retain the enum basis of a bit field * We were issuing Internal Errors 214 and 219 when using notation std::vector * At preprocessor time we now treat enumerators the same whether they are part of a pure enumeration such as enum { red, blue }; or part of something more complex. * We were treating the following incorrectly: typedef enum {FALSE, TRUE} Boolean; #define FRED FALSE #if (FRED==FALSE) * At preprocessor time greet enumerators with a Warning. * We were reporting a false Warning 624 (typedef is redeclared) when a tagless struct bears a tagless union bearing a tagless struct. * We were giving a false Error 126 (Inconsistent Structure definition) from LOB files where a common element was a tagless struct bearing a tagless union or tagless struct. * We did not instantiate Templates when we only saw a pointer and therefore we gave a Warning 1404 when we saw a delete of such a ptr ********** Version 7.50b 9-29-97 ********** * The fix to remove internal errors 214 and 219 (7.50a) resulted in our not finding typedef types declared within templates used within the same template as an actual template argument. ********** Version 7.50c 10-8-97 ********** * We should not give note 1923 (macro could be made const) within C code. * Retain #pragma with -p option * Pass #pragmas through with -p option to use as part of a production pass * In MSDOS, it was not possible to inhibit warnings specifically about operator!= because '!' was taken as a comma. Fixed to make ! after operator to be not special. * We were reporting corrupt object file (304 code 23) for an object file produced by combining two modules containing the same local struct such as: struct A { int a; }; * ASSERT(p) was not working. We were giving a false 527 (Unreachable) as well as false 730 and false 746. * We are now automatically suppressing 730 when employing a function with semantics equal to assert. * Message 806 was given for int bit fields that are larger than a char. * We were reporting a 1904 for lint comments. This doesn't make sense since the only way of incorporating a lint comment within a macro is via the old style. Hence we suppress 1904 for lint comments * Altered install.exe so that the order of files in STD.LNT is such that the author stuff comes first and the options.lnt comes last. * Template instantiations sometimes (but not always) did not find their way back into the namespace of the original template. This occured in the Rogue Wave headers among other places. The symptom was a false Ambiguous Reference (1075). ********** Version 7.50d 11-10-97 ********** * We gave a confusing Warning 533 on the second return of: int f() { ... return; ... return 1; } * Inhibited 506 (constant value Boolean) in constant expressions. Eg.: char password[ 3 < 10 ? 10 : 3 ]; * We incorrectly reported (with a 1007) that a pure specifier was used with a non-virtual function when the use was within an extern "C" block. * Messages 413 and 613, when issued for the right hand side of binary + or - would give the wrong symbol name or no symbol name. * When the address of a (non-static) member function was taken whether implicitly by mentioning the name of the function or explictly by using the & operator we would sometimes regard this as typed function rather than member function. Syntax errors were being given as a result. * Even though -clc6 was supposed to activate 'inline' it did not because of C++ keyword removal for C programs. To fix this, -clc6 causes inline to be re-added for each C module. * We were complaining (676) about a possibly negative subscript with: void f( unsigned u, unsigned v ) { if( u ) ... if( v < u ) a[v] = 0; unsigned's can never be negative. * We were complaining (676) about a possibly negative subscript with: int limit = 0; for( int i = 0; i < limit; i++ ) a[i] = 0; * When a return semantic was specified with a || operator as in: -sem( name, @p == 0 || @p == 1p ) it didn't always work. Subsequent use of a returned pointer was not always being checked for NULL. * If a pointer p is possibly NULL we did not avoid a warning with the construct: p ? new[ strlen(p) ] : 0 * We were not complaining when a class has itself as a base class. * The sequence void */* comment */x; did not work. * We are now supporting class-specific constants as in: class { const int N = 100; ... } as per the evolving standard. ********** Version 7.50e 1-10-98 ********** * There was a limit to the number of -function and -sem options that was too severe (256). The limit has been raised to 16 million. * A cast to a pointer to STRONG from a const was not picked up as a pointer to the strong. Thus: INT *p; ... p = e ? p : (INT *)0; resulted in a mysterious strong type warning * We were not comprehending: template { ~X(); }; * When using LOB's, we were reporting redefinition of in-line friend functions (where the the friend function is defined within a class) * A crash would sometimes occur with multiple includes of afxwin.h * Our 1746 (could be made const reference) was being issued when we were actually modifying the passed by value struct through the use of the += operator. * We did not issue a message on the possible truncation of addition when int's are 4 bytes. E.g. long long ll = i + j; * We were reporting a 429 (custodial ptr has not been freed) in the following case: void *f() { int *p, *q; p = malloc(N); if( p ) q = p; else ... } We now inhibit 429 in the event that there is any path in which the pointer is either freed or assigned. Either that or omit paths for which the pointer is NULL. * If a FILE* variable was assigned from both stdin and also from an fopen'ed return pointer then when we would go to close it we got a warning: 424 "Inappropriate deallocation (free) for static data". * Were getting a spurious error 90 with the -p option. (when processing comdef.h) * Added a define of __uuidof to co-msc50.lnt to support comdef.h * Added member class templates and member function templates to support constructs in comdef.h * Added the export keyword (syntax only) as per ANSI specs * When declaration prototype differs from the definition prototype by a const (or volatile) applied at the highest level to a parameter we now complain (as before) but equate the two rather than create a new overloaded function as we had done in the past. This follows the practice of compilers that equate (but do not complain). * Informational message 799 about a numeric constant (being too large) could have had garbage appended to the end of the constant in the presentation of the message. * Even though we were in the scope of a #if 0 we still complained about a numeric constant being too large. * The constant 0x800000000UL (that's 8 zeros after the '8') was typed unsigned long. It is now typed unsigned long long. We had previously taken the 'L' to mean that the long long was reduced to type long. In general, the 'L' suffix does not lose precision. * When we ascertain that a pointer is NULL we do not strip off allocation-type bits so that we occasionally reported an inappropriate disposition on a pointer we know is NULL. * Adjusted the assumed screen height (when producing help information) to the text height of the window (at least in NT) ********** Version 7.50f 2-18-98 ********** * We were giving an unwarranted 1522 (converting pointer to array-of-derived to pointer to base) when a[i] is passed to a reference to a base class (a is an array of derived class objects). The problem is we were ascribing a length to &a[i] that equaled the number of items left in the array rather than a length of 1. * We were complaining with a 1927 that an array member was not in the initializer list. Arrays can't go into initializer lists. * We were reporting Messages 55, 59, 60 and 1058 when we are outputting setw(k). This has to do with dependent types. Specifically template functions whose parameters are dependent template classes. * Fixed the -p option so that #pragma's reflected in the output will not have '('s and ')'s dropped. * When an indirect file contained errors the line numbers may have been off if there were /* ... */ comments within. * If a virtual member were hidden it could not be overridden. The standard explicitly provided for overriding hidden members. E.g. struct B { virtual void f(); }; struct D : B { void f(int); }; struct D2 : D { void f(); }; /* D2::f() overrides B::f */ * int Initializers of floating point variables would result in a sticky value associated with the floating point quantity that would not go away with subsequent assigns. * There was a problem with #pragma asm / #pragma endasm. When activated it would not recognize a preprocessor-off state and not restore to the status pre-#pragma asm. * Passing a suitably casted pointer variable to a function expected to receive a long will now remove the custodial property associated with that pointer. * When the initializer of a static const member contains a cast, the type of the members was not correctly identified. E.g. class X { static long n = (int) 3; }; n would not have the right type. This arose in connection with processing the HP headers. * We were getting Error 1039 (not a member of the class) when processing a function member of a class template when a function member was overloaded with the same number of parameters and one of the parameters was a dependent type. * We were treating the argument p in void f(p) const char *p; { ... } as char * because we were treating the const as part of the prototype. * for wscanf, etc we were not expecting a wide-char ptr for the %[...] format. * const declarations within namespaces were getting redefinition errors with multiple modules. * template specializations within namespaces used in multiple module situations would result in Messages 770 (tag defined identically) and 39 (Redefinition) * undefined types within templates such as T::size where T is a template parameter were assigned an unknown type. This would appear to be identical to some other type such as T::alloc. When member functions were overloaded on the basis of such type differences we would not understand that they were two different types. This arose in STL. ********** Version 7.50g 4-7-98 ********** * When processing code that is skipped over, especially in a sequence of the form #asm ... #endasm, we issued an Error (146) for any constant that began with a "0B", declaring that it is a binary constant. * We were issuing a 1927 (did not appear in constructor initializer list) when the item in question was an anonymous union * We were not handling using declarations properly. We gave an ambiguous reference when the target of a using declaration can be obtained via two different routes. * We not support #pragma once (don't include the file twice if it has this pragma in it). -cmsc automatically enables once. once is added as a new pragma action so that +pragma(once,once) will mimic the Microsoft compiler. This materially reduces the time to process Microsoft headers. (improved speed 49 to 43) * Added a new compiler option -cgnu that defines _LANGUAGE_C_PLUS_PLUS for C++ modules and LANGUAGE_C for C modules * An unwarranted 429 was issued (Custodial not freed or returned). If the return of the custodial was made at the end of an if or else branch then we would ignore properties developed in that branch. * If a user is at warning level 3 and he sets -w2 we now suppress all messages at levels 3 and 4. In general, a warning level reduction suppresses all messages above that warning level. * The C++ Standard now defines an order of initialization for: int a = 10; int b = a + 10; int c = b + 10; when these occur in a single module in that order. We were giving a false 1544 (value of 'b' depends on order of initialization). * enum color { }; (vacuous enumeration) is now allowed. * We were not supporting an enhanced search when processing namespace members. E.g. namespace X { void f(); void g(); } void X::f() { g(); /* can't find */ } * The following macro example: #define a(x) _a(x) #define b c.b a(b); resulted in: _a( c.c.b ) Macros should not be doubly evaluated according to the standard. * The use of the global scope operator from within a namespace would sometimes search the namespace. * Added a --ppw() option and placed "--ppw(import) +ppw(import)" options into the co-msc50.lnt compiler options file. The net effect is to treat #import as a no-op. It would previously try to read the file. * We were reporting a typedef not used when the typedef was declared and used only within the class. Same with static const's used as compile time constants. * When a typedef for a function declaration appears within a class it should be typed as a static function type, not a member function type. * We are now supporting Microsoft's i64 suffix for 64-bit int's * Explicit namespace scoped names did not always pick up the correct name. * We now suppress Elective Note 950 for C++ style comments within a C program when the C++ comments are opted out via conditional compiler statements. * We are now supporting explicit function template arguments. E.g. call of the form: convert(3.5) * Fixed a lob bug when dumping a namespace declaration. ********** Version 7.50h 6-4-98 ********** * When lob's were prepared of windows.h we would give the message Error 126 Inconsistent structure definition (tagARRAYDESC). This was traced to placing references to tags into the class symbol table rather than the nearest namespace symbol table. * When we saw a label for an identifier that had previously been declared as a type we issued an Error 10 (expecting identifier) thinking that the whole is a declaration rather than a labeled statement. * We were not properly distinguishing between templates with different argument lists when the arguments were for non-type parameters. Thus T<2> and T<3> were, in some cases, not properly distinguished and were thought to be the same type. We would then complain when we saw both void f( T<2> ); and void f( T<3> ); reporting that the second was a redundant declaration. * Message 911 was insufficiently precise. We now give a different message for when an array is promoted to pointer vs. when a sub-integer is promoted to int. * When giving a message about a typedef that was a member we would, under certain conditions, use the name of the class rather than the name of the member. * We were getting a corrupt object file (code 26) when processing the Borland OWL library * We were getting a corrupt object file (Error 304), code 3 when unusually long path names were used. * Some error messages were longer than our message buffer. This has been changed to allow for growth. * We failed to retain some flags about members within a lint object module. The result was that if the only usage of a member function was in the 2nd or subsequent lob file then we would issue a 1714 (member not referenced) * We fixed a bug having to do with value-tracking of char pointers which have been assigned string constants of length 0 ( this may affect other string constants as well ). In the sequence: if( !s ) s = ""; for( ; *s; s++ ) { ... } we would complain with Warning 661 (Possible access of out-of-bounds pointer). We knew that the length could be 1 so that the sequence s++; *s would cause the complaint. We now take reasonable deductions based on *s being non-zero. * When a class template N is defined within a class A and N has a member function that returns N or a pointer or reference to N we couldn't seem to process the definition. E.g. class A { template class N { N f(); }; }; template A::N A::N::f() {} * We are now supporting the Microsoft's #import. If a #import is seen we substitute an extension of .tlh and strip off path information from the filename. The file is then included as usual. Options on the #import line are ignored. import must be enabled via +ppw(import). This option has been inserted into co-msc50.lnt. The earlier meaning of #import as a conditional include was only used by the 'next' C compiler to mean conditional include. An appropriate option has been placed within the 'next' compiler options file to transfer the semantics of c_include to import. * We were getting a corrupt object module (Error 304, code 23) when processing a module with the same enum name defined differently in different functions. ********** Version 7.50i 8-13-98 ********** * We were issuing a Potentially Confusing Initializer message (651) when an object (i.e. not an aggregate, has a constructor) appears in an initializer without a left curly when a left curly appeared earlier in the initializer list. * We were issuing an Internal Error 213 for a string constant within a template within a template. * We were reevaluating the switch expression for every case statement. This meant that if the expression had side effects such as switch( *p++ ) we would bump the pointer twice and give an unwarranted out-of-bounds message. * the state of variables after a catch block sequence should not reflect values produced within catch blocks that directly return. * pr.exe now supports long filenames. It had to be recompiled for 32 bit processing and so is an NT console mode application running under Windows/95, Windows/98 and Windows NT. The DOS version is still available as pr-dos.exe * When a reference parameter is assigned a new allocation, and if later we use the pointer in a subscript reference, we complain (815) about an "Arithmetic modification of an unsaved pointer". * We were processing in-class function definitions for inner classes too early so that, for example, class A { class B { int f( A *p ) { return p->x; } }; int x; }; would not work. * The asm(...) construct did not work with C programs. * A problem with __finally has been fixed. We would under some circumstances report that _finally was not reachable when it was. We also would inadvertently consider _finally as dropping through when it would not. * An undeserved 114 (inconsistent structure declaration) is being issued when two or more modules include a header containing a class template definition which in turn bears a function template definition. * In an effort to allow the following (strange) construct (found in Microsoft's COM yielding Error 10, 114, 601 on the 2nd and subsequent modules): typedef int GUID; struct X { GUID GUID(); }; (i.e., a structure uses a typedef named GUID and then defines a member called GUID). To cope, we now undefine the members after every module. If this creates unforeseen problems the change can be reversed with a -fum (turn off the Undefine Member flag). * We were giving a false 809 (returning the address of an auto) in the following case: int *f( int *base ) { int *p = &base[2]; return p; } The problem was that we were erroneously flagging the pointer p as pointer to auto. * Under some unusual combinations of function templates we could bomb out (Illegal Operation under Win 95, core dump under Unix, etc.) * The install program of PC-lint has been fixed so that if the customer enters the name of a compiler directory that contains blanks, we place the name within quotes before giving it to the -i option. * We were consuming an excessive amount of space when multiple modules were being processed. This resulted in unusually slow operation. This was traced to a memory leak when template functions were embedded within templates. * We should not be escaping an unquoted \ when we stringize an argument. E.g. #define Q(x) #x Then Q(\n) should yield "\n" and not "\\n" * We now attempt to directly handle the '@' initializer of compilers for embedded systems. A declaration such as int a[10] @0x2000+2; is greeted with a specific warning (430, which can be suppressed) but otherwise properly parses the construct. The option -cwh still defines '@' to be a _gobble and so should not be used to test the new scheme. If the experiment goes well -cwh will be redefined. * We added Microsoft 6.0 to the install script. * We now support declarations within if, while and the 2nd for clause. * An initializer for an aggregate that is embedded within another aggregate can be an aggregate. For example, the following is valid in C++ (but not C). struct A { int a; }; struct B { A a1; int z; }; A a; B b = { a, 3 }; ********** Version 7.50j 8-18-98 ********** * An assignment of the form: p = test ? q : 0; where p and q are pointers would assign a value to p with the implied possibility that p referenced 0 bytes. ********** Version 7.50k 11-6-98 ********** * +libdir(directory) would inadvertently add to the list of search directories not the directory passed as argument but truncated by two characters on the left. Thus +libdir(D:\compiler) would have the effect of a -i\compiler (in addition to the libdir settings). * We now take into account overloaded functions (and overloaded operators) from nominated namespaces. Thus: namespace X { void f(int); } using namespace X; void f(double); void g() { f(0); } // calls X::f(int) previously we would regard f(double) as masking out X::f(int). This problem would especially evidence itself with operator<< and operator+. * We should not issue Info 730 when the argument is a constant. * We were giving error 1050 when using the list<> template from the standard template library. This was traced to our recognizing the name of a base class rather than the name of a class defined in an enclosing class. * We would bomb out when an untagged class contained a function template. E.g.: class { template void f(); }; Such an example appears on page 112 of Effective C++, 2nd ed. * Thanks to our recent change (7.50i) supporting declarations within if's we introduced a new bug: if( unsigned(i) == 2 ) was taken as an ill-formed declaration of i. * A pointer to a template class would not always be instantiated when it should be. E.g. X *p; ... void f() { *p = 3; ... requires an implicit instantiation to detect the operator= which was not always being done. * When the lib-stl.lnt options file is used in conjunction with the ATL header files we would give bogus messages starting with Error 39, redefinition of ATL::CComObjectRootEx. The problem would go away if the -template(1) option within lib-stl.lnt were omitted or neutralized. * When two pointers are compared for equality and if one is possibly NULL then in the range of the equality we would assume the second to be possibly NULL even though the second were marked as certainly not NULL. The equality comparision between pointers has been adjusted so that this sort of thing would not occur. * We were not allowing: extern T f( T (*)( T ) ); where T is some typedef. * We now support the 'charize' indicator (#@) of Microsoft. For example: #define C(x) #@ x Then C(a) becomes 'a'. * We were getting Error 49 while processing Microsoft's afxtempl.h This was traced to our not allowing template parameters to be redefined. They now can be redeclared and they follow the same scoping rules as other identifiers. * We were not able to process STL headers for the Borland 5.x compilers. By carefully monitoring the behavior of the Borland compiler we were able to deduce that for headers that are #included without a .h extension (an hence a .h is appended) the symbol __USING_STD_NAMES__ must be defined. Otherwise this symbol must be undefined. With this trick in play, STL headers are cleanly negotiable. * In the Rogue Wave headers (for example in ep_scntn.h) we are issuing some strange errors (1054, 10, 1073) declaring that we were expecting a type. The problem was traced to a dual usage of 'std' as both a namespace and a function. Compilers are supposed to be able to disambiguate on the basis of context which we were not doing. * Within a template allow: T *p; ... p->~T() ... for any type T. * We were not handling function template parameters whose type was defined as a subtype within one of the parameters. Eg. template void f( T, T::name ); We would issue 1025 (no function matches) and, at wrap-up time, 1734 (had difficulty compiling). * The GNU compiler allows for explicit indices in array initializers. e.g. int a[100] = { [10] = 10, [90] = 90 }; This syntax is recognized and diagnosed (Error 26) but if the GNU compiler option is given (-cgnu), no error message is produced. * There were a number of wrap-up anomalies when items were embedded in namespaces. These included enumerators, const integers, and unmerited 765's (function could be made static). * The line limit is too small. When a line exceeding 600 characters is encountered a message 91 prompts the user to use option +linebuf to increase the size of the line buffer. * We were bombing out on a syntactically illegal program of the form class X { X( y ); }; where y was undefined. * We now support 'plain-prototype' function templates. A plain prototype is one without template parameters. For example, template void f(int); To invoke a function of such a template one must use explicit template arguments, e.g., f(12) * A special error message (147) is now given when sizeof() is given two arguments. This is to cleanly support compilers for which the two arguments have meaning. ********** Version 7.50L 12-17-98 ********** * When processing lob files that were produced from files that had namespaces within namespaces we would give an access violation * Use of the -function option in conjunction with lob's could cause an access violation. * The preprocessor statement: #include 00DEG (i.e. where the lead character is a digit) would not work properly. * The state of variables at the end of a __try __except block was incorrect. It would reflect the state of variables at the end of the __except portion even if this portion ended with a return. * We had problems processing the definition of a static data item of a class template having a non-type parameter. E.g. template< int N > class X { static int data }; template< int N > int X::data; // Error 1062 Unfortunately atlcom.h has such a class within it. This was introduced in 7.50k when we were attempting to fix a bug in processing afxtempl.h (producing Error 49). * When we encounterd an initializer of the form mem() within a constructor initializer list and if mem is typed class and if the class has no constructor we issued erroneously Error 26 and 64. This is now ignored and if the member has no initialization in the constructor a warning is issued. * For PC-lint (LINT-NT.EXE) we now create a temporary file within the directory identified by the TMP environment variable. (temporary files are used only in producing lob's with option -lobbase active). * A false error 1061 could be given when a member function accesses a member of an anonymous struct which is a member of the class or (more likely) a member of an anonymous union which in turn is a member of the class. * An environment variable within the extended command line surrounded by %'s if not defined will now result in the null string. * Someone was getting an Error 303 (string too long, use +macros) but was getting no relief from using +macros. * In processing the header files for the object space STL we were getting Error 1039; e.g. 'deque<<1>>::insert(...)' not a member of class 'deque'. We were getting confused by two different representations of a partially specified template. * Increased the number of user files from 4096 to 6400 ********** Version 7.50m 12-29-98 ********** * We erred in converting %xxx% to NULL if it couldn't find xxx as an environment variable. This was apparently affecting -format. It could also adversely affect -sem and -d and so the %xxx% feature was disabled for these options. ********** Version 7.50n 1-4-99 ********** * Recovery from syntax errors is now designed to pass completely over braced expressions rather than stopping somewhere within (usually before the closing brace). This increases the overall sanity of the recovery process and removed a recursive loop. * Under some error conditions a struct could have a member typed to be the struct itself. This could cause an infinite recursive loop in initialization and a subsequent crash. * Our fix that produced 7.50m was not adequate in that it did not disable the replacement for environment variables in options that began with -"format... ********** Version 7.50o 3-31-99 ********** * We now allow a pointer difference to be specified as long long. (+fdl ++fdl). * Added shift and length information to Warning 572 * We were not processing lines of the form: #include /* comment */ * Line information for each candidate function has been added to the ambiguous function message (Error 1023). * We were issuing a false 1748 on class X when the base class of a diamond formation itself inherited non-virtually from X. * The Franklin compiler's stdlib.h contains a construct: void free( xdata *p ); that we stumbled over badly. We now give an error message that can be suppressed. * The construct: p = new Type; if( p == 0 ) return; ... would result in a false warning 429 (Custodial pointer has not been freed). This would only occur if option -function(operator new(r)) were in effect which it is if you're using lib-mfc.lnt. * The obsolete options -ze and -za were not checking for extraneous characters with the result that if a mistake was made in supplying a -zero option (as in '-zeros') it would be accepted (and treated as -Ze) * A using declaration in which the indirect name referenced a template was not being handled correctly. For example: using std::vector; would result, when vector was later referenced, in strange diagnostics, such as changing the storage class. * We give a false 1540 (pointer member not freed by destructor) when the pointer is passed as a modifiable operand (either non-const reference or non-const indirect pointer) to a function. * The install program has been fixed to allow for spaces in directory names as well as long filenames wherever the user employs them. * We would issue an unwarrented 304 (Corrupt object file, code 23) when processing a lob file containing some complicated template configurations involving template arguments containing template instantiations. An example could be found in MS header . * We could issue a 729 (not explicitly initialized) for a created variable (named "____temp...") when processing lob files * Default template parameters provided in a class template declaration were being overridden (to nothing) by a subsequent class template definition. * We were giving an unwarranted Error 126 (Inconsistent structure definition) when reading in a second lob file which had an identical structure to an earlier lob file. * We were getting an unwarranted Error 126 when combining lobs that had namespaces that were not identical. As long as they are consistent they should be OK. * We were issuing an unwarranted Warning 578 (Declaration of 'X' hides 'ns::X') for the following: namespace ns { void f() { class X {}; } } * We would not find a subclass when used as a qualifier within another subclass. E.g. struct X { struct Y { void f(); }; struct Z { using Y::f; }; }; Here we would not find the "Y" of "Y::f". * We would fail to recognize a template type parameter when the parameter was part of a function within a class within a class template within a class. * We no longer report that %ls and %lc are non-ANSI. * We now allow a variable N, declared as const int N = 0, to be used as a null pointer (according to the standard). * We were processing function definitions containing the specifier: extern "C" in such a way that any interior function call was C-like and could not contain template function calls. ********** Version 7.50p 6-11-99 ********** * choose.exe, a program invoked by config.bat, would not run under all versions of Windows 98. Accordingly, we have renamed choose.exe to choose16.exe, are now supplying a 32-bit version called choose.exe. This is available from our web site. * When a custodial pointer is passed to a const ref parameter we claimed that the custodial has not been freed. * We did not always remark when a custodial pointer within an inner block was not freed. * We were getting Error 304, "corrupt object file, code 23" when a template argument was a member (some class type) of another template. * We were issuing a false 424 (Inappropriate deallocation for 'constant' data) when deleting a pointer that was a reference parameter. * We were giving a false 1075 (Ambiguous reference) to a symbol in a namespace made accessible with two different using declarations. E.g. let S be a class within namespace NS. Then the following would do it. using NS::S; using namespace NS; S x; * We gave a false 514 (Unusual use of a Boolean) when a template non-type parameter was typed Bool and then cast to int. * We were giving an undeserved 506 (Constant Value Boolean) when expanding a template. 506 is now suspended during template expansion. * We did not complain about negative array dimensions. We now issue Error 92. * We did not support operators of lower precedence than '>' as template arguments. Thus: A was not parsed correctly * We were somehow not computing the value of !e even though we knew the value of e. * For C++ Builder we introduce a new flag +ftr that will truncate to 8x3 any header name. * When assigning pointers to member functions we would complain if the classes were not identical. Following the compilers we do not complain if the RHS class is a subclass of the LHS class. * When assigning pointers to member functions of the same class but with different const'ness, we got it wrong. We would complain if the RHS was const; now we complain if the LHS is const. * Merely using new could draw a Warning 1550 (function may throw an exception). The problem was traced to #including the file afxtempl.h which in turn includes new.h which includes new which contains a redefining declaration for operator new. The 'problem' goes away if you define symbol _NEW_ which we now do in co-msc?.lnt * Although we were reporting (Info 774) that the first if below always evaluates to True we were not reporting that the left side of the second if also always evaluates to True. int i = 3; if( i == 3 || g() ) ... int j = e; if( j == 3 && g() ) ... * ARGSUSED did not work for functions which contained catch blocks. * One of the Rogue Wave headers had a recursive template definition that would cause our product to blow up with a runaway recursion. The specific syntax is: template class A { enum { value = 2 * A::value }; }; * We were giving Error 304: Corrupt object file, code 23 When processing some unusual template situations. * The option --emacro(534,645) did not work properly. The ')' was missing from the resulting macro. * Processing templates at the end of a module could establish the wrong namespace at the start of a new module with many confusing symptoms including the possibility of a crash. * We were giving a false 304 (Corrupt object file, code 28) when processing a lob produced from StingRay headers. * We were giving a false Error 126 (inconsistent structure) when processing lob modules. * A binary operation involving a floating constant on the left and a long long (64 bit) integer on the right would be falsely flagged as non-constant and would elicit a false 34 when used in a constant- requiring situation. * We give a separate and suppressable message (93) for when a string argument to a macro is split across several lines. Apparently the Gnu compiler accepts this and some of our customers depend on it. * A reference of the form: a.T::y where a is an X, T is a typedef within X, and y a member of T, was not parsed properly and an Error 1013 was the result. * The type of the result of the relational operators (==, !=, >, >=, <, <=) and unary negation (!) was previously int but is now dependent on the state of the +fbo (Boolean) flag. If the flag is on, (it is on by default) the result type is bool which is in agreement with the standard; otherwise the result type is int. * The construct -function(exit,myexit)) caused a protection fault owing to the double right paren * When a function declared within a namespace was defined outside the namespace we did not support the namespace while processing the prototype. Thus void N::f( T x ) { ... } would not be processed correctly if T were defined within namespace N. * We had a runaway recursion whose symptom was a protection fault when attempting to instantiate a template with the following recursive definition: template class A {}; template class B : A< B > {}; Such a recursion appeared in one of the Rouge Wave headers. * We were issuing a false Error 39 when processing Gnu headers. The problem was traced to a specialization declaration followed by the class definition followed by the specialization definition. For example: template class C; template<> class C; template class C{}; template<> class C{}; We failed to mark C as a specialization and therefore erroneously applied the definition for the class C to the specialization * We now support the __property keyword of Borland's C++ Builder. The keyword is enabled automatically with the -ctc option. This support is at the level of syntax only. We do not fully support the semantics of this keyword. * The meaning of _ignore_init was extended to apply to function definitions where the function definition is now ignored. This is useful for processing functions whose definition consists soley of assembly code. * We now support class template partial specializations. These were needed to support Rogue Wave headers used by Borland's C++ Builder. * A problem that was fixed for 7.50f has caused problems for some users. Specifically &a[i] can be regarded as specifying an area whose length in elements is either 1 (single element interpretation) or N-i where N is the length of the array a (the subarea interpretation). The subarea interpretation was changed to the single element interpretation in 7.50f when it was realized that arrays of derived should not be passed to pointers to base classes. But many C programmers need the subarea interpretation. It was not always clear what the problem was and the alternative to &a[i] is a+i and that appears to be less descriptive. Ergo, for C++ style objects (technically, classes that are not aggregates) we now take the single element interpretation. For all other data we take the subarea interpretation. * We have fixed a problem that arose with the Borland headers. The proototype void f( X::T ); would not be parsed correctly if X were both a namespace and an array with the array intercepting. We now correctly ignore the array and use the namespace. * With this patch level, we're tentatively claiming support for Borland's C++ Builder. There is a compiler options file called co-cb.lnt and an environment file called env-cb.lnt ********** Version 7.50q 7-7-99 ********** * We were inadvertently giving the wrong precision (2) to Boolean expressions (relationals, unary !, etc.). This meant that we would report on: bool x = n > 0; as a loss of precision. * We now always accept bool in a Boolean context even if a strong Boolean is defined. * We now support the ':: template' construct necessary to support the notion of a template-time invocation of a template. This was used in the Borland library. * Template invocations of undefined templates are ignored at template-time. Such a construct is used in the Borland library. * We were not using the 'typename' keyword to bypass our test for typeness with the result that we were not parsing a compound name properly as a type and were thereby issuing unnecessary errors at template-time. * We were giving the wrong line number when issuing some messages (specifically 1711) about classes. The line number designated the first declaration of the class, not the definition. * We were issuing a false 39 (Redefinition) when processing a template within the Borland headers. The problem was traced to a faulty template argument deduction. The T of "const T*" was deduced to be "const char" when the argument was "const char *". It should have been "char" * When defining a function template of a class template outside the class template we would (occasionally) give an unmerited Error 1064 (Inconsistent template parameter list). Such a construct appeared in Borland's C++ Builder libraries. * We were not processing a double > within the context of a default template argument speciifcation. For example: template > class ... Such a construct appears in Borland's C++ Builder libraries. * We were giving an undeserved Error 36 when we declare a friend function template within a class and there was a prior declaration of the template. * A mismatch of template parameter names would sometimes confuse our parse such as: template class A { T a; }; template class A; We might use

against the definition of A and not identify T. * An underserved Error 64 occurred when outing to cout (cout << something). This in effect passes cout to the first parameter of the function template for <<. The parameter is typed basic_ostream< char, T > where T is the template parameter. cout is typed basic_ostream< char, char_traits >. A prior creation of the type basic_ostream< S, Q > where S and Q were template parameters superimposed itself at the wrong time. The error corrected could have arisen in a number of other circumstances when complex template parameterization is employed especially with repeated classes as the example above. * When a conversion function is typed reference to pointer or reference to class as in: class A { operator A*&(); operator B&(); }; Then the implicit use of that conversion function could result in an undeserved Error 64 suggesting that you couldn't convert from a reference to a type to that type. ********** Version 7.50r 9-24-99 ********** * We were not allowing a cast of the form: (_bit). * We would erroneously report Warning 533 when a function defined within a namespace would disagree in return mode from a function with the same name defined in the external scope. * We were not supporting a combination of inheritance and template instance matching for a function template. For example: template< class E, class T > class B {}; template< class E, class T > void f( E, B ); class S : public B {}; void g( S s ) { f( 'a', s ); } would give a type mismatch in passing an S to a B. * The use of multiple lob files could cause a stack overflow when including, for example, from the Microsoft library * We were giving an undeserved Error 126 when processing multiple LOB files. * We were giving an undeserved 1013 "symbol '...' is not a member of class '...' " in a module that does not give this error when processed alone. (The message could be suppressed with the option -fum). The problem could involve an expression such as p->member where p is a pointer to a template class (i.e. an instance of a class template). * Fixed a bug with __try { ... } __finally { ... }; Value states when arriving at the __finally are a composite of the value states from all __leave's, return's and the exit state of the __try block. We had previously ignored the return's and in some cases the exit state. * The following test did not work as expected: char a[MAX]; if( ((n= MAX ) return 0; * We were issuing an Internal Error 1211 and crashing when processing vector.h of the Borland library. More generally, templates within templates would occasionally not be instantiated because of an incorrectly perceived circular definition. * We introduced a bug in 7.50p in which an element of an initialized array is passed to a (non-const) reference to the item. We complain (Warning 530) that the array has not been initialized * We were not able to handle a pointer to member function declaration with a class template when the class of the member function was the very same template. In other words we couldn't handle: template class A { void (A::*pf)(int); }; giving an Error 10. This bug was introduced in patch level 7.50k. We also fixed a related bug. We were not digesting the longer form of the same construct: template class A { void (A::*pf)(int); }; * When ASSERT was used within namespace FOO and if no prior use of ASSERT was made we would complain that FOO::__assert was not previously declared. A work-around was to declare void __assert(...) at file-scope and the most unobtrusive way of doing that was with the -header option. We have now made this work-around unnecessary by pre-declaring __assert() if the Microsoft compiler is in use. * We now process .dsp files converting them into .lnt files. * We were ignoring an explicit specialization of a function template when another specialization was in scope that could serve (with impliciit conversions) as the function. * We were not able to handle a partially explicit specialization of function templates. For example: template< class X, class Y > X f(Y); ... f(5.6) * We were not able to resolve a reference to a template function when an argument list was not given (but an explicit specialization is given). E.g. template< class X > void f(X); void (*pf)(int) = f; * When unqualified name lookup was used for a name within a class we would include in our search not only the namespace and parential class (if any) of the current class but also the namespace and parential class of the base class if any. This created a problem with processing of C++ Builder's vector.h * We were issuing Error 18 when two overloaded functions differed in that one of the arguments was a reference and the other was not. This difference is significant enough to support an overloaded function although ambiguities can arise depending on argument type. Such a difference appeared in C++ Builder's vector.h with the insert function. * We fixed a protection violation. Circumstances included instantiating a class template from within a function definition. The template in turn contained other function definitions. * A break statement without a containing loop control structure could cause a protection violation. ********** Version 7.50s 12-1-99 ********** * We issued an Error 31 (redefinition) when a static within a namespace appeared in two separate modules. * Added __single_inheritance, __multiple_inheritance, __virtual_inheritance keywords for the Microsoft compiler * We were not always deducing when possible that an equality operation (== or !=) would certainly be true or certainly be false. We did not take into consideration certain non-zeroness of an expression. E.g. if( !n && n == 0 ) return 3; /* should issue 774 */ * We would complain that a pointer was not freed when it was 'clearly' deleted. This would occur when the pointer was typed X* where X was a class with an operator delete member function or was derived from a class with such a function. In particular, classes derived from CObject would experience this phenomenon. The work-around was to use: -function( operator delete, CObject::operator delete ) We now regard every operator delete as having the properties of the global operator delete unless prior semantics have been given. * Our .dsp processing had a flaw in the case of an include path that contained a blank. We now properly enclose any include path option that contains blanks with quotes. * When the name of a function with built-in semantics is #define'd to something else we now attempt to pass the semantics on to the function it is redefined to, provided the new function name differs from the old function name by appending or prepending underscores. * When processing .dsp files we allow the user to pre-specifiy via -d or +d variables that may appear in the dsp file. In particular, +d"CFG=..." can be used to define a configuration and to prevent redefinition. * We now report on a null pointer passed to free() * We did not give a not-accessed warning (551) for static symbols that were declared in namespaces. * We were issuing a false Error 1023 (ambiguous call) when a function call matches two different function templates. These are now disambiguated according to the resulting functions in the same manner as any other function set. In particular this was causing a problem with (not iostream.h). Here, a use of operator<< could result in the false Error 1023. * One of our Error 67's (can't cast from ... to enum) was coming out as "can't cast from %s to %s". Not good. * The following was giving a false 661: int i = 0, n = 4; int a[4]; for( ; i <= n && a[i]; i++ ) ; * Anyone using mfc (Microsoft Foundation Classes ) but not using lib-mfc.lnt might get unexplained 429's (Custodial pointer not freed or returned). This is because the delete used within an object would often be the CObject::operator delete() which is not by default associated with the properties of operator delete(). Since other libraries may be in the same boat, we have by default endowed all member functions operator delete()'s with a default semantic equal to operator delete(). This, of course, can be overridden. * We were not handling the following declaration correctly: CString s( CString(x) + "abc" ); We interpreted this as a declaration of the function s() and issued an Error 10 at the appearance of the '+'. * We now suppress the class key when displaying template argument lists. That is, instead of A we will now use: A. * We would occasionally give an Error 10 (expecting identifier or other declarator) when processing Borland headers using the map template. The line 'in error' would be "std::iterator<..." with the cursor pointing to the '<'. The message occurred as a result of not perceiving std::iterator as a template. The misperception could in general result from any template that was instatiated with all-parametric (i.e. not actual) parameters. * We were giving an Error 40 (Undeclared identifier) when processing an inline member function of a template all within a class declaration. The undeclared identifier was always a template parameter. * We now suppress 740 when a cast is being made between two compatible struct's. Two structs are considered compatible if one struct starts off with the other struct. * The error count is now not bumped because of the final message. * Processing .dsp files produced unwarranted messages 122 and 799. * We were regarding &A[i] as having length one where A is an object (i.e. it has a constructor). This is interfering with normal arithmetic computation with such pointers. We now assign a length equal to N-i where N is the length of the array. Only when &A[i] is being converted to the address of a base class do we reevaluate the length as 1. * Within a static member function of class D (derived from class B) it is OK to access a protected member of B using the notation B::m. We were giving a 1060 (B::m is not accessible). * We were reporting that unsigned(n*2) >> 2 had an unusual shift value (Warning 504). This has now been corrected. * .dsp files should not include a -d_AFXEXT since this fouls things up. We now purposely omit this define. * We now support the variable macro arguments ala Gnu C * We were complaining about the following: struct X { struct Y {}; }; struct Z : public X::Y { Z() : Y() {} }; We were issuing an Error 1038 upon encountering the 'Y()' Y should be found as a member of X::Y which is a base of Z. * We were reporting inconsistent lobs (Error 126) when there was a const static member of a class. * An option, -template(2), has been devised to allow templates to be defined recursively. This is needed for Rogue Wave's RWTwoToThePowerOf template. * We issued an undeserved 911 when a Bool was used in a Boolean context saying that there was a conversion from bool to int. We now no longer issue a 911 in that context and we have added a 909 message to cover the case were a non-Boolean is used as a Boolean. ********** Version 7.50t 12-10-99 ********** * Fixed a problem on access violation introduced into 7.50s. The net effect was that we were issuing a false 1061 saying public member not accessible through non-public inheritance. for the following case: struct A { static int x; }; struct B { static void f() { A::x = 0; } }; * We were issuing a 683 if an underscored version of the function already had semantics. * We were giving a spurious 765, (function could be made static) for overloaded functions. * We were issuing a gratuitous Error 210 (internal error) when processing a continue within a __try block. ********** Version 7.50u 3-8-00 ********** * A call to a delete within a constructor would convert any legitimate 1540's (pointer not freed) into a 1740 (pointer not freed but we did call an external function). This came about because of a rogue fix of 7.50o * We were issuing a false 761 (redundant typedef) for a typedef declared within a namespace and included by at least two modules. * We were issuing a bogus 526 for a variable declared static in a namespace, * We were issuing a bogus 729 for a variable declared in a namespace and defined elsewhere. * We were issuing a 303 when processing a template definition with unusually long (macro generated) statements. Moreover the +macros option suggested by the message did no good. * We would give a complaint for int *f( int &t ) { int *p = &t; return p; } * If A and B have destructors and B's destructor is not virtual we would fail to give message 1509 for: class C : public A, public B {...}; If the order is reversed then we give the message for B. * We were giving an undeserved 826 (suspicious ptr to ptr conversion, area too small) for: void f( double * ); char buf[8]; ... f( (double*) buf ); We now do not give the message when we know the underlying size of the area pointed to is large enough. * We were giving an undeserved 1401 for the following: struct X {int n;}; X g; struct Y : X { Y() : X(g) {} }; claiming that X::n was not initialized. * We now support the full range of length-specifying constants (e.g. 5i32, 22i16, etc.) and not just i64 as previously. * If an initializer triggered a template instantiation a subtle error could cause a protection violation. For example: Base *p = new Derived; * Although diagnostic messages are flushed immediately when the Flush Output flag is set (+ffo), and it is by default, the verbosity output was being buffered. This has been changed so that verbosity as well as diagnostics get flushed when the +ffo flag is ON. * The two logical operators (&& and ||) would result in some unjustified reevaluations of variable values. For example: int n = 1; if( n == 0 && x ) ... would unjustifiably regard n as possibly 0. * Generalized the location information provided in some messages so that filenames would not be truncated at 200 as they were in 7.50t or at 80 as they were in 7.50g but would tolerate the longest filename. * We were misevaluating some mixed mode expressions. For example: (int) (10.0 / 2) - (int) (4.0 / 2) resulted in a false 778 (constant expression evaluates to 0) * We were ignoring __declspec(). This meant that we could give an undeserved 765 or an undeserved 14 on variables that were properly tagged with an appropriate __declspec. (atlbase was producing an undeserved 14). * When semantics were assigned to a function we would complain about passing a derived class to a reference to a base class. * We were giving a false 1714 (Copy constructor for X not used) when the only use was to match up with a non-reference parameter of a catch(). * We now support mem-initializer-id's that have the same name as a parameter: E.g. the following should be Ok but yielded a diagnostic. class A { int a; A(int a) :a(a) {} }; * We were previously distinguishing between functions on the basis of a const-volatile qualifier at the highest level. That is, we were distinguishing between void f(int) and void f(const int). The standard folds these two together. * We were not catching p(args) where p is a possibly NULL pointer. We were catching (*p)(args). * We went haywire in our lint-nt.exe version when we had many nested includes and the user was using lines that end in \n and not \r\n. The problem has been traced to ftell/fseek not working properly on such files. As a work-around the user could set -maxopen(100) or some other suitable large value so that we do not resort to fseek/ftell trickery. To minimize the chance of this recurring we have increased the default value of maxopen to 50 for our lint-nt version. * Given some reason to suspect that p is NULL we would report falsely that the following may reference a NULL pointer: int *p; ... if( p == &n ) *p = 0; * Support for recursively defined templates previously depended on setting an obscure option (involving -template). The need for this option has been eliminated so that templates will by default support recursive definition. * Template object parameters (i.e. non-type parameters) would previously not match unless their types matched exactly. Thus A<4> and A would never match because sizeof is unsigned and the 4 a plain int. Now, object parameters with the same value whose types differ in signedness or in other non material ways will match. * Within a .dsp file, a /D option not followed by a quoted string was ignored. Now a /D name gets translated into -dname. * Within a .dsp file a /I "..\x386..." was greeted with an undeserved 541 (bad escape). This has now been suppressed. * We were not supporting friend declarations that were template members. E.g: template void f( T ); template< class T> { friend void f<>(T); } * Message 1914 should not be issued for unit checkout. * We were issuing an undeserved Error 36 (redefining the storage class of A<<1>>::S for the following construct: template< class T > class A { class S; }; template< class T > class A::S { }; ********** Version 7.50v 6-5-00 ********** * if( /*lint -e(720) */ a = f() ) ... didn't work as expected. It gave a 720. * For a double assignment statement such as: p1 = p2 = new A; we failed to regard p2 as aliased. This could cause an undeserved Warning 429 (custodial pointer not freed). * If the end of a function could not be reached then we could give an undeserved 429 (custodial pointer not freed) at function end. E.g. int f() { char *p = malloc(1); if( p ) { free(p); return 0; } else return 1; } * Undeserved warnings in regions of a program that can't be reached. In the following example char *p = 0; if( p ) free(p); we gave, in addition to Info 774 that the if always fails, a warning (418) that we're passing a null pointer to the function free. Warnings of this nature in regions that can't be reached are now inhibited. * We were issuing an undeserved 429 (custodial pointer has not been freed or returned) when a casted version of the pointer is returned. E.g. unsigned f() { char *p = new char; return (unsigned) p; } * ++n was previously not considered an l-value. * We were not supporting comments preceding a preprocessor comment. E.g. /* comment */ #define A 10 * We were regarding a function declared as void f( const Type ) where Type is a strong type, as not accepting a strong Type as argument. This bug was created in 7.50u. * conversion functions that return references that are in turn casted would draw a diagnostic. E.g. class X { operator int& (); }; X x; int n = (int) x; * We were not supporting the following construct in a .dsp file: /D name=value This would be translated into -dname, thereby losing the value. * For the function register mask syntax, e.g.: void f( int n ) @0x70 {...} we now issue a 430 (non-standard construct) which the user can suppress. * If the only use of a typedef was a function cast, then an unjustified Info 751 (local typedef not referenced) could be issued. * A memory leak was fixed which especially affected multiple modules using COM. Previously our Storage Consumed showed a 3% growth per module. It is down to a more respectable .3% growth. * When a case value was out of range of the switch statement, we would correctly issue a 650 warning but would mis-identify the 'operator' involved as '=='. We now correctly identify the context as the 'case' operator. * We now allow the \u escape sequence. * The function declaration int f(VOID); where VOID is a typedef and designated a strong type would not be taken to represent a vacuous argument list. * According to our documention we should not get a header resumed verbosity message when our verbosity is -vf. * The Gnu #include_next preprocessor command is supported. (actually this was supported but not reported in 7.50u) * We were not supporting __declspec within a class template definition as for example: template class __declspec( ... ) name ... This construct appeared in ATL. * We were not supporting the following call upon a function template: template< class T > void f( T, char *); ... f( 3, 0 ); * For FlexeLint, increasing the limit on the number of files by modifying FSETLEN was not working owing to the fact that FSETLEN had been inadvertently expanded during production of the source code. * We produced a spurious 780 (Vacuous array element) when processing the definition of a template containing a two dimensional array when both dimensions are non-type parameters of the template. * A strange error 1053 (function cannot be distinguished from function) occurred while using STL. The problem was characterized by nested template instantiations, default arguments and an inappropriate representation of the parameters of a function template. * Updated co-cosm.lnt (Compiler options file for the Cosmic C compiler) * When a using declaration appeared within a class definition we would erroneously introduce the fake symbol into the nearest prevailing namespace rather then into the class. * Introduced lib-ole.lnt which provides semantics for the storage allocation function of OLE. This file is automatically included by co-msc.lnt and co-msc50.lnt * Added support for Microtec's asm function using co-mc.h as an argument to the -header option introduced into co-mc86.lnt and co-mc386.lnt ********** Version 7.50w 9-27-00 ********** * Nested function definitions would sometimes make lint crash. * We were not processing an explicit global scoping in an elaborated type specifier. E.g. class ::A *p; was not parsed properly. * We were issuing an undeserved 1549 "exception not in throw list of function ..." when the expression thrown was derived from the expression listed or otherwise compatible with it. For example, we would complain about: void f() throw(E&) { throw E(); } * We were issuing an underserved Error 210 when a continue or break statement would appear within a catch block intended to transfer control out of the block. * We were not implicitly converting A to int where A was defined as: struct A { operator int&(); ... }; * We were giving a false Error 126 (Inconsistent structure definition) when processing lob files generated from STL examples. The error could occur using lob files and complex template references. * We were not handling logical OR (||) and logical AND (&&) properly when the right hand side could be a function that does not return. This could occur with the assert() facility since this is often implemented as a logical OR with a function that does not return on the right hand side. In particular, assert( i >= 0 ); if( i == 0 ) ... would be greeted with an inappropriate 774 (Boolean is always false) for the if statement. * We would give a 620 (suspicious constant) even though code was #if'ed out. * Function members of class templates that are members of namespaces would not always be compiled with the proper environment in place. As a result, elements of the namespace would not appear to be in scope. The work-around was to use a "using namespace" statement. * When function members of class templates are compiled at the end of a module and messages are produced we now precede such messages with an appropriate verbosity-like banner indicating exactly which function is being instantiated. * We gave an undeserved 734 (loss of precision 9 bits to 8 bits) for the following: unsigned n; unsigned char ch; ... ch = n % 256; * We were giving Warning 1540 (pointer member neither freed nor zero'd by destructor) for a pointer to a function. This warning is not really appropriate for pointers to functions. * We were crashing attempting to expand function templates at the end of a module. * In Windows 64, the type of sizeof is unsigned long long. Our code previously failed to adjust properly to this change. * We were not issuing a message if a const reference parameter was incremented (or decremented) * We were issuing a false 114 (inconsistent structure) for the following: class A { typedef void f(int); }; * We were giving an undeserved 530 (not initialized) warning for the following: void f() { char a[10][10]; strcpy( a[0], "abc" ); } * We would give an undeserved Error 1014 (explicit storage class not needed) for a class member definition within an extern "C++". E.g. extern "C++" { class A { void f(); }; void A::f(){} } * We now allow templated unions. * We now allow __declspec( params ) to have comma separated parameters. This was needed to support Borland's CBuilder. * We have fixed a bug in which under a #if 0 a #pragma message was processed. Any pragma processing is now inhibited under a #if 0 (or equivalent) state. * We could give strange messages when a function was called during an initialization of static members of class templates. * We were not handling some parenthesized initializers properly. One example is: int *p ( (e) ? e1 : e2 ); * We were reporting Error 10, Expecting ')' at a location where a '>' was found in a template, A, in the following situation: template < ... > struct A { ... void f() { if( n > 0 ) The template was being instantiated as part of a template argument list as in: B< A< ... > ... > x; We were getting confused as to whether angles were brackets or operators. * We were not supporting template function parameter deduction when the parameter was a non-type parameter. E.g. template< int N > void f( A ); ... f( A<13> ); would result in Error 1025 (no function matches...). * We were getting confused during aggegrate initialization in the rare case when an aggregate contained a static data member. * We were previously issuing a 1916 ("ellipsis encountered") when processing a catch. This generally is not what people are on the lookout for. * We now support the new .vcp extension as equivalent to the Microsoft .dsp extension. * We now make the #import files "library" by default. * We did not always follow the tie-breaking rules for overload resolution which caused us to report Error 1023 ambiguous function call when two function templates both matched a function call and when one function was more specialized than another. For example: template< class T > void f( T ); template< class T > void f( T * ); int n; ... f( &n ); // selects 2nd function. Such a construct appeared in the Rogue Wave libraries which in turn are used by a number of compiler manufacturers. * The overload resolution rule of selecting the nearest base class did not work if there was also a difference in qualification: class A {}; class B : public A {}; class C : public B {}; void f( const A & ); // function 1 void f( const B & ); // function 2 C c; ... f( c ); should select function 2. * When longs are designated as being longer than 4 bytes (with an option such as -sl8) we could misinterpret large constants. In general the value computed was modulo 2 ** 32. In particular 0x8000000000000000 was interpreted as being 0. ********** Version 7.50x 10-2-00 ********** * Our prior correction of the long integer had a slight flaw that could result in our not interpreting true and false properly (under some circumstances). * As a result of changes made in creating 7.50w we inadvertently made it impossible to apply function mimicry to static functions. E.g. //lint -function(exit,f) static void f(){} did not work. ********** Version 7.50y 10-9-00 ********** * We were complaining about a repeated friend declaration (Warning 1533) when multiple modules included the same class. This bug was introduced by changes made to 7.50v. * We would not accept const data passed to a function template whose argument was typed non-const ref. E.g. template< class T > void f( T & ); ... const int x; f( x ); This bug was introduced by changes made to 7.50v. * We were complaining (Warning 578) about symbol '1' hiding symbol '1' when untagged structs or unions were in the same scope. '1' is an internal symbol and therefore should not draw the complaint. * We were complaining that a pointer may not have been freed by a destructor when its delete was followed by a for loop. * We were issuing an undeserved 401 with a deserved 1034 when the static storage class was used with a member function outside a class. ********** Version 7.50z 11-10-00 ********** * We were issuing an undeserved Warning 401 (not previously declared static) when a static function was overloaded with a non-static function. * The precision of long decimal constants beyond the length of an internal long are now correctly ascertained so that the type of such a long constant is properly identified. * A global function called from within a namespace would be falsely attributed to the namespace. After a using decaration for that namespace the programmer would experience Error 1023 (ambiguous call). * The appearance of a private or protected function within a class should not influence whether that class is an aggregate. E.g. struct X { int n; int m; private: void f(); } x = { 1, 2 }; is OK because X is an aggregate. We were giving a syntax error. * We were getting errors while processing a 2nd module's header files that were merely a repeat of a first module's header files. Header files were heavily templated. This error was introduced in 7.50w. * We would give an undeserved warning when passing a const variable into a non-const reference template variable. E.g. the following didn't work. template void f( T & ); void g( const int & x ) { f( x ); } * A complaint might be issued (1548) about a function's exception specification in a second (or beyond) module when the exception referenced is std::bad_alloc. * We were giving an undeserved Error 1024 (no function has same argument count as ...) where the function in question was a constructor with a default argument. This would occur not in the first module but on the second and subsequent modules. * The type of a string literal has been made to be const char[N] where N is the length of the string to conform with the Standard. This was necessary to allow the proper selection of overloaded functions, etc. * We no longer issue a warning when free is given what might be a NULL pointer. All the standards indicate that no action is taken at that time. This warning was introduced into 7.50s. It is possible to copy the semantic of fclose's argument to obtain the prior semantic. * We were giving an undeserved inconsistent structure declaration (Error 114) under certain conditions involving numeruous templates * We were losing information concerning default arguments in member functions and it was not being regenerated. The result was that we could complain about a function not matching (such as a constructor with an optional argument) in a second module after it had been successfully processed in a first module. * Improved processing of .dsp files: 1) Rather than commenting out -d_AFXDLL we now supply needed additional defines (_MT and _DLL) along with commentary. 2) We were supporting C/C++ style strings in .dsp files with the result that we were misinterpreting, e.g., "\abc\def\" 3) We now support escapes for quotes (outside strings) in .dsp files as in: /D NAME=\"abc\" 4) We suppress Warning 435 (excessively long integral constant) in .dsp files. ********** Version 7.50aa 1-25-01 ********** * When using sizeof in the pre-processor it would not properly handle variables. E.g. The following would not work as expected. char a; #if sizeof(a) == 1 ... * We were issuing undeserved Error 86 (Structure has no elements-- i.e. no definition) for template instantiations in multi-module situations. The problem does not show up in a single module case. * Our lookahead to discriminate between function declaration and variable declaration was failing for the following case: double var( double(foo()) - double(bar()); This should be taken as a variable declaration, not as a function declaration. * The -cmsc option automatically turns on +fas (anonymous structs) as documented but you can't turn it off with a -fas. Now you can turn it off. * We now issue a new message (1561 Reference initialization causes loss of const/volatile integrity) during inappropriate reference initializations. E.g. const int x; int &y = x; // was 605 but misleading int *p; const int *q = p; // previously undetected. * We were sometimes reporting inconsistent structure definitions within lob files when the user was using typedef rather than tag to identify a struct. Thus typedef struct { ... } Name; was previously treated as a different type when it occurred in two different locations. * Another problem with LOB's occurs with the GCC standard (C++) library. When a template specialization used only non-type arguments and when the specialization was used to parameterize another template specialization, an Error 304 (Corrupt Object File, code 23) would be issued. * When a static function coexists with an external function having the same name but different prototype an undeserved Error 1023 can be issued (ambiguous call). However the candidate functions are both the same and are the same static function. * An explicitly specified template function was not always found if there is another explicitly specified template function from the same template. * We now inhibit Warning 620 when processing .dsp files. * If a static C function were called and its return value were ignored we would not issue a 534. ********** Version 7.50ab 1-26-01 ********** * We were issuing an improbable Error 10 while processing the vector header of Sun Workshop Pro 5.0. It had to do with not recognizing >> as two right angle brackets. * A bug introduced with release 7.50aa deduced the wrong size for a struct whose size has to be padded for the maximum alignment. The size of arrays of such a struct were sometimes computed correctly and sometimes not. * An untagged struct containing a member having a destructor could experience a protection fault. ********** Version 7.50ac 5-7-01 ********** * Changed the value of __cplusplus to 199711L as required by the Standard (rather than 1). * We were not passing on the const qualifier from the derived class when we found a member of the base class. This would affect overload resolution of class members. For example: struct Base { void b(); void b() const; }; struct Derived : Base {}; void g( const Derived &d ) { d.b() } We would think that the first b() was being called when actually the second b() is being called. * We were not always reporting when a custodial pointer could not be freed. In particular this would occur when the pointer in question was a local variable within an inner block in which there were no return's. E.g. for( int i = 1; i < 20; i++ ) { int *p = new int; } * Overloaded static functions were sometimes greeted with undeserved ambigous call messages. For example: static void f(char) {} static void f(int) {} void main() { f('a'); } * A braced expression within a larger expression such as: printf( "%d", { int n = 5; n < 0 ? -n : n; } ) will now be greeted with an explicit error message (155 which can be inhibited) and replaced with 0. Earlier we would stumble badly and there would be a ripple effect. * We were inadvertently tagging a wide string constant (having the form L"...") as a normal string for the purpose of overload resolution if the user was not using our built-in wide character type. By default he would not be. The result would be undeserved error 1025 (No function matches ...). * We were issuing redefinition errors (Error 39) while processing ATL headers. The problem was traced to a typedef of the form typedef A<...> name; which in turn triggered instantiation of A<...>. However this typedef was followed by a template specialization of A. Hence the complaint. The solution is to suspend instantiation until we really need it and not just the presence of a typedef. * We now delay instantiation when we see a reference to a template class. E.g. X &a; will not instantiate X. * We now support the %a and %A formats of C99. * Support the Macintosh convention that lines end in a \r. This was done by adding a new flag +frn (consider carriage Return as Newline). * We are no longer issuing a 778 while processing preprocessor statements Thus: #if FLAGS & 1 is not now greeted with a 778 since the test is being made at compile time. * For a function that does a throw "some string" and does not catch it and contains a throw list that does not contain const char * we would report that the throw list does not contain char *. We now report correctly that the throw list does not contain const char *. * If a function is defined with an array parameter (as opposed to a pointer parameter) and the type of the array is strong then the prototype of the function will contain the array type and not the nearly equivalent pointer type. In this fashion we will not give a complaint when a strong array is passed to a strong array. * We were issuing a false 1773 (attempt to cast away const without using const_cast) for: const_cast< X & >(...) That is, the exclusion for const_cast did not work for references. * When _UNICODE is defined, wmain() serves the purpose of main() and our messages now reflect that * Any verbosity option (except for the null verbosity option, -v) will retain module verbosity. * We allowed a constructor identified with the 'explicit' keyword to sometimes be invoked implicitly. * When member functions are defined repeatedly within the class it was possible to get an Error 18 (Symbol redeclared) positioned so that it seemed to be complaining about the following declaration. * Added __forceinline as a Microsoft reserved word. * Our constant out-of-range message was not being issued when the constant in question was an enumerator or a const variable. * We were letting user-defined operators win out in competition with built-in operators when built-ins should win. For example: struct X { operator char *(); }; struct R { R(X); R(int); }; int operator == ( const R&, const R& ); X x; ... if( x == 0 ) We now properly select the builtin rather than the user-defined which requires more conversions. Previously we were letting the user-defined win. * A gratuitous 791 (unusual option sequence) was issued for the following: //lint -sem(functionname,@p != 0 ) * We were not distinguishing among arrays of incomplete types. This was detected when lob files were produced using the +fod option (Output declared-only objects) and the resulting files received unjustifed Error 15's * Our value tracking was incorrectly casting some values. For example n = 127; a[ (unsigned char) -n ] = 0; would be greeted with a negative subscript warning. ********** Version 7.50ad 5-21-01 ********** * Changes made to produce 7.50ac that involved suspending instantiation "until needed" created several problems that are addressed by this fix. Not all "needed" cases had been implemented in 7.50ac