    ** This is our Bug Fix list for Patches to **

       **  PC-lint / FlexeLint Version 8.00 **


*************** 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<T> 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 <class U> static bool g( void(U::*)(void) );
	template <class U> static int g( ... );
	enum { h = g<T>(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<typename T> 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 <Dir()Sep()Name()>
       #include Dir()Sep()Name()

    would induce us to open <xxxSep()y.h> 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 <xxx/y.h>

    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 (<c.h>)
       #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 T> class A
	      {
	      A& operator =(A& );
	      template<class Y> A& operator =(A<Y>& );
	      };
    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<double>; };
      template<> class C<double> { };     // 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<typename T> struct A { A() { unsigned n = -1; } };
    A<int> 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<int> we were regarding the template
    A as a friend; we now properly regard A<int> 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<int> { ... };
    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 "&quot;" 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 T, class U> class A {};
      template <class T> class A<T,int> {};
      typedef A<double,int> 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<int> should be A<int> and not A<<1>>.
      template <class T >
	  struct A { template <class U> A f( A<U> ); };

*   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 <class T> struct A { };
      struct B { template <class U> B( A<U> ); };
      A<short> 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 <name> 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 <class T> void f( T const & );
      void g() { f( "hello" ); }

*   The following gave an Error 36 (redefining A::B from template
    to class):
      struct A { template <class T> struct B; };
      template< class T > struct A::B {};

*   We were instantiating template member functions too quickly and
    too often.  For example:
      template <class T> struct X { void f() { T a; } };
      struct Y : public X<Y> { };
    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<char>(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<char>(3);
    we would treat the '<' following "r.g" as a comparator.

*   The following sequence did not always work.
      typedef B<int> BI;
      template<> void BI:f() {}
    We might report erroneously that f was not a member of B
    if B<int> 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 <class S, class T> struct C{};
      template <class S> struct C<S,double> { C (); };
      C< float, double > x;

*   We were not supporting all cases of externally defined templates.
    E.g.:
      struct A { template<class T> 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<float> 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<int>( const unsigned& u );
      ... g<unsigned char>(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:
    <VisualStudioProject> ... <Files> ... <Filter> ... <Filter> ...
	<RelativePath> ...

*   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 ***************

*   We were issuing an unjustified Error 126 (inconsistent structure
    definition) when processing 2 or more .lob files that were produced
    by C (as opposed to C++) modules that contained nested struct's.

*   We were issuing a 434 (white space ignored after //) within a C
    style comment.  The message is not needed within comments.

*   We were issuing an undeserved 39 (Redefinition of untagged unions)
    and 407 (Inconsistent tag in the case of untagged structs) when
    two identical such aggregates were nested within separate structs,
    the +fct flag was set, and the language was C.

*   We were not making all possible deductions when the result of
    a relational was being compared with a value.  For example, we
    did not catch the divide by 0 inherent in:
      if( (n == 0) == 1 ) return 100/n;

*   Unix-lint style comments can now be placed in macros such as:
      #define NR /*NOTREACHED*/

*   Lint comments would find their way into pre-processor output
    when this was not warranted.  For example:
      #if 0
      /*lint -e777 */
      #endif
    would be OK under normal linting conditions but when the -p
    (pre-processing flag) was used, the lint comment would wind
    up in the output.  This has been fixed.

*   XML (using env-xml.lnt) output had two problems.  -append'ed
    information was not being incorporated within the message text.
    Also #pragma message was producing non-xml output.  The latter
    was fixed by using the -pragma(message) option in env-xml.lnt

*   It was possible for sequences of the form:
      /*lint -save ... */ ... /*lint -restore */
    to lose synchrony (during look-ahead for example) with the result
    that errors were not being inhibited when they should be.  This
    would commonly occur by using -emacro.  This has now been fixed.

*   We were giving an undeserved 545 (Suspicious use of &) when
    an array was passed to a template object parameter (typed pointer).
    E.g.
      template <char *p> class X { /* ... */ };
      char a[10];
      X< a > x;

*   We were not supporting function-like macro invocation where the
    name of the macro was separated from the following '(' by a comment

*   We were not finding the "f" in the following example:
      namespace A { void f(); class D; }
      class A::B { void g() { f(); } );

*   We were not finding B (the template argument to X) in the following:
      template <class T> struct X{};
      struct A { struct B; };
      struct A::B: public X<B> { };
    In general, classes defined out of the context in which they were
    declared would cause confusion.

*   We no longer issue the memory leak message (Warning 423) in
    catch blocks parameterized by std::bad_alloc

*   User-defined operator new() functions were being regarded as
    possibly returning NULL.  According to the standard this should
    only be presumed if the exception specification is the vacuous
    "throw()".  Of course, it will also be assumed if the +fnn
    flag is set.

*   We now support the variable macro argument convention as defined
    in the C99 standard.

*   We no longer give a 953 (variable could be declared const)
    for references.

*   We were issuing missing-const messages for virtual functions which
    is inappropriate because one interface must stand for several
    implementations which may not even be in evidence yet.  We now
    suppress the following messages for virtual functions:
      1746 (parameter could be made const reference)
      818 (pointer parameter could be made pointer to const)
      1764 (reference parameter could be made const)

*   In .dsp files the test for string equality was case sensitive.
    It is now case insensitive.  E.g.
      CFG=Release
      !IF "$(CFG)" == "RELEASE"
    now is regarded as true.

*   We were issuing Error 303 (String too long, try +macros) when
    +macros would not do any good.  This of course could be quite
    frustrating.  We now diagnose these cases and issue a different
    String too long message (326) which does not mention +macros.

*   We were placing some template storage into a wrongly parameterized
    region with the result that we could not create a string longer
    than about 1000 characters.  This has been fixed so that the maximum
    string is 4000 characters and can grow with +macros.

*   A template that was being instantiated as a result of a sizeof
    operation could produce undeserved 1762 messages (Member function
    could be made const).

*   During each pass (except the first) we inadvertently left one
    additional file open and as a result the number of passes
    become limited by the number of files that could simultaneously
    be open.

*   The representation of a (non-static) member function call
    used in the reporting of messages during Specific Walks was
    marred by an off-by-one error.  This would also occur during
    verbosity messages showing the logging of Specific Calls (-vc)
    and the initiation of Specific Walks (-vw).

*   Our value tracking of data members was being overly influenced by
    values obtained as the result of Specific Walks leaving a false
    hit rate of too high a level.

*   When a function pointer was passed to a function template we were
    not able to match a reference in the parameter list of the function
    with a template parameter in the parameter list of
    corresponding parameter of the function template.  E.g.:
      template< class T1> void f( float (*x)(T1) ) { }
      float h( int & );
      ...  f( h );

*   When a function template is declared after a function by the same
    name we were not allowing explicit template arguments to be used
    with the name.  E.g.
      void f( double );
      template <class T> void f(int) { }
      void g() { f<int>( 0 ); }

*   We no longer issue message 429 (Custodial pointer has not been
    freed) in catch blocks parameterized by std::bad_alloc

*   We no longer report on the use of // in a C module when the
    strict ANSI option (-A) is given since C99 now supports this form
    of comment.  To obtain the old behavior use -A(C90).
    You may also use +e950 to obtain the check.

*   We now recognize namespace std by default (i.e. without an explicit
    'using namespace std;' statement) when the -cgnu option (the option
    to specify gcc as the compiler) is given, to conform with the
    expectations of that compiler.


*************** Version 8.00h 6/25/2002 ***************

*   An instantiation of a template bearing an inline function
    within a class member function could cause unqualified name lookup
    to go awry.  In the following s was not found.
    template <class T> struct A
	{ int s; void f() { s = 0; } };
    struct B { void g( void ); };
    void B::g( void ) { A<int> x; }

*   Message 1053 (function cannot be distinguished from another) is
    now accompanied with the minor type differences leading to the message.

*   We were not producing any message when a declaration of a function
    declared the function to be inline whereas a prior definition of
    the function did not indicate that it was inline.

*   We were not recognizing an operator+ after it was defined as a
    friend function of a template specialization X<t>.  We would
    recognize operator+ in the first module that instantiated X<t>
    but not in subsequent modules.  This was because we were not
    reactivating friend functions declarations for subsequent modules.

*   We were not processing Visual Studio 6.0 project files (.dsp files)
    as well as we should.  In particular options appropriate to only
    a single module were being triggered in the order of appearance
    in the .dsp file.  The result was that these options came after
    the module name which was too late to be of any good.

*   We were processing .vcp files as if they were .vcproj files
    rather than as .dsp files.

*   We were not reporting when the address of a (non-reference) parameter
    was being returned.

*   We were not producing declarations of static functions when the
    -odi() option was used.

*   We were not allowing blanks within the -e{...} option.

*   We no longer give message 944 by default during specific walks

*   We were giving an undeserved Error 58 (bad type) when comparing
    ptr-to-member's

*   We were giving an undeserved 1764 (reference parameter could be
    declared const) when the reference parameter (r) was used in the
    following way:   r.*x = expression;

*   A pointer used on the left-hand side of a ->* operator would
    not get credited with an access.  Thus the expression
	(p->*pmf)(arguments);
    would not be sufficient to suppress Warning 550 (symbol p not
    accessed).

*   We were issuing an undeserved Info 1764 (Reference parameter
    could be made const) when its only use was in the call of a member
    function through a pointer to member function.  E.g.
	void f( C &r, void (C::*f)() ) { (r.*f)(); }
    would result in a 1764

*   A parameter declared Pointer-to-member-function would receive an
    unjustified 818 (pointer could be made const).

*   We would report an 'inconsistent structure definition' for a class
    within a lob that contained a template function member.

*   We were issuing an unjustified Corrupt Lob (Error 304, code 26)
    when a template function was called where the function sprang
    from a partial specialization.

*   We were issuing an unjustified Error 126 (inconsistent structure
    definition) when processing 2 or more .lob files that were produced
    by C (as opposed to C++) modules that contained nested struct's.

*   We were issuing an unjustified Error 126 (inconsistent structure
    definition) when processing 2 or more .lob files that contained
    untagged enum's that were not identical.  Our flaw was that we
    were making them identical when they were not and reporting the
    inconsistency at lob time.

*   We were looping on the following constant: 0.0e-999999
    In general, whenever there was a 0 value with a huge exponent
    we could loop.

*   We were giving an undeserved 304 (Corrupt Object file) code 28
    when linting a lob that contained a class that had both a function
    and a function template by the same name.  Such a condition prevailed
    in OLE.


*************** Version 8.00g 4/10/2002 ***************

*   You can now suppress message 126 with an -esym.

*   We no longer append a useless blank to "module" verbosity message.

*   Enhanced the env-xml.lnt file so that xml escapes would be employed
    for xml meta-characters.

*   Added the +fet flag (Explicit Throw) flag.  See readme

*   We were failing to deduce that after a successful test for
    x > 3 that x could no longer be 0.

*   An 'improvement' in our unqualified name lookup introduced in
    8.00f had a slight bug that would evidence itself when a function
    defined outside of its namespace was declared to return a pointer
    or reference.  E.g.
       namespace X { struct S { int *f(); }; }
       int *X::S::f() { int a; ...  }
    a would be considered defined within namespace X.

*   We were issuing an undeserved Error 64 when initializing a reference
    with a reference to a type that differs in some way from, but could
    be converted to, the target type.

*   We were not finding all source file names in .vcproj files.
    We were triggering off the attribute: name = "Source Files";
    but this is not that reliable as other names can be used.  We now
    trigger off extensions.

*   We were not properly truncating casts during value tracking.
    Thus information losing casts would retain their original values.

*   We were giving an undeserved Error 64 when an attempt was made
    to assign a pointer to a bool.  This is perfectly valid code and
    now draws only the usual implicit conversion messages.

*   We were not handling the .NET keywords __if_exists() and
    __if_not_exists() properly.  Although referred to as statements
    it seems they can appear anywhere in the source code, within
    classes, within initializers, etc., and not just within code blocks.

*   Unqualified name lookup in a constructor initializer would create
    a problem if the namespace depths become deep enough.  E.g. in the
    constructor definition:
       A::B::C::X::X() : B::X(3) {}
    where A, B, and C are namespaces, we would not find B.
    this had worked in patch levels prior to 8.00f.

*   We were converting bools b1 and b2 in the following expression to int.
      predicate ? b1 : b2
    According to the standard the result is a bool not an int.

*************** Version 8.00f 3/18/2002 ***************

*   We were not rewalking (in subsequent passes) class member functions
    defined in the class.

*   We were not rewalking instances of template functions in subsequent
    passes.

*   We were not rewalking template member functions in subsequent passes.

*   When there is a repeated definition of a template specialization
    as in:
	template<> class A<long> {};
	template<> class A<long> {};
    we correctly issued an Error 39 but the location we cited as being
    in conflict was the new location not the old location.  This has
    now been fixed.

*   We were sometimes not finding the correct namespace when a global
    scope operator was provided.  e.g.
      namespace A { class X {}; }
      namespace B { namespace A { class Y{}; } class Z { void f(); }; }
      void B::Z::f() { ::A::X n; }  /* we can't figure out ::A::X */

*   There was no way for a user to totally suppress #error messages.
    Now if you give the +fce (continue on #error flag) AND suppress
    message 309 with -e309 you will continue on as if nothing happened.

*   The flag +fdh (add .h by default for #include "name" where name does
    not have an extension) previously did not work with Unix systems.

*   Our unqualified name lookup has been improved so that we can pick
    up identifiers not only in the namespace bearing a function but
    in any containing namespace as well.  For example we were not
    finding the "i" in the following return statement:
	namespace A { int i; namespace B { int f(); } }
	int A::B::f() { return i; }

*   We were issuing a 304 (Corrupt Object file), code 23 for a template
    that was involved in an expression where the template arguments were
    somewhat intricate.  The smallest example causing the problem was:
	template <class E> class V { typedef V<E> y; };
	typedef V< V<int> > B;
	typedef V< V<B*> > C;
	B b;

*   We were issuing an undeserved 429 (custodial pointer not freed)
    during a specific walk of a function that was handed a pointer
    that was custodial in the caller.

*   Given two consecutive calls with partial lists of explicit template
    arguments could result in the wrong function.  E.g
      template <class T, class S> T f(S);
      double y = f<double>(0);    /* ok uses f<double,int> */
      long x = f<long>(0);        /* bad, still uses f<double,int> */

*   We were looping during the delete of class A that contained a
    member typed T<A> which in turn had a reference to A as a member.

*   When -emacro was applied to a macro which began a default
    argument the error suppression would not take place.  E.g.
    //lint +e1924 -emacro(1924,M)  warn about C style casts except in M
    #define M (int) 10
    template< int k = M > class A { int x[M]; };
    A<> a;    /* Issues a 1924 anyway */

*   We were occasionally issuing an undeserved Error 40 when processing
    member declaration within a class template.  The declaration includes
    the sequence:
	    ... typename qualified-name declarator;
    The Error 40 was somewhat random and 'typename' was necessary.

*   We were not allowing a function (declared to return void) to
    return an expression typed void

*   volatile variables are not assumed to hold values assigned to them
    with probability one.  Variables that are const volatile and
    initialized are not assumed to hold the const variable property.

*   We now support template nontype reference parameters and
    pointer parameters semantically and not just syntactically.

*   a MISRA rule 42 warning (avoid use of comma operator) was not
    suppressed in the top-level for clause.

*   We were issuing an unjustified 957 (Function defined without a
    prototype in scope) when a static member of a namespace was being
    defined as in:
	static void N::f() {}

*   We now support template member operators.  E.g.
	template <class T> class C {
	    template<class U> int operator==(U); };

*   We were giving an undeserved Info 768 (global member not referenced)
    for a template member even though the member was referenced in
    an externally defined function member.

*   We were not handling complex macros in the #include syntax.
    For example,
	#include macro(name)
    where macro evaluates to an angle-bracketed expression.
    This had been working prior to 7.50o.

*   We were not giving a divide by zero warning when a float was
    being divided by an integer.

*   We are now processing VC7 project files (extension .vcproj)
    producing an equivalent .lnt file (similar to .dsp).

*   We now support the Microsoft __if_exists and __if_not_exists
    keywords introduced with .net

*   We are getting an undeserved Warning 650 (Constant out of range)
    when a bit field contains an enumeration and is compared with
    an enumerator even though the +fbu (bitfields are unsigned) flag
    has been set

*   The Gnu reduced variant of the ?: operator, e.g.
	a = f() ? : -1;
    is supported.

*   The Microsoft attribute designation using [ ... ] before a
    type specifier is supported.

*   We were issuing an unjustified 1001 (X must be struct or class)
    for the following:
	template< class T > class A : public T::X::Y {};
    The message was benign as it did not prevent us from instantiating
    A properly.

*   We were issuing an unjustified 1070 when processing ATL (the Active
    Template Library).  The cause was traced to our inclination to
    unnecessarily instantiate template arguments.  Thus in:
	A< B<x> > a;
    there is normally a need to instantiate A< > with the appropriate
    type but not B< >.

*   We now support unnamed template parameters as in:
	template< class = int > class A {};

*   We now support template template parameters.

*   We now arbitrarily break template recursion and give a message
    indicating we are doing same.  The reason for this is that it
    is possible to define a recursive template as in:
	 template <class T> class A { A< A > x; };

*   We were not handling all uses of @ for the Cosmic compiler.
    In particular we were not handling @ as an introduction to a
    modifier.  For example:
	char * @near f();

*   We were issuing an unjustified 793 (external count exceeded ANSI
    limit) counting statics as externals

*   A complex initializer involving a template-id (i.e. an
    expression of the form: name< ... >) could trip up our
    look-ahead.  For example:
	 C x( NS::foo<int>() );
    was not parsed correctly because the look-ahead to break
    ambiguity involved a template-id.

*   Under some circumstances, when a member function of a template class
    was defined out of line we were not recognizing the function
    as a previously declared member.  The class had a non-type parameter
    and the function parameter was of the form C<I> and the out of line
    declaration used a slightly different form for the parameter than
    the inline.  E.g.
	 template< int I > class C { void f(C<I>); };
	 template< int I >  void C<I>::f(C)  {}
    This occurred in the MS header atlbase.h for VC7.

*   If two successive template parameters have the same name we would
    crash.  E.g.  template< class T, class T > void f();

*   When a template parameter contained a dependent type we could crash.
    E.g.
	 template< class T, T::M (*pf)() > ...
    Such a construct occurs in dxatlpb.h for VC7.

*   Our flag +fbu (bitfields are unsigned) was not being honored in the
    case of enumerations.  E.g. the following gave an unjustified constant
    out of range message.
	 //lint +fbu
	 enum E { a, b, c };
	 struct S { E m:2; } s;
	 void f() { if(s.m == c); }


*************** Version 8.00e 11/21/2001 ***************

*   Introduced Warning 686 suspicious option (unbalanced quotes)
    to cover what could be an almost undecipherable situation in
    processing lint options.  E.g.
	-i"C:\lint\"  std.lnt ...
    was parsed by the command processor to produce
	-iC:\lint"  std.lnt ...
    Warning 686 at least warns of the dangerous condition.

*   We now treat @ within a declaration specifier as being something
    that gets ignored with a Warning 431.  This enables compilers with
    syntax that resembles:
	@interrupt void f() { ... }
    to have a chance of working correctly.

*   We were issuing an undeserved 1928 (base class not on initializer
    list) when the base class had no constructor to begin with.

*   Added the ability to convert pragmas and/or preprocessor lines
    into macros.  This was needed by the ByteCraft compiler.

*   We were getting exceptions in template processing.  This would
    occur in template wrap-up activity when an instantiation of one
    function would trigger the instantiation of a template class.

*   When a base class within a template was originally a dependent
    type then it should not be searched for names during unqualified
    name lookup.  Since this is only a recent change in the standard
    and since most compilers do not support this change it is controllable
    via option: ++template(40)

*   We were issuing an unjustified Error 1050 (Expected a template
    argument list) while processing the Microsoft Standard Template
    Library.  We were finding the name "interator" in the base class
    iterator<int> which is not justified by the standard.  This was
    interfering with our finding class iterator.

*   We were issuing an unjustified 1549, 1550 and 1560 (exception thrown
    was not declared) within a function which had no exception
    specification and therefore is declared to throw any exception.

*   We were issuing an unjustified 1775 (catch block does not catch
    exception) when a function with no exception specification was called
    from within the corresponding try block.

*   A template function if the form:
    template< class T, class U > void f( const A<U> & );
    was not being matched by an argument of the form const A<type> &.

*   a user semantic option within a template could cause a crash.
    E.g.  template<class T> class A { /*lint -sem( a, custodial(1) )*/ };


*************** Version 8.00d 10/29/2001 ***************

*   We were issuing an undeserved 777 for the following:
    if( (x > 0) == (y > 0) ) ...
    where x and y are floating point numbers.

*   We now allow a variable number of arguments when a macro is
    defined using the -dname()=... form.  For example: -dasm()=0
    followed by:
	    n = asm( "mov a,3", "add b,a" );
    would work fine.

*   Allow unsigned integer constants for bit addressing.  E.g.
    a.0x3 = ...

*   We were issuing an undeserved 765 (could be made static)
    for a function whose only declaration is within another function.

*   rw_asgn(to,from) and ppw_asgn(to,from) did not work unless
    the from keyword was enabled.  For example to assign the meaning of
    "_to_brackets" to "IGNORE" you had to first enable the former as in:
	+rw(_to_brackets)  +rw_asgn(IGNORE,_to_brackets)
    This first option is no longer necessary

*   When the height of messages are 4 (-h...4) We were losing the
    first portion of the message (the format4a portion) when no
    location information was associated with the message.

*   __STDC_VERSION__ and __STDC_HOSTED__ are now pre-defined macros
    in conformance with the C-99

*   We were giving an undeserved 146 (binary constant) while processing
    assembly code.

*   -emacro({#,#},name) was not working.  Only the first # was supported.
    Our documentation did not give any example wherein this would work
    so its not strictly a bug but the presumed extension did not work.

*   Misra Rule 44 (redundant casting) is an advisory rule (961) but
    was issued as a required rule (960).  Our documentation on this
    was correct but the code was in error.  Rule 44 is now issued
    a Message 961.

*   An undeserved 1062 (template must be a class or function) was given
    for:
    template <class S, class T> void g(S (T::*f)() const) { }
    At some level we didn't think this was a valid prototype; the const
    was throwing us off.  This has now been fixed.

*   Support for the Cosmic C compiler's multi uses of @.  For example,
	volatile int n @ PORTADD + 2;
	@interrupt void f();
    required the introduction of the __at keyword.

*   Given a doubly scoped name (e.g., A::B::C) within a class X,
    if there was a B in class X we would pick up the wrong B.
    We now correctly confine our searching to A.

*   We were not supporting qualified name lookup for a namespace
    name properly.  We were giving ambiguous reference messages
    where none was deserved.  For example:
    namespace A { int a; } using namespace A; int a;  int n = ::a;
    would result in message 1075.  This would be a correct diagnosis
    if the global scope operator was omitted.  However when explicit
    namespace scoping is given (as in the above) then using directives
    are explored only as a last resort.

*   static items were not always visible when they should be.
    For example:
    namespace A { void f(); const int c = 3; }
    int A::f() { return c; }
    Here c is implied static and visible from within A::f but we
    claimed that it was undeclared in that context.

*   Templates were not being instantiated at the same library level
    in which they were declared.  This exposed too many template warnings
    on unsuspecting template users.  Template instantiation is now
    done at the same library level as the template definition.

*   We were reporting a 785 (too few initializers) with
    float x[10] = { 0 };
    when our documentation suggests that it would receive the more benign
    943.

*   We were not handling the situation where there were two independent
    definitions of a typedef'ed struct in two different modules.
    For example, if
    typedef struct A { ... } A_t;
    appeared in two different modules as independent declarations
    (i.e., not in the same header) we would properly give an origin
    error but then improperly assign the wrong type to A_t.

*   A template declaration of the form:
    typedef void (*F)( arglist );
    template < ... , F = function-name > ...
    i.e., where the parameter name was missing following a type (F in
    this example) would result in a misplaced diagnostic and possibly
    a crash.

*   We were giving an undeserved Error 40 within ole2.h for the
    identifier LPCLASSFACTORY when processing the second (and
    beyond) modules that were including COM header files.
    The problem was triggered by an unusually complex interaction
    between ole2.h and unknwn.h in which each was including the other
    making use of the #pragma once to break the recursion.  It turns
    out we neglected to reset our internal once flags.

*   We were issuing an unjustified 798 (redundant character) for the
    following sequence:
    #if 0
    #define A
	\
	x
    #endif
    The message was issued only in cases that conditional compilation
    indicated should NOT be examined.


*************** Version 8.00c 8/16/2001 ***************

*   A delete of a complex expression such as
	delete member[i];
    where the type is a pointer to a class that has a destructor
    could cause the issuance of internal error 257
    plus an infinite loop.

*   An undeserved MISRA Violation (message 960) is issued
    for a simple delete.

*   There was an undeserved 929 (cast from pointer to pointer)
    for any delete.

*   We were issuing Internal Error 212 with Gnu C.  The problem
    would occur when a new was encountered after size_t was
    (re)declared as unsigned long.


*************** Version 8.00b 8/8/2001 ***************

*   For messages 525 (negative indentation), 725 (expected positive
    indentation, and 539 (did not expect positive indentation),
    we were issuing a "location unknown" as part of the 830 message.

*   When the fai flag was turned off with a -fai (it is normally ON)
    we were not only regarding an argument whose address was passed
    to a functions as being possibly uninitialized as the documentation
    says but we were making a similar deduction with regard to
    the "this" argument when non-const member funtions were called.
    This was neither justified by the documentation nor by common
    sense and so "this" arguments are now immune to this treatment.

*   A false 960 message (Rule 69) was issued for a C++ catch clause
    using an ellipsis.

*   An undeserved 960 message (MISRA rule 68) was issued for
    any class or namespace function defined in file scope level.

*   We were issuing an undeserved 306 (previously encountered module)
    when processing a lob file in a multi-pass setting.

*   Message 641 (converting enum to int) has been parameterized with the
    name of the enumeration.

*   Message 910 was issued when we were assigning 0 to something other
    than a pointer.


*************** Version 8.00a 7/26/2001 ***************

*   If there is a side effect on the right hand side of a logical
    operator and if operator op() is defined or declared then
    an inexplicable Bad Type (61) and Type Mismatch (64) could
    occur.

*   We were giving an undeserved 133 (too many initializers) for the
    following code which is actually deemed legal by the C++ standard.
    struct A {} a = {};

*   In converting .dsp files to .lnt files we would not previously
    process SOURCE lines bearing module names that are quoted.

*   If a module name contained a blank then the second and subsequent
    passes (if any) would split the name at the blank.

*   An undeserved Error 2 (Unclosed Quote) could occur with two adjacent
    string constants following a template class expression that
    gets instantiated.



