diff --git a/cxx-sensors/src/main/resources/pclint.xml b/cxx-sensors/src/main/resources/pclint.xml
index bb9c8875c5..1238406f74 100644
--- a/cxx-sensors/src/main/resources/pclint.xml
+++ b/cxx-sensors/src/main/resources/pclint.xml
@@ -1,22418 +1,23445 @@
-
-
CheckId
of your custom rule, a title, a description, and a default severity.
- switch( n )
- {
- case 1: m = 25; break;
- case 2-1: m = 27; break;
- }
-
-]]>
-
- enum E; // Error
-
-This is prohibited by ISO C and ISO C++98. In C++0x, we can modify this example to be well-formed by explicitly indicating the underlying integral type; example:
-
- enum E : unsigned short; // Ok
-
-If you are not using C++0x and/or your compiler supports the construct you may simply suppress this message with a -e165.
]]> -
- __attribute__((mode(DF)));
-
-This is supposed to match a built-in scalar type whose size is the size indicated in the message. If this message is issued, it probably means that size options have not been set to match the compile configuration; see Section 5.3, Size and Alignment Options.
-]]> -
- double radius,
- diameter;
-
-the programmer had typed:
-
- double radius;
- diameter;
-
]]>
- ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
- - ]]> -ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
- - ]]> -ARR38-C. Guarantee that library functions do not form invalid pointers
- ]]> -ARR38-C. Guarantee that library functions do not form invalid pointers
- - ]]> -MEM31-C. Free dynamically allocated memory when no longer needed
- - ]]> -
- int *p = new int[20]; // p is a custodial pointer
- int *q = p; // p is no longer custodial
- p = new int[20]; // p again becomes custodial
- q = p + 0; // p remains custodial
-
--Here p does not lose its custodial property by merely participating in an arithmetic operation. -A pointer can lose its custodial property by passing the pointer to a function. If the parameter of the function is typed pointer to const or if the function is a library function, that assumption is not made. For example
-
- p = malloc(10);
- strcpy (p, "hello");
-
-Then p still has custody of storage allocated.
-It is possible to indicate via semantic options that a function will take custody of a pointer.
-MEM31-C. Free dynamically allocated memory when no longer needed
- ]]> -
- malloc( strlen(e+1) )
-
-where e is some expression. This is suspicious because it closely resembles the commonly used pattern:
-
- malloc( strlen(e)+1 )
-
-If you really intended to use the first pattern then an equivalent expression that will not raise this error is:
-
- malloc( strlen(e)-1 )
]]>
-
- int *p = malloc(1);
-
-This message is also provided for user-declared allocation functions. For example, if a user's own allocation function is provided with the following semantic:
-
- -sem(ouralloc,@P==malloc(1n))
-
-We would report the same message. Please note that it is necessary to designate that the returned area is freshly allocated (ala malloc). - This message is always given in conjunction with the more general Informational Message 826.
-
- Example:
-
- #define FOO(p) p
-
- FOO(
- #define X Y
- )
-
-According to the ISO Standards, this results in undefined behavior.
- -By the rules of Standard C the preprocessing directive is - absorbed into the macro argument but then will not subsequently - get executed. For this reason some compilers treat the apparent - preprocessor directive as a directive. This is logical but not - portable. It is therefore best to avoid this construct.
]]> -
- void f( int i )
- {
- int a[2] = {i++, i++};
- }
-
-The values of the array elements are unspecified because the order of evaluation is unspecified by the C standard.
]]> -
- enum colors { red, blue, green = 1 };
-
-will elicit this informational message while
-
- enum colors { red, blue = 1, green = 1 };
-
-will not.
]]> -
- defined(identifier)
- defined identifier
-
-Additionally, the preprocessor operator may not result from the expansion of another macro. This diagnostic highlights departures from these requirements as non-portable code.
- - ]]> -
- u >= 0 0 <= u
- u < 0 0 > u
-
-are suspicious if u is an unsigned quantity or a quantity judged to be never less then 0. See also message 775.
]]> -
- u / n
-
-where u is unsigned and n is signed will elicit this message whereas:
-
- u / 4
-
-will not, even though 4 is nominally an int. It is not a good idea to mix unsigned quantities with signed quantities in any case (a 737 will also be issued) but, with division, a negative value can create havoc. For example, the innocent looking:
-
- n = n / u
-
-will, if n is -2 and u is 2, not assign -1 to n but will assign some very large value.
-To resolve this problem, either cast the integer to unsigned if you know it can never be less than zero or cast the unsigned to an integer if you know it can never exceed the maximum integer.
]]> -
-> >= < <=
-
-One of the operands to a relational operator was signed and the other unsigned; also, the signed quantity could be negative. For example:
-
- if( u > n ) ...
-
-where u is unsigned and n is signed will elicit this message whereas:
-
- if( u > 12 ) ...
-
-will not (even though 12 is officially an int it is obvious that it is not negative). It is not a good idea to mix unsigned quantities with signed quantities in any case (a 737 will also be issued) but, with the four relationals, a negative value can produce obscure results. For example, if the conditional:
-
- if( n < 0 ) ...
-
-is true then the similar appearing:
-
- u = 0; if( n < u ) ...
-
-is false because the promotion to unsigned makes n very large.
-To resolve this problem, either cast the integer to unsigned if you know it can never be less than zero or cast the unsigned to an int if you know it can never exceed the maximum int.
]]> -For example:
-
- pattern = "(???) ???-????"; // warning 585
- pattern = "(?\?\?) ?\?\?-?\?\?\?"; // no warning
- #define Q "?"
- pattern = "(" Q Q Q ") " Q Q Q "-" Q Q Q Q // no warning
-
]]>
-
- char msg[100];
- ...
- printf( msg );
-
-This can easily be rewritten to the relatively safe:
-
- char msg[100];
- ...
- printf( "%s", msg );
-
-The danger lies in the fact that msg can contain hidden format codes. If msg is read from user input, then in the first example, a naive user could cause a glitch or a crash and a malicious user might exploit this to undermine system security. Since the unsafe form can easily be transformed into the safe form the latter should always be used. -
- ]]> -
- void f( int n )
- {
- int *p = new int;
- if( n ) delete p;
- } // message 593
-
-In this example an allocation is made and, if n is 0, no delete will have been made. -Please see message 429 for an explanation of "custodial" and ways of regulating when pointer variables retain custody of allocations. -
- ]]> -
- i << 32
-
-will elicit this message if i is typed int and where int is 32 bits wide or less (the usual case). Such shift results in undefined behavior.
-To suppress the message you may cast the shifted quantity to a type whose length is at least the length of the shift value.
]]> -
- int *p;
- const int *q;
- p = q; /* 605 */
-
-The message will be inhibited if a cast is used as in:
-
- p = (int *) q;
-
-An increase in capability is indicated because the const pointed to by q can now be modified through p. This message can be given for the volatile qualifier as well as the const qualifier and may be given for arbitrary pointer depths (pointers to pointers, pointers to arrays, etc.). -If the number of pointer levels exceeds one, things get murky in a hurry. For example:
-
- const char ** ppc;
- char ** pp;
- pp = ppc; /* 605 - clearly not safe */
- ppc = pp; /* 605 - looks safe but it's not */
-
-It was not realized by the C community until very recently that assigning pp to ppc was dangerous. The problem is that after the above assignment, a pointer to a const char can be assigned indirectly through ppc and accessed through pp which can then modify the const char. -The message speaks of an "increase in capability" in assigning to ppc, which seems counter intuitive because the indirect pointer has less capability. However, assigning the pointer does not destroy the old one and the combination of the two pointers represents a net increase in capability. -The message may also be given for function pointer assignments when the prototype of one function contains a pointer of higher capability than a corresponding pointer in another prototype. There is a curious inversion here whereby a prototype of lower capability translates into a function of greater trust and hence greater capability (a Trojan Horse). For example, let
-
- void warrior( char * );
-
-be a function that destroys its argument. Consider the function:
-
- void Troy( void (*horse)(const char *) );
-
-Troy() will call horse() with an argument that it considers precious believing the horse() will do no harm. Before compilers knew better and believing that adding in a const to the destination never hurt anything, earlier compilers allowed the Greeks to pass warrior() to Troy and the rest, as they say, is history.
]]> --(long) (n << 8) --might elicit this message if n is unsigned int, whereas -
-(long) n << 8 --would not. In the first case, the shift is done at int precision and the high order 8 bits are lost even though there is a subsequent conversion to a type that might hold all the bits. In the second case, the shifted bits are retained. -
The operations that are scrutinized and reported upon by this message are: shift left, multiplication, and bit-wise complementation. Addition and subtraction are covered by Informational message 776.</description></rule>
-The conversion to long may be done explicitly with a cast as shown or implicitly via assignment, return, argument passing or initialization.
-The message can be suppressed by casting. You may cast one of the operands so that the operation is done in full precision as is given by the second example above. Alternatively, if you decide there is really no problem here (for now or in the future), you may cast the result of the operation to some form of int. For example, you might write:
--(long) (unsigned) (n << 8) --In this way PC-lint/FlexeLint will know you are aware of and approve of the truncation. - - ]]> -
- int a[10];
- if( n <= 10 ) a[n] = 0;
-
-Here the programmer presumably should have written n<10. This message is similar to messages 415 and 796 but differs from them by the degree of probability.
-ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
- - ]]> -
- int a[10];
- if( n <= 20 ) f( a + n );
-
-Here, it appears as though an illicit pointer is being created, but PC-lint/FlexeLint cannot be certain. See also messages 416 and 797.
-ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
- - ]]> -ARR38-C. Guarantee that library functions do not form invalid pointers
- - ]]> -ARR38-C. Guarantee that library functions do not form invalid pointers
- - ]]> -MEM31-C. Free dynamically allocated memory when no longer needed
- - ]]> -INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
- - ]]> -INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
- - ]]> -INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
- - ]]> -
- int a[10];
- int j = 100;
- for( i = 0; i < n; i++ )
- j = n;
- a[j] = 0;
-
-Here, the access to a[j] is flagged because it is conceivable that the for loop is not executed leaving the unacceptable index of 100 in variable j. This message is similar to messages 415 and 661 but differing from them by the degree of probability.
-ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
- - ]]> -ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
- - ]]> -ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
-ARR38-C. Guarantee that library functions do not form invalid pointers
- - ]]> -ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
-ARR38-C. Guarantee that library functions do not form invalid pointers
- - ]]> --int f( char * const p, const int n ) { return *p = n; } --There are few advantages to declaring an unchanging parameter a const. It signals to the person reading the code that a parameter is unchanging, but, in the estimate of most, reduces legibility. For this reason the message has been given an Elective Note status. -However, there is a style of programming that encourages declaring parameters const. For the above example, this style would declare f as -
-int f( char * p, int n); --and would use the const qualifier only in the definition. Note that the two forms are compatible according to the standard. The declaration is considered the interface specification where the const's do not matter. The const's do matter in the definition of the function which is considered the implementation. Message 952 could be used to support this style. -Marking a parameter as const does not affect the type of argument that can be passed to the parameter. In particular, it does not mean that only const arguments may be passed. This is in contrast to declaring a parameter as pointer to const or reference to const. For these situations, Informational messages are issued (818 and 1764 respectively) and these do affect the kinds of arguments that may be passed. See also messages 953 and 954. - - ]]> -
The list of required checks made for both MISRA 1998 and 2004 are:
-
- (Rule 16/12.12) Bit representation of a floating point type used.
- (Rule 19/7.1) Octal constant used.
- (Rule 22/8.7) Could define variable at block scope.
- (Rule 27/8.8) Object/function previously declared.
- (Rule 32/9.3) Should initialize either all enum members or only the first.
- (Rule 33/12.4) Side effects on right hand side of logical operator.
- (Rule 34/12.5) Non-primary expression used with logical operator.
- (Rule 36/12.6) Boolean expression required for operator.
- (Rule 40/12.3) 'sizeof' used on expressions with side effect
- (Rule 42/12.10) Comma operator used outside of 'for' expression.
- (Rule 47/12.1) Dependence placed on C operator precedence.
- (Rule 54/14.3) Null statement not in line by itself.
- (Rule 57/14.5) continue statement should not be used.
- (Rules 59/14.8 & 14.9) Left brace expected for if, else, for, do, and while.
- (Rule 60/14.10) No 'else' at end of 'if ... else if' chain.
- (Rule 63/15.4) Boolean value in switch expression.
- (Rule 65/13.4) Floating point variable used as loop counter.
- (Rule 68/8.6) Function not declared at file scope.
- (Rule 69/16.1) Function has variable number of arguments.
- (Rule 73/16.3) Either all parameters or no parameters should have identifiers.
- (Rule 74/16.4) Parameter list differs from prior declaration for function.
- (Rule 87/19.1) Declaration before #include.
- (Rule 88/19.2) Header file name with non-standard character.
- (Rule 91/19.5) '#define/#undef' used within a block.
- (Rule 92/19.6) Use of '#undef' prohibited.
- (Rule 98/19.12) Multiple use of '#' and/or '##' operators in macro definition.
- (Rule 100/19.14) Non-standard use of 'defined' preprocessor operator.
- (Rule 115/20.2) Re-use of C90 identifier/identifier pattern.
-
- Required checks made exclusively for MISRA 1998 are:
-
- (Rule 8) Multibyte characters and wide string literals prohibited.
- (Rule 42) Comma operator used outside of 'for' expression.
- (Rule 54) Null statement not in line by itself.
- (Rule 58) break used outside of a switch.
- (Rule 73) Either all parameters or no parameters should have identifiers.
- (Rule 87) Declaration before #include.
- (Rule 88) Header file name contains non-standard character.
- (Rule 110) Bitfields inside union.
-
- Required checks made exclusively for MISRA 2004 are:
-
- (Rule 4.1) Prohibited escape sequence used.
- (Rule 6.1) Disallowed use of non-character value.
- (Rule 6.2) Disallowed use of non-numeric value.
- (Rule 8.5) No definitions of objects or function in header files.
- (Rules 10.1 & 10.2) Prohibited implicit conversion.
- (Rules 10.3 & 10.4) Prohibited cast of complex expressions.
- (Rule 10.5) Recasting required for operators '~' and '<<'.
- (Rule 10.6) Unsigned integer literals require a 'U' suffix.
- (Rule 11.5) Attempt to cast away const/volatile from a pointer or reference.
-
- (Rule 12.7) Bitwise operator applied to signed underlying type.
- (Rule 12.9) Prohibited operator applied to unsigned underlying type.
- (Rule 12.10) Comma operator used.
- (Rule 12.13) Increment or decrement combined with another operator.
- (Rule 14.3) Null statement not in line by itself.
- (Rule 14.6) More than one 'break' terminates loop.
- (Rule 14.8) Left brace expected.
- (Rule 16.3) All parameters shall have identifiers.
- (Rule 16.9) Function identifier used without '&' or parenthesized parameter list.
- (Rule 17.4) Pointer arithmetic other than array indexing used.
-
-
- (Rule 18.4) Unions shall not be used.
- (Rule 19.13) '#/##' operator used in macro.
-
-
-MISRA 1998 checking is achieved using the -misra(1) option. For -MISRA 2004 checks, use -misra(2)
- -You may disable individual rules to your taste by using the Rule number in an esym option.
For example:
-
- -esym( 960, 75, 8? )
-
-will suppress MISRA rules 75 and any of the those between 80 and 89 inclusive that are issued as the result of a 960. See [10] for information on the MISRA guidelines.
-]]> -The list of advisory checks made for both MISRA 1998 and 2004 are: - (Rule 47/12.1) Dependence placed on C's operator precedence (Rule 87/19.1) Only preprocessor statements and comments before '#include'. (Rule 93/19.7) Use of function-like macros is discouraged. (Rule 102/17.5) More than two pointer indirection levels used. - Advisory checks made exclusively for MISRA 1998 are: - (Rule 18) Constant requires numerical suffix (Rule 28) 'register' class discouraged (Rule 40) 'sizeof' used on expressions with side effect (Rule 44) Redundant explicit casting (Rule 55) Non-case label (Rule 60) No 'else' at end of 'if ... else if' chain. (Rule 63) Boolean value in switch expression (Rule 92) Use of '#undef' is discouraged - Advisory checks made exclusively for MISRA 2004 are: - (Rule 19.2) Header file name contains non-standard character. (Rule 19.13) No use of '#' or '##'. - Messages can be suppressed based on rule number. See also Message 960.
]]> -
- .* ? .
-
-are not redefinable and may not be overloaded [11, 13.4].
]]> -
- template< class T > class A { }; // a template
- template<> class A<int> { }; // a specialization
-
-If the 'template<>' is omitted, you will get this message but it will still be interpreted as a specialization. Before the standardization of template syntax was completed, a template specialization did not require this clause and its absence is still permitted by some compilers. -
]]> -
- = () [] ->
-
-The parameter String indicates which it is. [11, #3.4.3 and #3.4.6] -
]]> -
- void f(int i=0, int j, int k=0);
-
-is illegal. [11, #2.6] -
]]> -
- X( const X &)
-
-If you leave off the '&' then a copy constructor would be needed just to copy the argument into the copy constructor. This is a runaway recursion. [11,#2.1] -
]]> -
- namespace name = scoped-identifier
-
-the scoped-identifier must identify a namespace. -
]]> -
- template< class T = abc > class A { /* ... */ };
-
-will be greeted with an Error 1077 only if an instantiation of A<> requires evaluation of the default argument and if that evaluation cannot be made. In that event int is assumed for type parameters and 0 is assumed for object parameters. -
]]> -
- class A : public A { };
-
-You can't define A in terms of itself as there is no escape from the recursive plummet. -
]]> -
- template <class T = A< int ] >
- class X
- {
- };
-
-This will cause PC-lint/FlexeLint to process to the end of the file looking (in vain) for the terminating pointy bracket. Not finding it will cause this message to be printed. Fortunately, the message will bear the Location of the malformed template. -
]]> -
- class X; // declare class X
- X *p; // OK, no definition required
- X a; // Error 1080
-
]]>
-
- template< int *P > class A { ... };
- int a[10];
- A< a+2 > x; // a+2 does not represent a symbol
-
]]>
-
- template< int &I > class A { ... };
- int a[10];
- A< a[2] > x; // a[2] does not represent a symbol
-
-See also message 1081. -
]]> -(Note, explicit specializations would have been considered before determining that the class definition needs to be generated by way of instantiation.) If multiple partial specializations match then:
-In the message, the matching partial specializations are provided as the list of candidates. Example:
-
- template<class T1, class T2, int I> class A {}; //#1
- template<class T1, class T2, int I> class A<T1*, T2, I> {}; //#2
- template<class T1, class T2, int I> class A<T1, T2*, I> {}; //#3
- A<int*, int*, 2> a; // ambiguous: matches #2 and #3
- // (and neither template is more specialized than the other)
-
]]>
-
- template<class T, class U> struct A
- {
- void
- };
- template<class U, class T> void A<T,U>::f(){} // Error 1085
-
-In this case, the template argument list is out of order; T and U have been interchanged. -
]]> -
- using NS::name;
-
-seems to be in error. It introduces a name that clashes with the name introduced earlier by another using-declaration. E.g.:
- -
- namespace N { int i;}
- namespace Q { void i();}
- using N::i;
- using Q::i; // Error 1087 issued here.
-
]]>
-
- class A { protected: int n; };
- class B : public A {
- public:
- using n; // Error 1088: should be 'using A::n;'
- };
-
-See Section <ref,14. Added Bibliography,14.>, [34], 7.3.3 namespace.udecl. -
]]> -
- namespace N { namespace Q{ void g(); } }
- void f() {
- using ::N::Q; // Error 1089
- Q::g();
- }
-
-Instead, use a namespace-alias-definition:
-
- namespace N { namespace Q{ void g(); } }
- void f() {
- namespace Q = ::N::Q; // OK
- Q::g(); // OK, calls ::N::Q::g().
- }
-
-See Section <ref,14. Added Bibliography,14.>, [35], Issue 460. -
]]> -
- template<class T> class A {
- protected:
- template<class U> class B{};
- };
-
- struct D : public A<int> {
- public:
- using A<int>::B<char*>; // Error 1090
- };
-
- D::B<char*> bc;
-
-Instead, refer to the template name without template arguments:
-
- template<class T> class A {
- protected:
- template<class U> class B{};
- };
-
- struct D : public A<int> {
- public:
- using A<int>::B; // OK
- };
-
- D::B<char*> bc; // OK
-
-See Section <ref,14. Added Bibliography,14.>, [34], 7.3.3 namespace.udecl. -
]]> -
- struct N {
- void f();
- }
-
- class A { protected: void f(); };
- class B : A {
- public:
- using N::f; // Error 1091
- };
-
-See Section <ref,14. Added Bibliography,14.>, [35], Issue 400. -
]]> -
- struct A { void f(); };
-
- struct B : A{
- void g() {
- using A::f; // Error 1092
- }
- };
-
-See Section <ref,14. Added Bibliography,14.>, [34], 7.3.3 namespace.udecl. -
]]> -
- // primary template:
- template<class T, T N, class U> struct B;
-
- // PS #1:
- template<class U> struct B<int,257,U>; // Ok
-
- // PS #2:
- template<class U> struct B<bool,257,U>; // Ok, same as:
- template<class U> struct B<bool,true,U>; // Ok (redeclaration of #2)
-
- // PS #3:
- template<class U> struct B<T,257,U>; // Error 1095 here
-
-In PS #3, the value 257 is the 'specialized non-type argument' and its corresponding parameter is 'N' whose type is T which was not made concrete. But in PS #1 and PS #2, T was given the concrete types 'int' and 'bool', respectively. -
]]> -
- struct A
- {
- int n;
- A(int);
- A( const A& p) : A(p.n) {} // Ok
- A() :
- n(42), A(32) // Error 1096
- {}
- };
-
]]>
-
- struct A
- {
- int n;
- A(int x) : A(x){} // Error 1097
- };
-
]]>
-
- template<class T> void f( const T& ); // #1
-
- struct A{};
- template<> void f( const A& ); // Ok
- // (A is the deduced argument to T.)
-
- struct B{};
- template<> void f( const B ); // Error 1097.
- // (A template argument cannot be deduced for T.)
-
]]>
-
- template<class T> struct A {};
-
- template<class T, class U> void f( T*, U ); // #1
- template<class T, class U> void f( T, A<U> ); // #2
-
- struct B{};
- template<> void f( B, A<B> ); // Ok
- // #1 does not match but #2 does.
-
- template<> void f( char*, A<int> ); // Error 1099
- // Both #1 and #2 match and neither is more specialized than the
- // other.
-
-This situation can be avoided in at least a couple of ways. One way is to explicitly specify one or more template arguments. Example:
-
- // continuing from above...
- template<> void f<char*>( char*, A<int> ); // Ok
- // #1 does not match but #2 does.
-
-Another way is to use SFINAE tactics in the declaration of one or more function templates, e.g. with boost::enable_if
]]> -
- template<class T> struct A {};
-
- template<class T> inline void f( A<T> ); // #1
- void f( A<int> ); // #2 // Ok, declares an ordinary function
-
- void f<char>( A<char> ); // Error 1100
-
]]>
-
- int f(void);
- int f(char*);
- auto n = f; // Error
-
-In terms of deduction, this is equivalent to:
-
- int f(void);
- int f(char*);
- template<class T> void g( const T& );
- void h( void )
- {
- g( f ); // Error
- }
-
-Here, 'f' refers to multiple overloaded functions, so it is an ambiguous reference and T cannot be deduced. (Code like this could still be well-formed however, e.g. if g is overloaded with a non-template function whose parameter type is 'ptr-to-function returning int taking (char*)'.) -
]]> -
- float g(void);
- char* s();
- auto a = 42; // Ok, auto is 'int'
- auto b = g(); // Ok, auto is 'float'
- auto c = 'q',
- *d = s(); // Ok, auto is 'char' (for both c and d)
- auto x = 42, y = g(); // Error 1102 here
-
]]>
-
- enum A : bool; // ok
- enum B : short; // ok
- enum C : unsigned long long; // ok
- enum D : float; // Error 1103
-
]]>
-
- enum class A { red, green };
- enum class A x; // Error: don't need 'class'
- enum A : unsigned { red, green };
- enum A : unsigned y; // Error: don't need ': unsigned'
-
]]>
-
- class A
- {
- void f(int) &; // ok (so far)
- void f(int); // 1105
- void f(double); // 1105
- void g(int); // ok (fresh function)
- void g(double); // still ok
- };
-
]]>
-
- enum E : unsigned char { e = 256 };
-
-The value 256 cannot be represented by an unsigned char. -
]]> -
- char *s = u"abc" U"def";
- char *q = L"ghi" u"jkl";
-
-This message is issued for mixing strings of char16_t, char32_t, and/or wchar_t (as shown). Literal string concatenation of any of these with an ordinary character literal is permitted and will receive Informational 707. -
]]> -
- void f( int ) = delete;
- void f( double );
- void g( double d, int n ) {
- f( d ); // Ok
- f( n ); // Error
- }
-
]]>
-
- a->b
-
-it is effectively expanded to:
-
- a.operator->()->b
-
-And this expansion repeats until an operator-> is found that does not yield a class type. But in the process of evaluating this expansion, it might be found that one of the operators returns a class type for which an overloaded operator-> was already expanded; in that case, Error 1110 is triggered. Example:
-
- struct B;
- struct A { struct B& operator->(); };
- struct B { struct A& operator->(); };
- int f( A & p ) { p->g(); } // Error
-
]]>
-
- struct A {
- template <typename U> struct B {};
-
- // template <> // Would be ill-formed by ISO C++.
- // struct B<int> {};
- };
- template<> struct A::B<int> {}; // Ok.
-
-There is an additional limitation with member class templates of class templates. As with members of a non-template class, one cannot write a specialization at class scope. Example:
-
- template<typename T> struct G {
- template <typename U> struct H {};
- // template <> // Would be ill-formed by ISO C++.
- // struct H<int> {};
- };
-
-But the language specification does not even allow this to be expressed in a namespace-scope definition; there is no way to write an explicit specialization that is a member of a class template. Example:
-
- template<typename T> struct J {
- template <typename U> struct K {};
- };
- // template<typename T>
- // template <> // Would be ill-formed by ISO C++;
- // struct J<T>::K<int> {};
-
-This is because the rules for explicit specializations say that 'template<>' is not allowed to appear after a non-empty template-parameter-list within the same declaration. However, one may write an explicit specialization that is a member of an implicitly-instantiated specialization of a class template. Example:
-
- template<typename T> struct L {
- template <typename U> struct M {};
- };
- template <> template <> struct L<char>::M<int> {}; // Ok
-
-Here, the body of the class L<char> is automatically generated by implicit instantiation (otherwise the reference to 'L<char>::M' would be ill-formed), while the body of L<char>:M<int> is provided in the explicit specialization. - -In March of 2009, the ISO C++ committee reviewed a report submitted against this example:
-
- struct A {
- template<class T> struct B;
- template <class T> struct B<T*> { }; // well-formed
- template <> struct B<int*> { }; // ill-formed
- };
-
-While it might seem odd that one is able to write the partial specialization but not the full specialization, the committee (which at the time was in a "feature-freeze" mode and trying to finalize a draft for the next International Standard) decided that this capability would need to be regarded as an "extension", meaning that it could be considered as a new feature in a future standard but not as a bug-fix for C++0x. - -Note that the Microsoft compiler implements this extension. For that reason, the Lint option
-
- -elib(1111)
-
-appears in recent versions of our configuration files for Microsoft compilers
]]> -
- auto f() -> int *;
-
- ... and not:
-
- auto *f() -> int;
-
-This also applies to a type-id (e.g., in a cast to a pointer-to-function, or as an argument to a template type-parameter)
]]> -Example:
-
- template<class T> using X = typename T::type;
- typedef X<int> XI; // error 1113
-
-]]>
-
- class A {
- friend struct B; // ok
- friend struct C {}; // error
- };
-
]]>
-
- class X; ... X *p; ... delete p;
-
-That is, a placeholder declaration for a class is given and an object of that type is deleted before any definition is seen. This may or may not be followed by the actual class definition:
-
- class X { ... };
-
-A delete before the class is defined is dangerous because, among other things, any operator delete that may be defined within the class could be ignored. -
]]> -
- struct A
- {
- char *x;
- void f()
- {
- char y[10];
- x = y; // warning 1414
- }
- };
-
-Here the address of y is being passed to member x but this is dangerous (if not ridiculous) since when the function returns, the storage allocated for y is deallocated and the pointer could very easily harm something. -
]]> -
- class C
- {
- int &n, &m;
- C( int &k ) : n(m), m(k) { /* ... */ }
- };
-
-Here m is initialized properly to be identical to k. However, the initialization of n, taking place, as it does, before m is so initialized, is erroneous. It is undefined what location n will reference. -
]]> -
- class C
- {
- int &n, &m;
- C( int &k ) : n(k) { /* ... */ }
- };
-
]]>
-
- class A : B { int a; };
-
-would make B a private base class by default.
-
- class A : private B { int a; };
-
-is preferred if that's what you want. [11,#1.1] -
]]> -
- void operator=(X);
- void operator=(X) const;
-
-Which is to be used for assignment? -
]]> -
- if( &arg == this )
- if( &arg != this )
- if( this == &arg )
- if( this != &arg )
-
-as the first statement of the function. - -It is important to check for a self assignment so as to know whether the old value should be subject to a delete operation. This is often overlooked by a class designer since it is counter-intuitive to assign to oneself. But through the magic of aliasing (pointers, references, function arguments) it is possible for an unsuspecting programmer to stumble into a disguised self-assignment [12, Item 17]. - -If you are currently using the following test
-
- if( arg == *this)
-
-we recommend you replace this with the more efficient:
-
- if( &arg == this || arg == *this)
-
]]>
-
- class X
- {
- private:
- int a;
- public:
- int *f() { return &a; }
- };
-
-This looks like a breach of the access system [12, Item 30]. You may lower the access rights of the function, raise the accessibility of the member or make the return value a const pointer or reference. In the above example you could change the function to: -
-
- const int *f() { return &a; }
-
]]>
-
- class X
- {
- int *p;
- int *f() const { return p; }
- };
-
-Since f is supposedly const and since p is presumptively pointing to data that is logically part of class X we certainly have the potential for a security breach. Either return a pointer to const or remove the const modifier to the function. [12, Item 29]. - -Note, if a const function returns the address of a data member then a 605 (capability increase) is issued. -
OOP55-CPP. Do not use pointer-to-member operators to access nonexistent members
- - ]]> -
- class B { ... };
- class D : public B
- {
- D( const D &arg ) : B( arg ) { ... }
- ...
- };
-
]]>
-
- class X
- {
- X( const X & );
- };
-
- extern X x1;
- X x2 = x1;
- X x1 = x2;
-
-It is theoretically possible, but unlikely, that the constructor X() is interested only in the address of its argument and not its current value. If so, it only means you will be getting a spurious report which you can suppress based on variable name. However, if the const is missing when passing a reference parameter (or a pointer parameter) then we cannot easily assume that values are being used. In this case no report will be issued. The moral is that if you want to get the checking implied by this message you should make your constructor reference arguments const. -
]]> -
- class B { };
- class D : public B {};
- D a[10];
- B *p = a; // Warning 1547
- B *q = &a[0]; // OK
-
-In this example p is being assigned the address of the first element of an array. This is fraught with danger since access to any element other than the zeroeth must be considered an error (we presume that B and D actually have or have the potential to have different sizes). [23, Item 3]. - -We do not warn about the assignment to q because it appears that the programmer realizes the situation and wishes to confine q to the base object of the zeroeth element of a only. As a further precaution against inappropriate array access, out of bounds warnings are issued for subsequent references to p[1] and q[1]. -
]]> -
- Derived *d = new Derived[10];
- Base *b;
- b = d; // Warning 1552
- b = &d[0]; // OK
-
-[23, Item 3] Also, see the article by Mark Nelson (Bug++ of the Month, Windows developer's Journal, May 1997, pp. 43-44). -
]]> -
- class X
- {
- char *p;
- X( const X & x )
- { p = x.p; }
- ...
- };
-
-Here, member p is expected to be recreated using new or some variant. -
]]> -
- class X
- {
- char *p;
- X& operator=( const X & x )
- { p = x.p; }
- ...
- };
-
-Here, member p is expected to be recreated using new or some variant. -
]]> -
- new int(10)
-
-will draw this warning. The expression allocates an area of storage large enough to hold one integer. It then initializes that integer to the value 10. Could this have been a botched attempt to allocate an array of 10 integers? Even if it was a deliberate attempt to allocate and initialize a single integer, a casual inspection of the code could easily lead a reader astray. - -The warning is only given when the type T has no constructor. If T has a constructor then either a syntactic error will result because no constructor matches the argument or a match will be found. In the latter case no warning will or should be issued. -
]]> -
- class C
- {
- virtual inline void f(); // Warning 1558
- };
-
-Virtual functions by their nature require an address and so inlining such a function seems contradictory. We recommend that the 'inline' function specifier be removed. -
]]> -
- void f( int &x );
- const int n = 0;
- ...
- f(n);
-
-Here, function f() could assign a value to its argument and thereby modify n which is declared to be const. - -The message can also be issued when a pointer is initialized. Consider the following example.
-
- void h( const int *&q );
- int *p;
- ...
- h(p);
-
-It might seem that passing a regular (i.e., non-const) pointer to a const int * could cause no harm. That would be correct if it were not for the reference. If function h() were to assign a pointer to const to its parameter q then upon return from the call, p could be used to modify const data. - -There are many subtle cases that can boggle the mind. See the commentary to Message 605. -
]]> -
- struct B { virtual void f() throw(B); };
- struct D:B { virtual void f() throw(D); };
-
-Here, although the exception specification is not identical, the exception D is considered a subset of the base class B. - -It would not be reasonable for D::f() to throw an exception outside the range of those thrown by B::f() because in general the compiler will only see calls to B::f() and it should be possible for the compiler to deduce what exceptions could be thrown by examining the static call -
]]> -
- p ? a : b = 1
-
-If this is what was intended you should parenthesize the third argument as in:
-
- p ? a : (b = 1)
-
-Not only is the original form difficult to read but C, as opposed to C++, would parse this as:
-
- (p ? a : b) = 1
-
]]>
-
- bool a = 34;
-
-Although there is an implicit conversion from integral to bool and assigning an integer varaible to a bool to obtain its Boolean meaning is legitimate, assigning an integer such as this looks suspicious. As the message suggests, the warning is not given if the value assigned is either 0 or 1. An Elective Note would be raised in that instance. -
]]> -
- class A {
- int a;
- public:
- void f();
- A() { f(); }
- };
-
-Here f() is presumably serving as an initializer for the constructor A::A(). To inform PC-lint/FlexeLint of this situation, use the option:
-
- -sem( A::f, initializer )
-
-This will suppress Warning 1566 for any constructor of class A that calls A::f. -
]]> -
- a.cpp: b.cpp:
-
- int g(void); int f(void);
- int y = g(); int x = f();
- int f() { return y; }
-
-The initialization of both x and y are dynamic. Although the order of dynamic initialization within a module is pre-ordained the order in which modules are initialized is not. Therefore it is perfectly possible for b.cpp to be initialized before a.cpp. Thus when the call is made upon function f() to initialize x, variable y may not yet have been initialized. -
]]> -
- int g(void);
- int f(void);
- int x = f();
- int y = g();
- int f() { return y; }
-
-The initialization of both x and y are dynamic. The order of dynamic initialization within a module is in the order in which the initialization is specified. Thus when the call is made upon function f() to initialize x, variable y will not yet have been initialized. -
]]> -
- struct A { int &n; A() : n(3) {} };
-
-The constructor A() contains an initializer list within which it initializes n. But n will be bound to a temporary created by the compiler to hold the value 3. The lifetime of this temporary is limited; it "persists until the constructor exits" [10 section class.temporary] -
]]> -
- class X { int &n; X(int k) :n(k) {} };
-
-In this example member n is being bound to variable k which, although a parameter, is nonetheless placed into auto storage. But the lifetime of k is only the duration of the call to the constructor, whereas the lifetime of n is the lifetime of the class object constructed. -
]]> -
- void f( int n ) { static int& r = n; ... }
-
-The reference r will be permanently bound to an auto variable n. The lifetime of n will not extend beyond the life of the function. On the second and subsequent calls to function f the static variable r will be bound to a non-existent entity. -
]]> -
- namespace X
- {
- template< class T >
- void f( int, const T& ); // Generic
- class A{}; // Warning 1573
- }
-
-A call to function f that contained an argument of type X::A would, by ADL (Argument Dependent Lookup), need to also consider function X::f even though this function was not in the scope of the call. In the past this has led to strange an unexpected results. - -Some designers adopt the strategy of embedding the class within a sub namespace and employing a using-declaration to make it available to users of the original namespace. For example:
-
- namespace X
- {
- template< class T >
- void f( int, const T& ); // Generic
- namespace X1
- {
- class A{}; // No Warning
- }
- using X1::A;
- }
-
-Now an argument of type X::A will not automatically trigger a consideration of X::f. -
]]> -
- int &f( int k )
- {
- int &r = k;
- return r;
- }
-
]]>
-
- class A {
- int *p;
- public:
- void release_ptrs();
- ~A() { release_ptrs(); }
- };
-
-Here release_ptrs() is presumably serving as a cleanup function for the destructor ~A::A(). To inform PC-lint/FlexeLint of this situation, use the option:
-
- -sem( A::release_ptrs, cleanup )
-
-A separate message (Warning 1578) will be issued if the cleanup function fails to clear all pointers. See also Warning 1566. -
]]> --a = b = c --[11, ?13.4.3] - - ]]> -
Example:
-
- template<class T, class U> struct A;
- template<class T, class U> struct A<T*, U> { };
- template<class T, class U> struct A<T, U*> { };
- A<int*, char*> x; // Error 1084 followed by Info 1723
-
-]]>
- -int f( const int & k ) { return k; } --Declaring a parameter a reference to const offers advantages that a mere reference does not. In particular, you can pass constants, temporaries and const types into such a parameter where otherwise you may not. In addition it can offer better documentation. -Other situations in which a const can be added to a declaration are covered in messages 818, 952, 953 and 954. - - ]]> -
- if( arg == sizeof(class) ) - if( arg != sizeof(class) ) - if( sizeof(class) == arg ) - if( sizeof(class) != arg ) --or the equivalent. If any such function is found that is a member of a class that is the base of a derivation, then in addition to Note 1921, we issue Warning 1531. (see Steve Simpson, "More on Memory Management", Dr. Dobb's Journal, August 1994, p. 10). -
- if( arg ) - if( arg == 0 ) - if( arg != NULL ) --etc. Classes which have destructors will normally filter out passing the NULL pointer into the operator delete so that this message is only in the Elective Note category. If there is no destructor you obtain a warning. See Warning 1532. - ]]> -
The list of checks made are as follows:
-
- (Rule 0-1-8) Void return type for function without external side-effects.
- (Rule 2-13-2) Octal constant or escape sequence used.
- (Rule 2-13-4) Lower case literal suffix.
- (Rule 3-1-1) Object/function definitions in headers.
- (Rule 3-1-2) Function not declared at file scope.
- (Rule 3-2-3) Object/function previously declared in location.
- (Rule 3-9-3) Bit representation of a floating point type used.
- (Rule 4-5-1) Boolean expression used with non-permitted operator.
- (Rule 4-5-3) Plain char used with prohibited operator.
- (Rule 5-0-3) Implicit conversion of cvalue.
- (Rule 5-0-4) Implicit conversion changes signedness.
- (Rule 5-0-5) Implicit conversion between integer and floating point types.
- (Rule 5-0-6) Implicit conversion to smaller type.
- (Rule 5-0-7) Cast of cvalue between integer and floating point types.
- (Rule 5-0-8) Cast of cvalue to larger type.
- (Rule 5-0-9) Cast of cvalue changes signedness.
- (Rule 5-0-10) Recasting required for operators '~' and '<<'.
- (Rule 5-0-11) Disallowed use of non-character value.
- (Rule 5-0-12 Disallowed use of non-numeric value.
- (Rule 5-0-15) Pointer arithmetic other than array indexing used.
- (rule 5-0-19) More than two pointer indirection levels used.
- (Rule 5-0-21) Bitwise operator applied to signed underlying type.
- (Rule 5-2-1) Non-postfix expression used with logical operator.
- (Rule 5-2-5) Attempt to cast away const/volatile from a pointer or reference.
- (Rule 5-2-12) Array-pointer decay when passing the array to a function.
- (Rule 5-3-1) Boolean expresion required for operator.
- (Rule 5-3-2) Prohibited operator applied to unsigned underlying type: .
- (Rule 5-3-3) Overloading unary &.
- (Rule 5-3-4) 'sizeof' used on expressions with side effect.
- (Rule 5-14-1) Side effects on right hand side of logical operator.
- (Rule 5-18-1) Comma operator used.
- (Rule 6-2-3) Null statement not in line by itself.
- (Rules 6-3-1 and 6-4-1) Left brace expected for if, else, for, do, switch and while.
- (Rule 6-4-2) No 'else' at end of 'if ... else if' chain.
- (Rule 6-4-7) Boolean value in switch expression.
- (Rule 6-6-2) Gotos jumping to an earlier point in the code.
- (Rule 6-6-3) continue statement should not be used.
- (Rule 6-6-4) More than one 'break' terminates loop.
- (Rule 7-3-1) Global declarations other than main(), namespace declarations, extern "C" declarations and arithmetic typedefs.
- (Rule 7-3-2) Using the identifier main for functions other than the global one.
- (Rule 7-3-3) Unnamed namespaces in headers.
- (Rule 7-3-4) No using-directives allowed.
- (Rule 7-3-6) using-directives or using declarations (except class and/or block scope using declarations) in header files.
- (Rule 8-0-1) Multiple declarators in a declaration.
- (Rule 8-4-1) Function has variable number of arguments.
- (Rule 8-4-2) Function parameter list differs
- (Rule 8-4-4) Function identifier used without '&' or parenthisized parameter list.
- (Rule 8-5-3) Should initialize either all enum members or only the first.
- (Rule 9-5-1) Unions shall not be used.
- (Rule 11-0-1) Non-private data member within a no-POD structure.
- (Rule 12-8-2) Public copy constructor in abstract class.
- (Rule 14-8-1) Explicit specialization of overloaded function templates.
- (Rule 15-1-2) Explicit throw of the Null macro.
- (Rule 15-1-3) Empty throw outside of a catch block.
- (Rule 15-3-7) Catch handler after catch(...) in a try-catch sequence.
- (Rule 16-0-1) Only preprocessor statements and comments before '#include'.
- (Rule 16-0-2) '#define/#undef' used within a block.
- (Rule 16-0-3) Use of '#undef' is discouraged.
- (Rule 16-0-4) Use of function-like macros is discouraged.
- (Rule 16-1-1) Non-standard use of 'defined' preprocessor operator.
- (Rule 16-2-4) Header file name with non-standard character: .
- (Rule 16-3-1) Multiple use of '#' and/or '##' operators in macro definition.
- (Rule 17-0-2) Re-use of reserved identifier
-
-You may disable individual rules to your taste by using the Rule number in an esym option; see Message 960.
- ]]> -The list of checks made are as follows:
-
- (Rule 2-5-1) Possible digraph used.
- (Rule 5-0-2) Dependence placed on C's operator precedence.
- (Rule 5-2-10) Increment or decrement combined with another operator.
- (Rule 14-8-2) Mixing template and non-template functions in a viable sets.
- (Rule 15-0-2) Throwing a pointer expression.
- (Rule 16-2-5) Header file name with non-standard character.
- (Rule 16-3-2) No use of '#' or '##'.
-
-]]>
-
- { label: { goto label; } }
-
-is permitted but
-
- { goto label; { label: } }
-
-is not. To assist the programmer, the message refers to the blocks using an identification code (Example: "1.2.1"). This identification scheme is defined as follows.
-Thus in the following 'code',
-
- { { } { { label: } { } } }
-
-label: lies in block 1.2.1.
]]> -
- #include <initializer_list>
-
- std::initializer_list<int> f() {
- return { 1, 2, 3 }; // The memory used to store the array
- // elements will be freed before returning.
- }
-
- void g() {
- auto x = f(); // Attempting to access the elements of x will read invalid memory.
- }
]]>
-
- void foo(int *pi) {
- if (!pi) return; // Okay
- if (&pi == 0) return; // 2440
- if (foo != 0) return; // 2440
- }
-
-The first string parameter is one of 'function', 'array', or 'address -of' and the second string parameter represents the corresponding -function, array, or variable.
]]> -
- void foo(int *pi) {
- if (!pi) return; // Okay
- if (&pi) return; // 2441
- if (!foo) return; // 2441
- }
-
-The first string parameter is one of 'function', 'array', or 'address -of' and the second string parameter represents the corresponding -function, array, or variable.
]]> -
- void foo(int i) {
- int (*pf)(float) = &foo; // Warning 2455
- }
]]>
-
- void f(int a) {
- int* p = &a;
- p[0] = 0;
- p[1] = 0; // Warning 2662
- p + 0;
- p + 1; // Warning 2662
- }
]]>
-
- template<typename T>
- void f(T&& t) {
- g(std::move(t)); // might unexpectedly move from the caller's lvalue
- }
]]>
-
- void foo(int &i) {
- int &ri = i;
- if (&i == 0) return; // 3408
- if (&i != 0) return; // 3408
- }
]]>
-
- void foo(int &i) {
- int &ri = i;
- if (&i) return; // 3409
- if (&ri) return; // 3409
- if (!&i) return; // 3409
- }
]]>
-
- template <typename T>
- T foo(T);
-
- template<> // warning 3420
- template<>
- int foo(int);
]]>
-
- void foo(unsigned u) {
- switch(u) {
- case -1: // warning 3423, cannot narrow -1 to unsigned
- break;
- ...
- }
- }
-
- template <unsigned char I>
- struct S { unsigned char value = I; };
- S<300> s; // warning 3423, cannot narrow 300 to unsigned char
]]>
-
- struct X { ... };
-
- void foo() {
- &X(); // warning 3430
- }
]]>
-
- template <typename... T>
- void foo() {
- bar([] {
- void g(T t...); // warning 3703, probably meant g(T... t);
- }...);
- }
]]>
-
- struct X { };
- struct Y {
- Y(const X&);
- };
-
- void foo() {
- Y y(X()); // warning 3705
- }
-
-Here y is interpreted as a function that returns an object of type Y and -takes a single parameter that is a pointer to a function taking no -arguments and returning type X. In particular, it is not interpreted as -a declaration of an object of type Y initialized with a temporary of -type X as was almost certainly intended.
- -There are several ways to force interpretation of a variable -declaration. In and later the simplest way is to employ uniform -initialization syntax, for example any of the following would work:
-
- Y y1(X{}); // OK, variable declaration
- Y y2{X()}; // OK, variable declaration
- Y y3{X{}}; // OK, variable declaration
-
-Prior to , an extra pair of parenthesis can be used to force the desired -interpretation, e.g.:
-
- Y y4((X())); // OK, variable declaration
-
-The same issue can appear with casts, for example:
-
- void foo(double d) {
- int i( int(d) ); // warning 3705
- }
-
-In this case, i is not a variable initialized with the truncated value -of d but rather a function returning int and taking int. In addition to -the methods mentioned above to force a variable declaration, the -functional cast can be converted to a C-style cast or a named cast, -e.g.:
-
- int i1( (int) d ); // OK, variable declaration
- int i2( static_cast<int>(d) ); // OK, variable declaration
]]>
-
- if (x)
-
-will elicit this message while:
-
- if (x != 0)
-
-will not. ";Effectively boolean"; value are produced by the operators ==, -!=, <=, >=, <, >, !, ||, and &&.
]]> -CheckId
of your custom rule, a title, a description, and a default severity.
+ switch( n )
+ {
+ case 1: m = 25; break;
+ case 2-1: m = 27; break;
+ }
+
+]]>
+
+ enum E; // Error
+
+This is prohibited by ISO C and ISO C++98. In C++0x, we can modify this example to be well-formed by explicitly indicating the underlying integral type; example:
+
+ enum E : unsigned short; // Ok
+
+If you are not using C++0x and/or your compiler supports the construct you may simply suppress this message with a -e165.
]]> +
+ __attribute__((mode(DF)));
+
+This is supposed to match a built-in scalar type whose size is the size indicated in the message. If this message is issued, it probably means that size options have not been set to match the compile configuration; see Section 5.3, Size and Alignment Options.
+]]> +
+ double radius,
+ diameter;
+
+the programmer had typed:
+
+ double radius;
+ diameter;
+
]]>
+ ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ + ]]> +ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ + ]]> +ARR38-C. Guarantee that library functions do not form invalid pointers
+ ]]> +ARR38-C. Guarantee that library functions do not form invalid pointers
+ + ]]> +MEM31-C. Free dynamically allocated memory when no longer needed
+ + ]]> +
+ int *p = new int[20]; // p is a custodial pointer
+ int *q = p; // p is no longer custodial
+ p = new int[20]; // p again becomes custodial
+ q = p + 0; // p remains custodial
+
++Here p does not lose its custodial property by merely participating in an arithmetic operation. +A pointer can lose its custodial property by passing the pointer to a function. If the parameter of the function is typed pointer to const or if the function is a library function, that assumption is not made. For example
+
+ p = malloc(10);
+ strcpy (p, "hello");
+
+Then p still has custody of storage allocated.
+It is possible to indicate via semantic options that a function will take custody of a pointer.
+MEM31-C. Free dynamically allocated memory when no longer needed
+ ]]> +
+ malloc( strlen(e+1) )
+
+where e is some expression. This is suspicious because it closely resembles the commonly used pattern:
+
+ malloc( strlen(e)+1 )
+
+If you really intended to use the first pattern then an equivalent expression that will not raise this error is:
+
+ malloc( strlen(e)-1 )
]]>
+
+ int *p = malloc(1);
+
+This message is also provided for user-declared allocation functions. For example, if a user's own allocation function is provided with the following semantic:
+
+ -sem(ouralloc,@P==malloc(1n))
+
+We would report the same message. Please note that it is necessary to designate that the returned area is freshly allocated (ala malloc). + This message is always given in conjunction with the more general Informational Message 826.
+
+ Example:
+
+ #define FOO(p) p
+
+ FOO(
+ #define X Y
+ )
+
+According to the ISO Standards, this results in undefined behavior.
+ +By the rules of Standard C the preprocessing directive is + absorbed into the macro argument but then will not subsequently + get executed. For this reason some compilers treat the apparent + preprocessor directive as a directive. This is logical but not + portable. It is therefore best to avoid this construct.
]]> +
+ void f( int i )
+ {
+ int a[2] = {i++, i++};
+ }
+
+The values of the array elements are unspecified because the order of evaluation is unspecified by the C standard.
]]> +
+ enum colors { red, blue, green = 1 };
+
+will elicit this informational message while
+
+ enum colors { red, blue = 1, green = 1 };
+
+will not.
]]> +
+ defined(identifier)
+ defined identifier
+
+Additionally, the preprocessor operator may not result from the expansion of another macro. This diagnostic highlights departures from these requirements as non-portable code.
+ + ]]> +
+ u >= 0 0 <= u
+ u < 0 0 > u
+
+are suspicious if u is an unsigned quantity or a quantity judged to be never less then 0. See also message 775.
]]> +
+ u / n
+
+where u is unsigned and n is signed will elicit this message whereas:
+
+ u / 4
+
+will not, even though 4 is nominally an int. It is not a good idea to mix unsigned quantities with signed quantities in any case (a 737 will also be issued) but, with division, a negative value can create havoc. For example, the innocent looking:
+
+ n = n / u
+
+will, if n is -2 and u is 2, not assign -1 to n but will assign some very large value.
+To resolve this problem, either cast the integer to unsigned if you know it can never be less than zero or cast the unsigned to an integer if you know it can never exceed the maximum integer.
]]> +
+> >= < <=
+
+One of the operands to a relational operator was signed and the other unsigned; also, the signed quantity could be negative. For example:
+
+ if( u > n ) ...
+
+where u is unsigned and n is signed will elicit this message whereas:
+
+ if( u > 12 ) ...
+
+will not (even though 12 is officially an int it is obvious that it is not negative). It is not a good idea to mix unsigned quantities with signed quantities in any case (a 737 will also be issued) but, with the four relationals, a negative value can produce obscure results. For example, if the conditional:
+
+ if( n < 0 ) ...
+
+is true then the similar appearing:
+
+ u = 0; if( n < u ) ...
+
+is false because the promotion to unsigned makes n very large.
+To resolve this problem, either cast the integer to unsigned if you know it can never be less than zero or cast the unsigned to an int if you know it can never exceed the maximum int.
]]> +For example:
+
+ pattern = "(???) ???-????"; // warning 585
+ pattern = "(?\?\?) ?\?\?-?\?\?\?"; // no warning
+ #define Q "?"
+ pattern = "(" Q Q Q ") " Q Q Q "-" Q Q Q Q // no warning
+
]]>
+
+ char msg[100];
+ ...
+ printf( msg );
+
+This can easily be rewritten to the relatively safe:
+
+ char msg[100];
+ ...
+ printf( "%s", msg );
+
+The danger lies in the fact that msg can contain hidden format codes. If msg is read from user input, then in the first example, a naive user could cause a glitch or a crash and a malicious user might exploit this to undermine system security. Since the unsafe form can easily be transformed into the safe form the latter should always be used. +
+ ]]> +
+ void f( int n )
+ {
+ int *p = new int;
+ if( n ) delete p;
+ } // message 593
+
+In this example an allocation is made and, if n is 0, no delete will have been made. +Please see message 429 for an explanation of "custodial" and ways of regulating when pointer variables retain custody of allocations. +
+ ]]> +
+ i << 32
+
+will elicit this message if i is typed int and where int is 32 bits wide or less (the usual case). Such shift results in undefined behavior.
+To suppress the message you may cast the shifted quantity to a type whose length is at least the length of the shift value.
]]> +
+ int *p;
+ const int *q;
+ p = q; /* 605 */
+
+The message will be inhibited if a cast is used as in:
+
+ p = (int *) q;
+
+An increase in capability is indicated because the const pointed to by q can now be modified through p. This message can be given for the volatile qualifier as well as the const qualifier and may be given for arbitrary pointer depths (pointers to pointers, pointers to arrays, etc.). +If the number of pointer levels exceeds one, things get murky in a hurry. For example:
+
+ const char ** ppc;
+ char ** pp;
+ pp = ppc; /* 605 - clearly not safe */
+ ppc = pp; /* 605 - looks safe but it's not */
+
+It was not realized by the C community until very recently that assigning pp to ppc was dangerous. The problem is that after the above assignment, a pointer to a const char can be assigned indirectly through ppc and accessed through pp which can then modify the const char. +The message speaks of an "increase in capability" in assigning to ppc, which seems counter intuitive because the indirect pointer has less capability. However, assigning the pointer does not destroy the old one and the combination of the two pointers represents a net increase in capability. +The message may also be given for function pointer assignments when the prototype of one function contains a pointer of higher capability than a corresponding pointer in another prototype. There is a curious inversion here whereby a prototype of lower capability translates into a function of greater trust and hence greater capability (a Trojan Horse). For example, let
+
+ void warrior( char * );
+
+be a function that destroys its argument. Consider the function:
+
+ void Troy( void (*horse)(const char *) );
+
+Troy() will call horse() with an argument that it considers precious believing the horse() will do no harm. Before compilers knew better and believing that adding in a const to the destination never hurt anything, earlier compilers allowed the Greeks to pass warrior() to Troy and the rest, as they say, is history.
]]> ++(long) (n << 8) ++might elicit this message if n is unsigned int, whereas +
+(long) n << 8 ++would not. In the first case, the shift is done at int precision and the high order 8 bits are lost even though there is a subsequent conversion to a type that might hold all the bits. In the second case, the shifted bits are retained. +
The operations that are scrutinized and reported upon by this message are: shift left, multiplication, and bit-wise complementation. Addition and subtraction are covered by Informational message 776.</description></rule>
+The conversion to long may be done explicitly with a cast as shown or implicitly via assignment, return, argument passing or initialization.
+The message can be suppressed by casting. You may cast one of the operands so that the operation is done in full precision as is given by the second example above. Alternatively, if you decide there is really no problem here (for now or in the future), you may cast the result of the operation to some form of int. For example, you might write:
++(long) (unsigned) (n << 8) ++In this way PC-lint/FlexeLint will know you are aware of and approve of the truncation. + + ]]> +
+ int a[10];
+ if( n <= 10 ) a[n] = 0;
+
+Here the programmer presumably should have written n<10. This message is similar to messages 415 and 796 but differs from them by the degree of probability.
+ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ + ]]> +
+ int a[10];
+ if( n <= 20 ) f( a + n );
+
+Here, it appears as though an illicit pointer is being created, but PC-lint/FlexeLint cannot be certain. See also messages 416 and 797.
+ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ + ]]> +ARR38-C. Guarantee that library functions do not form invalid pointers
+ + ]]> +ARR38-C. Guarantee that library functions do not form invalid pointers
+ + ]]> +MEM31-C. Free dynamically allocated memory when no longer needed
+ + ]]> +INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
+ + ]]> +INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
+ + ]]> +INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
+ + ]]> +
+ int a[10];
+ int j = 100;
+ for( i = 0; i < n; i++ )
+ j = n;
+ a[j] = 0;
+
+Here, the access to a[j] is flagged because it is conceivable that the for loop is not executed leaving the unacceptable index of 100 in variable j. This message is similar to messages 415 and 661 but differing from them by the degree of probability.
+ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ + ]]> +ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ + ]]> +ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ARR38-C. Guarantee that library functions do not form invalid pointers
+ + ]]> +ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
+ARR38-C. Guarantee that library functions do not form invalid pointers
+ + ]]> ++int f( char * const p, const int n ) { return *p = n; } ++There are few advantages to declaring an unchanging parameter a const. It signals to the person reading the code that a parameter is unchanging, but, in the estimate of most, reduces legibility. For this reason the message has been given an Elective Note status. +However, there is a style of programming that encourages declaring parameters const. For the above example, this style would declare f as +
+int f( char * p, int n); ++and would use the const qualifier only in the definition. Note that the two forms are compatible according to the standard. The declaration is considered the interface specification where the const's do not matter. The const's do matter in the definition of the function which is considered the implementation. Message 952 could be used to support this style. +Marking a parameter as const does not affect the type of argument that can be passed to the parameter. In particular, it does not mean that only const arguments may be passed. This is in contrast to declaring a parameter as pointer to const or reference to const. For these situations, Informational messages are issued (818 and 1764 respectively) and these do affect the kinds of arguments that may be passed. See also messages 953 and 954. + + ]]> +
The list of required checks made for both MISRA 1998 and 2004 are:
+
+ (Rule 16/12.12) Bit representation of a floating point type used.
+ (Rule 19/7.1) Octal constant used.
+ (Rule 22/8.7) Could define variable at block scope.
+ (Rule 27/8.8) Object/function previously declared.
+ (Rule 32/9.3) Should initialize either all enum members or only the first.
+ (Rule 33/12.4) Side effects on right hand side of logical operator.
+ (Rule 34/12.5) Non-primary expression used with logical operator.
+ (Rule 36/12.6) Boolean expression required for operator.
+ (Rule 40/12.3) 'sizeof' used on expressions with side effect
+ (Rule 42/12.10) Comma operator used outside of 'for' expression.
+ (Rule 47/12.1) Dependence placed on C operator precedence.
+ (Rule 54/14.3) Null statement not in line by itself.
+ (Rule 57/14.5) continue statement should not be used.
+ (Rules 59/14.8 & 14.9) Left brace expected for if, else, for, do, and while.
+ (Rule 60/14.10) No 'else' at end of 'if ... else if' chain.
+ (Rule 63/15.4) Boolean value in switch expression.
+ (Rule 65/13.4) Floating point variable used as loop counter.
+ (Rule 68/8.6) Function not declared at file scope.
+ (Rule 69/16.1) Function has variable number of arguments.
+ (Rule 73/16.3) Either all parameters or no parameters should have identifiers.
+ (Rule 74/16.4) Parameter list differs from prior declaration for function.
+ (Rule 87/19.1) Declaration before #include.
+ (Rule 88/19.2) Header file name with non-standard character.
+ (Rule 91/19.5) '#define/#undef' used within a block.
+ (Rule 92/19.6) Use of '#undef' prohibited.
+ (Rule 98/19.12) Multiple use of '#' and/or '##' operators in macro definition.
+ (Rule 100/19.14) Non-standard use of 'defined' preprocessor operator.
+ (Rule 115/20.2) Re-use of C90 identifier/identifier pattern.
+
+ Required checks made exclusively for MISRA 1998 are:
+
+ (Rule 8) Multibyte characters and wide string literals prohibited.
+ (Rule 42) Comma operator used outside of 'for' expression.
+ (Rule 54) Null statement not in line by itself.
+ (Rule 58) break used outside of a switch.
+ (Rule 73) Either all parameters or no parameters should have identifiers.
+ (Rule 87) Declaration before #include.
+ (Rule 88) Header file name contains non-standard character.
+ (Rule 110) Bitfields inside union.
+
+ Required checks made exclusively for MISRA 2004 are:
+
+ (Rule 4.1) Prohibited escape sequence used.
+ (Rule 6.1) Disallowed use of non-character value.
+ (Rule 6.2) Disallowed use of non-numeric value.
+ (Rule 8.5) No definitions of objects or function in header files.
+ (Rules 10.1 & 10.2) Prohibited implicit conversion.
+ (Rules 10.3 & 10.4) Prohibited cast of complex expressions.
+ (Rule 10.5) Recasting required for operators '~' and '<<'.
+ (Rule 10.6) Unsigned integer literals require a 'U' suffix.
+ (Rule 11.5) Attempt to cast away const/volatile from a pointer or reference.
+
+ (Rule 12.7) Bitwise operator applied to signed underlying type.
+ (Rule 12.9) Prohibited operator applied to unsigned underlying type.
+ (Rule 12.10) Comma operator used.
+ (Rule 12.13) Increment or decrement combined with another operator.
+ (Rule 14.3) Null statement not in line by itself.
+ (Rule 14.6) More than one 'break' terminates loop.
+ (Rule 14.8) Left brace expected.
+ (Rule 16.3) All parameters shall have identifiers.
+ (Rule 16.9) Function identifier used without '&' or parenthesized parameter list.
+ (Rule 17.4) Pointer arithmetic other than array indexing used.
+
+
+ (Rule 18.4) Unions shall not be used.
+ (Rule 19.13) '#/##' operator used in macro.
+
+
+MISRA 1998 checking is achieved using the -misra(1) option. For +MISRA 2004 checks, use -misra(2)
+ +You may disable individual rules to your taste by using the Rule number in an esym option.
For example:
+
+ -esym( 960, 75, 8? )
+
+will suppress MISRA rules 75 and any of the those between 80 and 89 inclusive that are issued as the result of a 960. See [10] for information on the MISRA guidelines.
+]]> +The list of advisory checks made for both MISRA 1998 and 2004 are: + (Rule 47/12.1) Dependence placed on C's operator precedence (Rule 87/19.1) Only preprocessor statements and comments before '#include'. (Rule 93/19.7) Use of function-like macros is discouraged. (Rule 102/17.5) More than two pointer indirection levels used. + Advisory checks made exclusively for MISRA 1998 are: + (Rule 18) Constant requires numerical suffix (Rule 28) 'register' class discouraged (Rule 40) 'sizeof' used on expressions with side effect (Rule 44) Redundant explicit casting (Rule 55) Non-case label (Rule 60) No 'else' at end of 'if ... else if' chain. (Rule 63) Boolean value in switch expression (Rule 92) Use of '#undef' is discouraged + Advisory checks made exclusively for MISRA 2004 are: + (Rule 19.2) Header file name contains non-standard character. (Rule 19.13) No use of '#' or '##'. + Messages can be suppressed based on rule number. See also Message 960.
]]> +
+ .* ? .
+
+are not redefinable and may not be overloaded [11, 13.4].
]]> +
+ template< class T > class A { }; // a template
+ template<> class A<int> { }; // a specialization
+
+If the 'template<>' is omitted, you will get this message but it will still be interpreted as a specialization. Before the standardization of template syntax was completed, a template specialization did not require this clause and its absence is still permitted by some compilers. +
]]> +
+ = () [] ->
+
+The parameter String indicates which it is. [11, #3.4.3 and #3.4.6] +
]]> +
+ void f(int i=0, int j, int k=0);
+
+is illegal. [11, #2.6] +
]]> +
+ X( const X &)
+
+If you leave off the '&' then a copy constructor would be needed just to copy the argument into the copy constructor. This is a runaway recursion. [11,#2.1] +
]]> +
+ namespace name = scoped-identifier
+
+the scoped-identifier must identify a namespace. +
]]> +
+ template< class T = abc > class A { /* ... */ };
+
+will be greeted with an Error 1077 only if an instantiation of A<> requires evaluation of the default argument and if that evaluation cannot be made. In that event int is assumed for type parameters and 0 is assumed for object parameters. +
]]> +
+ class A : public A { };
+
+You can't define A in terms of itself as there is no escape from the recursive plummet. +
]]> +
+ template <class T = A< int ] >
+ class X
+ {
+ };
+
+This will cause PC-lint/FlexeLint to process to the end of the file looking (in vain) for the terminating pointy bracket. Not finding it will cause this message to be printed. Fortunately, the message will bear the Location of the malformed template. +
]]> +
+ class X; // declare class X
+ X *p; // OK, no definition required
+ X a; // Error 1080
+
]]>
+
+ template< int *P > class A { ... };
+ int a[10];
+ A< a+2 > x; // a+2 does not represent a symbol
+
]]>
+
+ template< int &I > class A { ... };
+ int a[10];
+ A< a[2] > x; // a[2] does not represent a symbol
+
+See also message 1081. +
]]> +(Note, explicit specializations would have been considered before determining that the class definition needs to be generated by way of instantiation.) If multiple partial specializations match then:
+In the message, the matching partial specializations are provided as the list of candidates. Example:
+
+ template<class T1, class T2, int I> class A {}; //#1
+ template<class T1, class T2, int I> class A<T1*, T2, I> {}; //#2
+ template<class T1, class T2, int I> class A<T1, T2*, I> {}; //#3
+ A<int*, int*, 2> a; // ambiguous: matches #2 and #3
+ // (and neither template is more specialized than the other)
+
]]>
+
+ template<class T, class U> struct A
+ {
+ void
+ };
+ template<class U, class T> void A<T,U>::f(){} // Error 1085
+
+In this case, the template argument list is out of order; T and U have been interchanged. +
]]> +
+ using NS::name;
+
+seems to be in error. It introduces a name that clashes with the name introduced earlier by another using-declaration. E.g.:
+ +
+ namespace N { int i;}
+ namespace Q { void i();}
+ using N::i;
+ using Q::i; // Error 1087 issued here.
+
]]>
+
+ class A { protected: int n; };
+ class B : public A {
+ public:
+ using n; // Error 1088: should be 'using A::n;'
+ };
+
+See Section <ref,14. Added Bibliography,14.>, [34], 7.3.3 namespace.udecl. +
]]> +
+ namespace N { namespace Q{ void g(); } }
+ void f() {
+ using ::N::Q; // Error 1089
+ Q::g();
+ }
+
+Instead, use a namespace-alias-definition:
+
+ namespace N { namespace Q{ void g(); } }
+ void f() {
+ namespace Q = ::N::Q; // OK
+ Q::g(); // OK, calls ::N::Q::g().
+ }
+
+See Section <ref,14. Added Bibliography,14.>, [35], Issue 460. +
]]> +
+ template<class T> class A {
+ protected:
+ template<class U> class B{};
+ };
+
+ struct D : public A<int> {
+ public:
+ using A<int>::B<char*>; // Error 1090
+ };
+
+ D::B<char*> bc;
+
+Instead, refer to the template name without template arguments:
+
+ template<class T> class A {
+ protected:
+ template<class U> class B{};
+ };
+
+ struct D : public A<int> {
+ public:
+ using A<int>::B; // OK
+ };
+
+ D::B<char*> bc; // OK
+
+See Section <ref,14. Added Bibliography,14.>, [34], 7.3.3 namespace.udecl. +
]]> +
+ struct N {
+ void f();
+ }
+
+ class A { protected: void f(); };
+ class B : A {
+ public:
+ using N::f; // Error 1091
+ };
+
+See Section <ref,14. Added Bibliography,14.>, [35], Issue 400. +
]]> +
+ struct A { void f(); };
+
+ struct B : A{
+ void g() {
+ using A::f; // Error 1092
+ }
+ };
+
+See Section <ref,14. Added Bibliography,14.>, [34], 7.3.3 namespace.udecl. +
]]> +
+ // primary template:
+ template<class T, T N, class U> struct B;
+
+ // PS #1:
+ template<class U> struct B<int,257,U>; // Ok
+
+ // PS #2:
+ template<class U> struct B<bool,257,U>; // Ok, same as:
+ template<class U> struct B<bool,true,U>; // Ok (redeclaration of #2)
+
+ // PS #3:
+ template<class U> struct B<T,257,U>; // Error 1095 here
+
+In PS #3, the value 257 is the 'specialized non-type argument' and its corresponding parameter is 'N' whose type is T which was not made concrete. But in PS #1 and PS #2, T was given the concrete types 'int' and 'bool', respectively. +
]]> +
+ struct A
+ {
+ int n;
+ A(int);
+ A( const A& p) : A(p.n) {} // Ok
+ A() :
+ n(42), A(32) // Error 1096
+ {}
+ };
+
]]>
+
+ struct A
+ {
+ int n;
+ A(int x) : A(x){} // Error 1097
+ };
+
]]>
+
+ template<class T> void f( const T& ); // #1
+
+ struct A{};
+ template<> void f( const A& ); // Ok
+ // (A is the deduced argument to T.)
+
+ struct B{};
+ template<> void f( const B ); // Error 1097.
+ // (A template argument cannot be deduced for T.)
+
]]>
+
+ template<class T> struct A {};
+
+ template<class T, class U> void f( T*, U ); // #1
+ template<class T, class U> void f( T, A<U> ); // #2
+
+ struct B{};
+ template<> void f( B, A<B> ); // Ok
+ // #1 does not match but #2 does.
+
+ template<> void f( char*, A<int> ); // Error 1099
+ // Both #1 and #2 match and neither is more specialized than the
+ // other.
+
+This situation can be avoided in at least a couple of ways. One way is to explicitly specify one or more template arguments. Example:
+
+ // continuing from above...
+ template<> void f<char*>( char*, A<int> ); // Ok
+ // #1 does not match but #2 does.
+
+Another way is to use SFINAE tactics in the declaration of one or more function templates, e.g. with boost::enable_if
]]> +
+ template<class T> struct A {};
+
+ template<class T> inline void f( A<T> ); // #1
+ void f( A<int> ); // #2 // Ok, declares an ordinary function
+
+ void f<char>( A<char> ); // Error 1100
+
]]>
+
+ int f(void);
+ int f(char*);
+ auto n = f; // Error
+
+In terms of deduction, this is equivalent to:
+
+ int f(void);
+ int f(char*);
+ template<class T> void g( const T& );
+ void h( void )
+ {
+ g( f ); // Error
+ }
+
+Here, 'f' refers to multiple overloaded functions, so it is an ambiguous reference and T cannot be deduced. (Code like this could still be well-formed however, e.g. if g is overloaded with a non-template function whose parameter type is 'ptr-to-function returning int taking (char*)'.) +
]]> +
+ float g(void);
+ char* s();
+ auto a = 42; // Ok, auto is 'int'
+ auto b = g(); // Ok, auto is 'float'
+ auto c = 'q',
+ *d = s(); // Ok, auto is 'char' (for both c and d)
+ auto x = 42, y = g(); // Error 1102 here
+
]]>
+
+ enum A : bool; // ok
+ enum B : short; // ok
+ enum C : unsigned long long; // ok
+ enum D : float; // Error 1103
+
]]>
+
+ enum class A { red, green };
+ enum class A x; // Error: don't need 'class'
+ enum A : unsigned { red, green };
+ enum A : unsigned y; // Error: don't need ': unsigned'
+
]]>
+
+ class A
+ {
+ void f(int) &; // ok (so far)
+ void f(int); // 1105
+ void f(double); // 1105
+ void g(int); // ok (fresh function)
+ void g(double); // still ok
+ };
+
]]>
+
+ enum E : unsigned char { e = 256 };
+
+The value 256 cannot be represented by an unsigned char. +
]]> +
+ char *s = u"abc" U"def";
+ char *q = L"ghi" u"jkl";
+
+This message is issued for mixing strings of char16_t, char32_t, and/or wchar_t (as shown). Literal string concatenation of any of these with an ordinary character literal is permitted and will receive Informational 707. +
]]> +
+ void f( int ) = delete;
+ void f( double );
+ void g( double d, int n ) {
+ f( d ); // Ok
+ f( n ); // Error
+ }
+
]]>
+
+ a->b
+
+it is effectively expanded to:
+
+ a.operator->()->b
+
+And this expansion repeats until an operator-> is found that does not yield a class type. But in the process of evaluating this expansion, it might be found that one of the operators returns a class type for which an overloaded operator-> was already expanded; in that case, Error 1110 is triggered. Example:
+
+ struct B;
+ struct A { struct B& operator->(); };
+ struct B { struct A& operator->(); };
+ int f( A & p ) { p->g(); } // Error
+
]]>
+
+ struct A {
+ template <typename U> struct B {};
+
+ // template <> // Would be ill-formed by ISO C++.
+ // struct B<int> {};
+ };
+ template<> struct A::B<int> {}; // Ok.
+
+There is an additional limitation with member class templates of class templates. As with members of a non-template class, one cannot write a specialization at class scope. Example:
+
+ template<typename T> struct G {
+ template <typename U> struct H {};
+ // template <> // Would be ill-formed by ISO C++.
+ // struct H<int> {};
+ };
+
+But the language specification does not even allow this to be expressed in a namespace-scope definition; there is no way to write an explicit specialization that is a member of a class template. Example:
+
+ template<typename T> struct J {
+ template <typename U> struct K {};
+ };
+ // template<typename T>
+ // template <> // Would be ill-formed by ISO C++;
+ // struct J<T>::K<int> {};
+
+This is because the rules for explicit specializations say that 'template<>' is not allowed to appear after a non-empty template-parameter-list within the same declaration. However, one may write an explicit specialization that is a member of an implicitly-instantiated specialization of a class template. Example:
+
+ template<typename T> struct L {
+ template <typename U> struct M {};
+ };
+ template <> template <> struct L<char>::M<int> {}; // Ok
+
+Here, the body of the class L<char> is automatically generated by implicit instantiation (otherwise the reference to 'L<char>::M' would be ill-formed), while the body of L<char>:M<int> is provided in the explicit specialization. + +In March of 2009, the ISO C++ committee reviewed a report submitted against this example:
+
+ struct A {
+ template<class T> struct B;
+ template <class T> struct B<T*> { }; // well-formed
+ template <> struct B<int*> { }; // ill-formed
+ };
+
+While it might seem odd that one is able to write the partial specialization but not the full specialization, the committee (which at the time was in a "feature-freeze" mode and trying to finalize a draft for the next International Standard) decided that this capability would need to be regarded as an "extension", meaning that it could be considered as a new feature in a future standard but not as a bug-fix for C++0x. + +Note that the Microsoft compiler implements this extension. For that reason, the Lint option
+
+ -elib(1111)
+
+appears in recent versions of our configuration files for Microsoft compilers
]]> +
+ auto f() -> int *;
+
+ ... and not:
+
+ auto *f() -> int;
+
+This also applies to a type-id (e.g., in a cast to a pointer-to-function, or as an argument to a template type-parameter)
]]> +Example:
+
+ template<class T> using X = typename T::type;
+ typedef X<int> XI; // error 1113
+
+]]>
+
+ class A {
+ friend struct B; // ok
+ friend struct C {}; // error
+ };
+
]]>
+
+ class X; ... X *p; ... delete p;
+
+That is, a placeholder declaration for a class is given and an object of that type is deleted before any definition is seen. This may or may not be followed by the actual class definition:
+
+ class X { ... };
+
+A delete before the class is defined is dangerous because, among other things, any operator delete that may be defined within the class could be ignored. +
]]> +
+ struct A
+ {
+ char *x;
+ void f()
+ {
+ char y[10];
+ x = y; // warning 1414
+ }
+ };
+
+Here the address of y is being passed to member x but this is dangerous (if not ridiculous) since when the function returns, the storage allocated for y is deallocated and the pointer could very easily harm something. +
]]> +
+ class C
+ {
+ int &n, &m;
+ C( int &k ) : n(m), m(k) { /* ... */ }
+ };
+
+Here m is initialized properly to be identical to k. However, the initialization of n, taking place, as it does, before m is so initialized, is erroneous. It is undefined what location n will reference. +
]]> +
+ class C
+ {
+ int &n, &m;
+ C( int &k ) : n(k) { /* ... */ }
+ };
+
]]>
+
+ class A : B { int a; };
+
+would make B a private base class by default.
+
+ class A : private B { int a; };
+
+is preferred if that's what you want. [11,#1.1] +
]]> +
+ void operator=(X);
+ void operator=(X) const;
+
+Which is to be used for assignment? +
]]> +
+ if( &arg == this )
+ if( &arg != this )
+ if( this == &arg )
+ if( this != &arg )
+
+as the first statement of the function. + +It is important to check for a self assignment so as to know whether the old value should be subject to a delete operation. This is often overlooked by a class designer since it is counter-intuitive to assign to oneself. But through the magic of aliasing (pointers, references, function arguments) it is possible for an unsuspecting programmer to stumble into a disguised self-assignment [12, Item 17]. + +If you are currently using the following test
+
+ if( arg == *this)
+
+we recommend you replace this with the more efficient:
+
+ if( &arg == this || arg == *this)
+
]]>
+
+ class X
+ {
+ private:
+ int a;
+ public:
+ int *f() { return &a; }
+ };
+
+This looks like a breach of the access system [12, Item 30]. You may lower the access rights of the function, raise the accessibility of the member or make the return value a const pointer or reference. In the above example you could change the function to: +
+
+ const int *f() { return &a; }
+
]]>
+
+ class X
+ {
+ int *p;
+ int *f() const { return p; }
+ };
+
+Since f is supposedly const and since p is presumptively pointing to data that is logically part of class X we certainly have the potential for a security breach. Either return a pointer to const or remove the const modifier to the function. [12, Item 29]. + +Note, if a const function returns the address of a data member then a 605 (capability increase) is issued. +
OOP55-CPP. Do not use pointer-to-member operators to access nonexistent members
+ + ]]> +
+ class B { ... };
+ class D : public B
+ {
+ D( const D &arg ) : B( arg ) { ... }
+ ...
+ };
+
]]>
+
+ class X
+ {
+ X( const X & );
+ };
+
+ extern X x1;
+ X x2 = x1;
+ X x1 = x2;
+
+It is theoretically possible, but unlikely, that the constructor X() is interested only in the address of its argument and not its current value. If so, it only means you will be getting a spurious report which you can suppress based on variable name. However, if the const is missing when passing a reference parameter (or a pointer parameter) then we cannot easily assume that values are being used. In this case no report will be issued. The moral is that if you want to get the checking implied by this message you should make your constructor reference arguments const. +
]]> +
+ class B { };
+ class D : public B {};
+ D a[10];
+ B *p = a; // Warning 1547
+ B *q = &a[0]; // OK
+
+In this example p is being assigned the address of the first element of an array. This is fraught with danger since access to any element other than the zeroeth must be considered an error (we presume that B and D actually have or have the potential to have different sizes). [23, Item 3]. + +We do not warn about the assignment to q because it appears that the programmer realizes the situation and wishes to confine q to the base object of the zeroeth element of a only. As a further precaution against inappropriate array access, out of bounds warnings are issued for subsequent references to p[1] and q[1]. +
]]> +
+ Derived *d = new Derived[10];
+ Base *b;
+ b = d; // Warning 1552
+ b = &d[0]; // OK
+
+[23, Item 3] Also, see the article by Mark Nelson (Bug++ of the Month, Windows developer's Journal, May 1997, pp. 43-44). +
]]> +
+ class X
+ {
+ char *p;
+ X( const X & x )
+ { p = x.p; }
+ ...
+ };
+
+Here, member p is expected to be recreated using new or some variant. +
]]> +
+ class X
+ {
+ char *p;
+ X& operator=( const X & x )
+ { p = x.p; }
+ ...
+ };
+
+Here, member p is expected to be recreated using new or some variant. +
]]> +
+ new int(10)
+
+will draw this warning. The expression allocates an area of storage large enough to hold one integer. It then initializes that integer to the value 10. Could this have been a botched attempt to allocate an array of 10 integers? Even if it was a deliberate attempt to allocate and initialize a single integer, a casual inspection of the code could easily lead a reader astray. + +The warning is only given when the type T has no constructor. If T has a constructor then either a syntactic error will result because no constructor matches the argument or a match will be found. In the latter case no warning will or should be issued. +
]]> +
+ class C
+ {
+ virtual inline void f(); // Warning 1558
+ };
+
+Virtual functions by their nature require an address and so inlining such a function seems contradictory. We recommend that the 'inline' function specifier be removed. +
]]> +
+ void f( int &x );
+ const int n = 0;
+ ...
+ f(n);
+
+Here, function f() could assign a value to its argument and thereby modify n which is declared to be const. + +The message can also be issued when a pointer is initialized. Consider the following example.
+
+ void h( const int *&q );
+ int *p;
+ ...
+ h(p);
+
+It might seem that passing a regular (i.e., non-const) pointer to a const int * could cause no harm. That would be correct if it were not for the reference. If function h() were to assign a pointer to const to its parameter q then upon return from the call, p could be used to modify const data. + +There are many subtle cases that can boggle the mind. See the commentary to Message 605. +
]]> +
+ struct B { virtual void f() throw(B); };
+ struct D:B { virtual void f() throw(D); };
+
+Here, although the exception specification is not identical, the exception D is considered a subset of the base class B. + +It would not be reasonable for D::f() to throw an exception outside the range of those thrown by B::f() because in general the compiler will only see calls to B::f() and it should be possible for the compiler to deduce what exceptions could be thrown by examining the static call +
]]> +
+ p ? a : b = 1
+
+If this is what was intended you should parenthesize the third argument as in:
+
+ p ? a : (b = 1)
+
+Not only is the original form difficult to read but C, as opposed to C++, would parse this as:
+
+ (p ? a : b) = 1
+
]]>
+
+ bool a = 34;
+
+Although there is an implicit conversion from integral to bool and assigning an integer varaible to a bool to obtain its Boolean meaning is legitimate, assigning an integer such as this looks suspicious. As the message suggests, the warning is not given if the value assigned is either 0 or 1. An Elective Note would be raised in that instance. +
]]> +
+ class A {
+ int a;
+ public:
+ void f();
+ A() { f(); }
+ };
+
+Here f() is presumably serving as an initializer for the constructor A::A(). To inform PC-lint/FlexeLint of this situation, use the option:
+
+ -sem( A::f, initializer )
+
+This will suppress Warning 1566 for any constructor of class A that calls A::f. +
]]> +
+ a.cpp: b.cpp:
+
+ int g(void); int f(void);
+ int y = g(); int x = f();
+ int f() { return y; }
+
+The initialization of both x and y are dynamic. Although the order of dynamic initialization within a module is pre-ordained the order in which modules are initialized is not. Therefore it is perfectly possible for b.cpp to be initialized before a.cpp. Thus when the call is made upon function f() to initialize x, variable y may not yet have been initialized. +
]]> +
+ int g(void);
+ int f(void);
+ int x = f();
+ int y = g();
+ int f() { return y; }
+
+The initialization of both x and y are dynamic. The order of dynamic initialization within a module is in the order in which the initialization is specified. Thus when the call is made upon function f() to initialize x, variable y will not yet have been initialized. +
]]> +
+ struct A { int &n; A() : n(3) {} };
+
+The constructor A() contains an initializer list within which it initializes n. But n will be bound to a temporary created by the compiler to hold the value 3. The lifetime of this temporary is limited; it "persists until the constructor exits" [10 section class.temporary] +
]]> +
+ class X { int &n; X(int k) :n(k) {} };
+
+In this example member n is being bound to variable k which, although a parameter, is nonetheless placed into auto storage. But the lifetime of k is only the duration of the call to the constructor, whereas the lifetime of n is the lifetime of the class object constructed. +
]]> +
+ void f( int n ) { static int& r = n; ... }
+
+The reference r will be permanently bound to an auto variable n. The lifetime of n will not extend beyond the life of the function. On the second and subsequent calls to function f the static variable r will be bound to a non-existent entity. +
]]> +
+ namespace X
+ {
+ template< class T >
+ void f( int, const T& ); // Generic
+ class A{}; // Warning 1573
+ }
+
+A call to function f that contained an argument of type X::A would, by ADL (Argument Dependent Lookup), need to also consider function X::f even though this function was not in the scope of the call. In the past this has led to strange an unexpected results. + +Some designers adopt the strategy of embedding the class within a sub namespace and employing a using-declaration to make it available to users of the original namespace. For example:
+
+ namespace X
+ {
+ template< class T >
+ void f( int, const T& ); // Generic
+ namespace X1
+ {
+ class A{}; // No Warning
+ }
+ using X1::A;
+ }
+
+Now an argument of type X::A will not automatically trigger a consideration of X::f. +
]]> +
+ int &f( int k )
+ {
+ int &r = k;
+ return r;
+ }
+
]]>
+
+ class A {
+ int *p;
+ public:
+ void release_ptrs();
+ ~A() { release_ptrs(); }
+ };
+
+Here release_ptrs() is presumably serving as a cleanup function for the destructor ~A::A(). To inform PC-lint/FlexeLint of this situation, use the option:
+
+ -sem( A::release_ptrs, cleanup )
+
+A separate message (Warning 1578) will be issued if the cleanup function fails to clear all pointers. See also Warning 1566. +
]]> ++a = b = c ++[11, ?13.4.3] + + ]]> +
Example:
+
+ template<class T, class U> struct A;
+ template<class T, class U> struct A<T*, U> { };
+ template<class T, class U> struct A<T, U*> { };
+ A<int*, char*> x; // Error 1084 followed by Info 1723
+
+]]>
+ +int f( const int & k ) { return k; } ++Declaring a parameter a reference to const offers advantages that a mere reference does not. In particular, you can pass constants, temporaries and const types into such a parameter where otherwise you may not. In addition it can offer better documentation. +Other situations in which a const can be added to a declaration are covered in messages 818, 952, 953 and 954. + + ]]> +
+ if( arg == sizeof(class) ) + if( arg != sizeof(class) ) + if( sizeof(class) == arg ) + if( sizeof(class) != arg ) ++or the equivalent. If any such function is found that is a member of a class that is the base of a derivation, then in addition to Note 1921, we issue Warning 1531. (see Steve Simpson, "More on Memory Management", Dr. Dobb's Journal, August 1994, p. 10). +
+ if( arg ) + if( arg == 0 ) + if( arg != NULL ) ++etc. Classes which have destructors will normally filter out passing the NULL pointer into the operator delete so that this message is only in the Elective Note category. If there is no destructor you obtain a warning. See Warning 1532. + ]]> +
The list of checks made are as follows:
+
+ (Rule 0-1-8) Void return type for function without external side-effects.
+ (Rule 2-13-2) Octal constant or escape sequence used.
+ (Rule 2-13-4) Lower case literal suffix.
+ (Rule 3-1-1) Object/function definitions in headers.
+ (Rule 3-1-2) Function not declared at file scope.
+ (Rule 3-2-3) Object/function previously declared in location.
+ (Rule 3-9-3) Bit representation of a floating point type used.
+ (Rule 4-5-1) Boolean expression used with non-permitted operator.
+ (Rule 4-5-3) Plain char used with prohibited operator.
+ (Rule 5-0-3) Implicit conversion of cvalue.
+ (Rule 5-0-4) Implicit conversion changes signedness.
+ (Rule 5-0-5) Implicit conversion between integer and floating point types.
+ (Rule 5-0-6) Implicit conversion to smaller type.
+ (Rule 5-0-7) Cast of cvalue between integer and floating point types.
+ (Rule 5-0-8) Cast of cvalue to larger type.
+ (Rule 5-0-9) Cast of cvalue changes signedness.
+ (Rule 5-0-10) Recasting required for operators '~' and '<<'.
+ (Rule 5-0-11) Disallowed use of non-character value.
+ (Rule 5-0-12 Disallowed use of non-numeric value.
+ (Rule 5-0-15) Pointer arithmetic other than array indexing used.
+ (rule 5-0-19) More than two pointer indirection levels used.
+ (Rule 5-0-21) Bitwise operator applied to signed underlying type.
+ (Rule 5-2-1) Non-postfix expression used with logical operator.
+ (Rule 5-2-5) Attempt to cast away const/volatile from a pointer or reference.
+ (Rule 5-2-12) Array-pointer decay when passing the array to a function.
+ (Rule 5-3-1) Boolean expresion required for operator.
+ (Rule 5-3-2) Prohibited operator applied to unsigned underlying type: .
+ (Rule 5-3-3) Overloading unary &.
+ (Rule 5-3-4) 'sizeof' used on expressions with side effect.
+ (Rule 5-14-1) Side effects on right hand side of logical operator.
+ (Rule 5-18-1) Comma operator used.
+ (Rule 6-2-3) Null statement not in line by itself.
+ (Rules 6-3-1 and 6-4-1) Left brace expected for if, else, for, do, switch and while.
+ (Rule 6-4-2) No 'else' at end of 'if ... else if' chain.
+ (Rule 6-4-7) Boolean value in switch expression.
+ (Rule 6-6-2) Gotos jumping to an earlier point in the code.
+ (Rule 6-6-3) continue statement should not be used.
+ (Rule 6-6-4) More than one 'break' terminates loop.
+ (Rule 7-3-1) Global declarations other than main(), namespace declarations, extern "C" declarations and arithmetic typedefs.
+ (Rule 7-3-2) Using the identifier main for functions other than the global one.
+ (Rule 7-3-3) Unnamed namespaces in headers.
+ (Rule 7-3-4) No using-directives allowed.
+ (Rule 7-3-6) using-directives or using declarations (except class and/or block scope using declarations) in header files.
+ (Rule 8-0-1) Multiple declarators in a declaration.
+ (Rule 8-4-1) Function has variable number of arguments.
+ (Rule 8-4-2) Function parameter list differs
+ (Rule 8-4-4) Function identifier used without '&' or parenthisized parameter list.
+ (Rule 8-5-3) Should initialize either all enum members or only the first.
+ (Rule 9-5-1) Unions shall not be used.
+ (Rule 11-0-1) Non-private data member within a no-POD structure.
+ (Rule 12-8-2) Public copy constructor in abstract class.
+ (Rule 14-8-1) Explicit specialization of overloaded function templates.
+ (Rule 15-1-2) Explicit throw of the Null macro.
+ (Rule 15-1-3) Empty throw outside of a catch block.
+ (Rule 15-3-7) Catch handler after catch(...) in a try-catch sequence.
+ (Rule 16-0-1) Only preprocessor statements and comments before '#include'.
+ (Rule 16-0-2) '#define/#undef' used within a block.
+ (Rule 16-0-3) Use of '#undef' is discouraged.
+ (Rule 16-0-4) Use of function-like macros is discouraged.
+ (Rule 16-1-1) Non-standard use of 'defined' preprocessor operator.
+ (Rule 16-2-4) Header file name with non-standard character: .
+ (Rule 16-3-1) Multiple use of '#' and/or '##' operators in macro definition.
+ (Rule 17-0-2) Re-use of reserved identifier
+
+You may disable individual rules to your taste by using the Rule number in an esym option; see Message 960.
+ ]]> +The list of checks made are as follows:
+
+ (Rule 2-5-1) Possible digraph used.
+ (Rule 5-0-2) Dependence placed on C's operator precedence.
+ (Rule 5-2-10) Increment or decrement combined with another operator.
+ (Rule 14-8-2) Mixing template and non-template functions in a viable sets.
+ (Rule 15-0-2) Throwing a pointer expression.
+ (Rule 16-2-5) Header file name with non-standard character.
+ (Rule 16-3-2) No use of '#' or '##'.
+
+]]>
+
+ { label: { goto label; } }
+
+is permitted but
+
+ { goto label; { label: } }
+
+is not. To assist the programmer, the message refers to the blocks using an identification code (Example: "1.2.1"). This identification scheme is defined as follows.
+Thus in the following 'code',
+
+ { { } { { label: } { } } }
+
+label: lies in block 1.2.1.
]]> +
+ #include <initializer_list>
+
+ std::initializer_list<int> f() {
+ return { 1, 2, 3 }; // The memory used to store the array
+ // elements will be freed before returning.
+ }
+
+ void g() {
+ auto x = f(); // Attempting to access the elements of x will read invalid memory.
+ }
]]>
+
+ void foo(int *pi) {
+ if (!pi) return; // Okay
+ if (&pi == 0) return; // 2440
+ if (foo != 0) return; // 2440
+ }
+
+The first string parameter is one of 'function', 'array', or 'address +of' and the second string parameter represents the corresponding +function, array, or variable.
]]> +
+ void foo(int *pi) {
+ if (!pi) return; // Okay
+ if (&pi) return; // 2441
+ if (!foo) return; // 2441
+ }
+
+The first string parameter is one of 'function', 'array', or 'address +of' and the second string parameter represents the corresponding +function, array, or variable.
]]> +
+ void foo(int i) {
+ int (*pf)(float) = &foo; // Warning 2455
+ }
]]>
+
+ void f(int a) {
+ int* p = &a;
+ p[0] = 0;
+ p[1] = 0; // Warning 2662
+ p + 0;
+ p + 1; // Warning 2662
+ }
]]>
+
+ template<typename T>
+ void f(T&& t) {
+ g(std::move(t)); // might unexpectedly move from the caller's lvalue
+ }
]]>
+
+ void foo(int &i) {
+ int &ri = i;
+ if (&i == 0) return; // 3408
+ if (&i != 0) return; // 3408
+ }
]]>
+
+ void foo(int &i) {
+ int &ri = i;
+ if (&i) return; // 3409
+ if (&ri) return; // 3409
+ if (!&i) return; // 3409
+ }
]]>
+
+ template <typename T>
+ T foo(T);
+
+ template<> // warning 3420
+ template<>
+ int foo(int);
]]>
+
+ void foo(unsigned u) {
+ switch(u) {
+ case -1: // warning 3423, cannot narrow -1 to unsigned
+ break;
+ ...
+ }
+ }
+
+ template <unsigned char I>
+ struct S { unsigned char value = I; };
+ S<300> s; // warning 3423, cannot narrow 300 to unsigned char
]]>
+
+ struct X { ... };
+
+ void foo() {
+ &X(); // warning 3430
+ }
]]>
+
+ template <typename... T>
+ void foo() {
+ bar([] {
+ void g(T t...); // warning 3703, probably meant g(T... t);
+ }...);
+ }
]]>
+
+ struct X { };
+ struct Y {
+ Y(const X&);
+ };
+
+ void foo() {
+ Y y(X()); // warning 3705
+ }
+
+Here y is interpreted as a function that returns an object of type Y and +takes a single parameter that is a pointer to a function taking no +arguments and returning type X. In particular, it is not interpreted as +a declaration of an object of type Y initialized with a temporary of +type X as was almost certainly intended.
+ +There are several ways to force interpretation of a variable +declaration. In and later the simplest way is to employ uniform +initialization syntax, for example any of the following would work:
+
+ Y y1(X{}); // OK, variable declaration
+ Y y2{X()}; // OK, variable declaration
+ Y y3{X{}}; // OK, variable declaration
+
+Prior to , an extra pair of parenthesis can be used to force the desired +interpretation, e.g.:
+
+ Y y4((X())); // OK, variable declaration
+
+The same issue can appear with casts, for example:
+
+ void foo(double d) {
+ int i( int(d) ); // warning 3705
+ }
+
+In this case, i is not a variable initialized with the truncated value +of d but rather a function returning int and taking int. In addition to +the methods mentioned above to force a variable declaration, the +functional cast can be converted to a C-style cast or a named cast, +e.g.:
+
+ int i1( (int) d ); // OK, variable declaration
+ int i2( static_cast<int>(d) ); // OK, variable declaration
]]>
+
+ if (x)
+
+will elicit this message while:
+
+ if (x != 0)
+
+will not. ";Effectively boolean"; value are produced by the operators ==, +!=, <=, >=, <, >, !, ||, and &&.
]]> +When certain combinations of compiler extensions are mixed in a manner that does not conform +to the language standard, situations may arise where it is not possible to systematically construct a mangled +name to allow an entity to be cross-referenced between translation units. This message is parameterized by +the category of grammatical entity for which mangling failed.
]]> +
+ #define SUM(x, y) ((x) + (y));
+ void foo(int a, int b) {
+ int result = SUM(a, b) + 1;
+ }
+
+result will be the sum of a and b without the + 1. +
+ //lint -deprecate(ppw, pragma)
+ #if 0
+ #pragma BLAH
+ #endif
+
+will cause this message to be issued for the #pragma directive.
]]> +FIO13-C. Never push back anything other than one read character
]]> +FIO11-C. Take care when specifying the mode parameter of fopen()
]]> +
+"r" "w" "wx" "a"
+"rb" "wb" "wbx" "ab"
+"r+" "w+" "w+x" "a+"
+"r+b" "w+b" "w+bx" "a+b"
+"rb+" "wb+" "wb+x" "ab+"
+
+The second string parameter provides an explanation of why the mode argument is invalid. +
FIO11-C. Take care when specifying the mode parameter of fopen()
]]> +STR38-C. Do not confuse narrow and wide character strings and functions
]]> +STR38-C. Do not confuse narrow and wide character strings and functions
]]> +FLP37-C. Do not use object representations to compare floating-point values
]]> +FLP37-C. Do not use object representations to compare floating-point values
]]> +
+ 1 //lint -sem(save, no_ptr_to_auto(1))
+ 2 void save(int* p);
+ 3 void g(int* x) {
+ 4 save(x);
+ 5 }
+ 6 void f(void) {
+ 7 int a = 5;
+ 8 g(&a);
+ 9 }
+
+will report:
+4 warning 2601: passing address of auto variable ’a’ to parameter 1 of + function ’save’ + save(x); + ^
+8 supplemental 894: during specific walk g(&(5)) + g(&a); + ^ +
POS34-C. Do not call putenv() with a pointer to an automatic variable as the argument
]]> +
+ #define DEBUG_VAL(x)
+
+ int process(int i) {
+ DEBUG_VAL(++i); // 2666 - increment doesn’t occur
+ /* ... */
+ return i;
+ }
+
+Since the parameter isn’t expanded, ++i is not evaluated and the increment does not occur which may +be unexpected. If the intention is that the side-effect occurs regardless of how the macro is defined, the +expression provoking the side effect should be placed outside the macro invocation. For the purpose of this +message, any expression appearing to contain a function call is considered to have side-effects.
+Detail is one of “parameter is not referenced in the expansion” or “parameter is only used with +#/## operators”. The message can be suppressed based on the value of the detail parameter by using +-estring. +
SIG30-C. Call only asynchronous-safe functions within signal handlers
]]> +SIG35-C. Do not return from a computational exception signal handler
]]> +SIG30-C. Call only asynchronous-safe functions within signal handlers
+]]> +SIG34-C. Do not call signal() from within interruptible signal handlers
+]]> +SIG34-C. Do not call signal() from within interruptible signal handlers
+]]> +SIG35-C. Do not return from a computational exception signal handler
+]]> +
+ struct S {
+ int a;
+ int b[0]; // warning 9040
+ };
+
+ union U {
+ int a;
+ short b[1]; // warning 9040
+ char c[1]; // warning 9040
+ double d;
+ };
+
DCL38-C. Use the correct syntax when declaring a flexible array member
+]]> +
+ auto j1{1}; // direct list initialization
+ // j1 is std::initializer_list<int> in C++11 and int in C++17
+ auto j2 = {1}; // copy list initialization
+ // j2 is always std::initializer_list<int>
+ auto j3 = 1; // copy initialization - NOT list initialization
+ // j3 is always int
+
+This message will be issued for the initialization of j1 and j2. Avoiding list initialization for auto variables +can prevent unintended results. The string parameter is either ’direct’ or ’copy’ indicating the type of list +initialization employed (copy list initialization uses an equal sign, direct list initialization does not).
+]]> +
+ void init_buffer(void *buffer) {
+ memset(buffer, 0,
+ #ifdef LARGE_BUFFER
+ 1024
+ #else
+ 128
+ #endif
+ );
+ }
+
+The problem is that if memset is implemented as a macro, the presence of the embedded preprocessor +directives would invoke undefined behavior. PC-lint Plus issues message 436 when a preprocessor directive +appears inside a macro invocation but message 9501 can be used to warn about directives in function calls +that may be implemented as macros in other configurations or when compiled on other platforms. +One alternative is to move the directives outside the call, e.g.:
+
+ void init_buffer(void *buffer) {
+ const unsigned buf_size =
+ #ifdef LARGE_BUFFER
+ 1024
+ #else
+ 128
+ #endif
+ ;
+ memset(buffer, 0, buf_size);
+ }
+
+This message isn’t issued if the function name is surrounded by parenthesis which suppresses the invocation +of a potential macro by the same name. This message is parameterized on the function being called and can +be enabled for specific functions using either +esym or +ecall. +
PRE32-C. Do not use preprocessor directives in invocations of function-like macros
]]> +
+ #define M(x) do { ... } while (0)
+
+where 0 may be replaced by any integer literal with a zero value (0u, 0x0, etc.), the false keyword or a +keyword that has been assigned the same meaning as false with the -rw_asgn option, or an identifier whose +name is false, ignoring case.
+A macro that expands to multiple statements may result in unintentional interpretation during expansion. +For example:
+
+ #define ADJUST(a, b) a = (b); a++; b = 0
+
+would not work as intended if used as:
+
+ void foo(int a, int b) {
+ if (a >= b)
+ ADJUST(a, b);
+ }
+
+which would expand to:
+
+ void foo(int a, int b) {
+ if (a >= b)
+ a = (b); a++; b = 0;
+ }
+
+where the last two statements would be unconditionally executed as they are not part of the if statement. +Simply wrapping the macro definition in braces is not always sufficient:
+
+ #define ADJUST(a, b) { a = (b); a++; b = 0; }
+
+as this will prevent the macro from being usable in certain contexts, e.g.:
+
+ void foo(int a, int b) {
+ if (a >= b)
+ ADJUST(a, b);
+ else
+ ADJUST(b, a);
+ }
+
+will result in a compile error as the else is not attached to the if statement because of the semi-colon. +Wrapping the replacement text in a do/while (0) loop addresses all of the related issues:
+
+ #define ADJUST(a, b) do { a = (b); a++; b = 0; } while (0)
+
+