2009-01-26 20:14:46 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2009-05-30 07:48:12 +02:00
* Copyright ( C ) 2007 - 2009 Daniel Marjamäki and Cppcheck team .
2009-01-26 20:14:46 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2009-09-27 17:08:31 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2009-01-26 20:14:46 +01:00
*/
//---------------------------------------------------------------------------
# include "checkother.h"
2009-05-02 10:45:15 +02:00
# include "mathlib.h"
2009-03-20 18:16:21 +01:00
# include "tokenize.h"
2009-02-04 19:49:19 +01:00
# include <algorithm>
2009-01-26 20:14:46 +01:00
# include <list>
# include <map>
# include <sstream>
# include <cstring>
# include <cctype>
//---------------------------------------------------------------------------
2009-03-20 18:16:21 +01:00
// Register this check class (by creating a static instance of it)
namespace
2009-01-26 20:14:46 +01:00
{
2009-03-20 18:16:21 +01:00
CheckOther instance ;
2009-01-26 20:14:46 +01:00
}
2009-03-20 18:16:21 +01:00
//---------------------------------------------------------------------------
2009-01-26 20:14:46 +01:00
2009-07-05 22:16:43 +02:00
void CheckOther : : warningOldStylePointerCast ( )
2009-01-26 20:14:46 +01:00
{
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
// Old style pointer casting..
2009-09-24 22:46:08 +02:00
if ( ! Token : : Match ( tok , " ( const| %type% * ) %var% " ) & &
! Token : : Match ( tok , " ( const| %type% * ) (| new " ) )
2009-01-26 20:14:46 +01:00
continue ;
2009-07-20 21:52:27 +02:00
int addToIndex = 0 ;
2009-07-27 11:24:24 +02:00
if ( tok - > tokAt ( 1 ) - > str ( ) = = " const " )
2009-07-20 21:52:27 +02:00
addToIndex = 1 ;
2009-07-27 11:24:24 +02:00
if ( tok - > tokAt ( 4 + addToIndex ) - > str ( ) = = " const " )
2009-06-18 22:26:21 +02:00
continue ;
2009-01-26 20:14:46 +01:00
// Is "type" a class?
2009-07-20 21:52:27 +02:00
const std : : string pattern ( " class " + tok - > tokAt ( 1 + addToIndex ) - > str ( ) ) ;
2009-01-26 20:14:46 +01:00
if ( ! Token : : findmatch ( _tokenizer - > tokens ( ) , pattern . c_str ( ) ) )
continue ;
2009-03-21 17:58:13 +01:00
cstyleCastError ( tok ) ;
2009-01-26 20:14:46 +01:00
}
}
//---------------------------------------------------------------------------
// Redundant code..
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : warningRedundantCode ( )
2009-01-26 20:14:46 +01:00
{
// if (p) delete p
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
2009-07-18 16:42:08 +02:00
if ( ! Token : : simpleMatch ( tok , " if ( " ) )
2009-01-26 20:14:46 +01:00
continue ;
2009-09-28 23:18:40 +02:00
std : : string varname ;
2009-07-18 16:42:08 +02:00
const Token * tok2 = tok - > tokAt ( 2 ) ;
/*
* Possible if - constructions :
*
* if ( var )
* if ( this - > var )
* if ( Foo : : var )
*
* */
2009-09-28 23:18:40 +02:00
while ( Token : : Match ( tok2 , " %var% .|:: " ) )
2009-07-18 20:35:22 +02:00
{
2009-09-28 23:18:40 +02:00
varname . append ( tok2 - > str ( ) ) ;
varname . append ( tok2 - > next ( ) - > str ( ) ) ;
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > tokAt ( 2 ) ;
2009-01-26 20:14:46 +01:00
}
2009-07-18 16:42:08 +02:00
2009-09-28 23:18:40 +02:00
if ( ! Token : : Match ( tok2 , " %var% ) { " ) )
2009-01-26 20:14:46 +01:00
continue ;
2009-09-28 23:18:40 +02:00
varname . append ( tok2 - > str ( ) ) ;
tok2 = tok2 - > tokAt ( 3 ) ;
2009-07-18 16:42:08 +02:00
/*
* Possible constructions :
*
* - delete % var %
* - delete [ ] % var %
* - free ( % var )
* - kfree ( % var % )
*
* Where % var % may be :
* - just variable name ( var )
* - class member ( this - > var )
* - static member ( Class : : var )
*
* */
2009-09-28 23:18:40 +02:00
bool funcHasBracket = false ;
2009-07-18 20:35:22 +02:00
if ( Token : : Match ( tok2 , " free|kfree ( " ) )
{
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > tokAt ( 2 ) ;
funcHasBracket = true ;
2009-07-18 20:35:22 +02:00
}
else if ( tok2 - > str ( ) = = " delete " )
{
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > next ( ) ;
2009-07-18 20:35:22 +02:00
if ( Token : : simpleMatch ( tok2 , " [ ] " ) )
{
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > tokAt ( 2 ) ;
2009-01-26 20:14:46 +01:00
}
}
2009-07-18 16:42:08 +02:00
2009-09-28 23:18:40 +02:00
std : : string varname2 ;
while ( Token : : Match ( tok2 , " %var% ::|. " ) )
2009-07-18 20:35:22 +02:00
{
2009-09-28 23:18:40 +02:00
varname2 . append ( tok2 - > str ( ) ) ;
varname2 . append ( tok2 - > next ( ) - > str ( ) ) ;
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > tokAt ( 2 ) ;
}
2009-09-28 23:18:40 +02:00
varname2 . append ( tok2 - > str ( ) ) ;
if ( Token : : Match ( tok2 , " %var% " ) & & varname = = varname2 )
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > next ( ) ;
2009-09-28 23:18:40 +02:00
else
continue ;
2009-07-18 16:42:08 +02:00
2009-07-18 20:35:22 +02:00
if ( funcHasBracket )
{
if ( tok2 - > str ( ) ! = " ) " )
{
2009-09-28 23:18:40 +02:00
continue ;
2009-07-18 20:35:22 +02:00
}
else
{
2009-07-18 16:42:08 +02:00
tok2 = tok2 - > next ( ) ;
2009-01-26 20:14:46 +01:00
}
2009-07-18 16:42:08 +02:00
}
2009-09-28 23:18:40 +02:00
if ( ! Token : : Match ( tok2 , " ; } !!else " ) )
2009-07-18 20:35:22 +02:00
{
2009-09-28 23:18:40 +02:00
continue ;
2009-01-26 20:14:46 +01:00
}
2009-09-28 23:18:40 +02:00
redundantIfDelete0Error ( tok ) ;
2009-01-26 20:14:46 +01:00
}
// Redundant condition
// if (haystack.find(needle) != haystack.end())
// haystack.remove(needle);
redundantCondition2 ( ) ;
}
//---------------------------------------------------------------------------
void CheckOther : : redundantCondition2 ( )
{
const char pattern [ ] = " if ( %var% . find ( %any% ) != %var% . end ( ) ) "
" {|{| "
" %var% . remove ( %any% ) ; "
" }|}| " ;
const Token * tok = Token : : findmatch ( _tokenizer - > tokens ( ) , pattern ) ;
while ( tok )
{
2009-07-27 11:24:24 +02:00
bool b ( tok - > tokAt ( 15 ) - > str ( ) = = " { " );
2009-01-26 20:14:46 +01:00
// Get tokens for the fields %var% and %any%
const Token * var1 = tok - > tokAt ( 2 ) ;
const Token * any1 = tok - > tokAt ( 6 ) ;
const Token * var2 = tok - > tokAt ( 9 ) ;
const Token * var3 = tok - > tokAt ( b ? 16 : 15 ) ;
const Token * any2 = tok - > tokAt ( b ? 20 : 19 ) ;
// Check if all the "%var%" fields are the same and if all the "%any%" are the same..
if ( var1 - > str ( ) = = var2 - > str ( ) & &
var2 - > str ( ) = = var3 - > str ( ) & &
any1 - > str ( ) = = any2 - > str ( ) )
{
2009-03-21 17:58:13 +01:00
redundantIfRemoveError ( tok ) ;
2009-01-26 20:14:46 +01:00
}
tok = Token : : findmatch ( tok - > next ( ) , pattern ) ;
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// strtol(str, 0, radix) <- radix must be 0 or 2-36
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : invalidFunctionUsage ( )
2009-01-26 20:14:46 +01:00
{
// strtol and strtoul..
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( ( tok - > str ( ) ! = " strtol " ) & & ( tok - > str ( ) ! = " strtoul " ) )
continue ;
// Locate the third parameter of the function call..
int parlevel = 0 ;
int param = 1 ;
for ( const Token * tok2 = tok - > next ( ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
2009-07-27 11:24:24 +02:00
if ( tok2 - > str ( ) = = " ( " )
2009-01-26 20:14:46 +01:00
+ + parlevel ;
2009-07-27 11:24:24 +02:00
else if ( tok2 - > str ( ) = = " ) " )
2009-01-26 20:14:46 +01:00
- - parlevel ;
2009-07-27 11:24:24 +02:00
else if ( parlevel = = 1 & & tok2 - > str ( ) = = " , " )
2009-01-26 20:14:46 +01:00
{
+ + param ;
if ( param = = 3 )
{
if ( Token : : Match ( tok2 , " , %num% ) " ) )
{
2009-05-02 10:45:15 +02:00
int radix = MathLib : : toLongNumber ( tok2 - > next ( ) - > str ( ) ) ;
2009-01-26 20:14:46 +01:00
if ( ! ( radix = = 0 | | ( radix > = 2 & & radix < = 36 ) ) )
{
2009-03-21 17:58:13 +01:00
dangerousUsageStrtolError ( tok2 ) ;
2009-01-26 20:14:46 +01:00
}
}
break ;
}
}
}
}
// sprintf|snprintf overlapping data
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
// Get variable id of target buffer..
unsigned int varid = 0 ;
if ( Token : : Match ( tok , " sprintf|snprintf ( %var% , " ) )
varid = tok - > tokAt ( 2 ) - > varId ( ) ;
else if ( Token : : Match ( tok , " sprintf|snprintf ( %var% . %var% , " ) )
varid = tok - > tokAt ( 4 ) - > varId ( ) ;
if ( varid = = 0 )
continue ;
// goto ","
const Token * tok2 = tok - > tokAt ( 3 ) ;
while ( tok2 & & tok2 - > str ( ) ! = " , " )
tok2 = tok2 - > next ( ) ;
// is any source buffer overlapping the target buffer?
int parlevel = 0 ;
while ( ( tok2 = tok2 - > next ( ) ) ! = NULL )
{
if ( tok2 - > str ( ) = = " ( " )
+ + parlevel ;
else if ( tok2 - > str ( ) = = " ) " )
{
- - parlevel ;
if ( parlevel < 0 )
break ;
}
2009-01-27 08:21:52 +01:00
else if ( parlevel = = 0 & & Token : : Match ( tok2 , " , %varid% [,)] " , varid ) )
2009-01-26 20:14:46 +01:00
{
2009-03-21 17:58:13 +01:00
sprintfOverlappingDataError ( tok2 - > next ( ) , tok2 - > next ( ) - > str ( ) ) ;
2009-01-26 20:14:46 +01:00
break ;
}
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Check for unsigned divisions
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : checkUnsignedDivision ( )
2009-01-26 20:14:46 +01:00
{
2009-09-15 20:46:47 +02:00
if ( ! _settings - > _showAll | | ! _settings - > _checkCodingStyle )
return ;
2009-01-26 20:14:46 +01:00
// Check for "ivar / uvar" and "uvar / ivar"
2009-10-11 16:52:35 +02:00
std : : map < unsigned int , char > varsign ;
2009-01-26 20:14:46 +01:00
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( Token : : Match ( tok , " [{};(,] %type% %var% [;=,)] " ) )
{
const char * type = tok - > strAt ( 1 ) ;
if ( strcmp ( type , " char " ) = = 0 | | strcmp ( type , " short " ) = = 0 | | strcmp ( type , " int " ) = = 0 )
2009-10-11 16:52:35 +02:00
varsign [ tok - > tokAt ( 2 ) - > varId ( ) ] = ' s ' ;
2009-01-26 20:14:46 +01:00
}
else if ( Token : : Match ( tok , " [{};(,] unsigned %type% %var% [;=,)] " ) )
2009-10-11 16:52:35 +02:00
varsign [ tok - > tokAt ( 3 ) - > varId ( ) ] = ' u ' ;
2009-01-26 20:14:46 +01:00
else if ( ! Token : : Match ( tok , " [).] " ) & & Token : : Match ( tok - > next ( ) , " %var% / %var% " ) )
{
2009-03-20 18:16:21 +01:00
if ( ErrorLogger : : udivWarning ( * _settings ) )
2009-01-26 20:14:46 +01:00
{
2009-10-11 16:52:35 +02:00
char sign1 = varsign [ tok - > tokAt ( 1 ) - > varId ( ) ] ;
char sign2 = varsign [ tok - > tokAt ( 3 ) - > varId ( ) ] ;
2009-01-26 20:14:46 +01:00
if ( sign1 & & sign2 & & sign1 ! = sign2 )
{
// One of the operands are signed, the other is unsigned..
2009-03-21 17:58:13 +01:00
udivWarning ( tok - > next ( ) ) ;
2009-01-26 20:14:46 +01:00
}
}
}
2009-03-17 20:50:06 +01:00
else if ( ! Token : : Match ( tok , " [).] " ) & & Token : : Match ( tok - > next ( ) , " %var% / %num% " ) )
2009-01-26 20:14:46 +01:00
{
2009-03-17 20:50:06 +01:00
if ( tok - > strAt ( 3 ) [ 0 ] = = ' - ' & & ErrorLogger : : udivError ( ) )
2009-01-26 20:14:46 +01:00
{
2009-10-11 16:52:35 +02:00
char sign1 = varsign [ tok - > tokAt ( 1 ) - > varId ( ) ] ;
2009-01-26 20:14:46 +01:00
if ( sign1 = = ' u ' )
{
2009-03-21 17:58:13 +01:00
udivError ( tok - > next ( ) ) ;
2009-01-26 20:14:46 +01:00
}
}
}
2009-03-17 20:50:06 +01:00
else if ( Token : : Match ( tok , " [([=*/+-,] %num% / %var% " ) )
2009-01-26 20:14:46 +01:00
{
2009-03-17 20:50:06 +01:00
if ( tok - > strAt ( 1 ) [ 0 ] = = ' - ' & & ErrorLogger : : udivError ( ) )
2009-01-26 20:14:46 +01:00
{
2009-10-11 16:52:35 +02:00
char sign2 = varsign [ tok - > tokAt ( 3 ) - > varId ( ) ] ;
2009-01-26 20:14:46 +01:00
if ( sign2 = = ' u ' )
{
2009-03-21 17:58:13 +01:00
udivError ( tok - > next ( ) ) ;
2009-01-26 20:14:46 +01:00
}
}
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Check scope of variables..
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : checkVariableScope ( )
2009-01-26 20:14:46 +01:00
{
// Walk through all tokens..
bool func = false ;
int indentlevel = 0 ;
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
// Skip class and struct declarations..
if ( ( tok - > str ( ) = = " class " ) | | ( tok - > str ( ) = = " struct " ) )
{
for ( const Token * tok2 = tok ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( tok2 - > str ( ) = = " { " )
{
2009-10-06 17:45:28 +02:00
tok = tok2 - > link ( ) ;
2009-01-26 20:14:46 +01:00
break ;
}
if ( Token : : Match ( tok2 , " [,);] " ) )
{
break ;
}
}
if ( ! tok )
break ;
}
2009-10-06 17:45:28 +02:00
else if ( tok - > str ( ) = = " { " )
2009-01-26 20:14:46 +01:00
{
+ + indentlevel ;
}
2009-10-06 17:45:28 +02:00
else if ( tok - > str ( ) = = " } " )
2009-01-26 20:14:46 +01:00
{
- - indentlevel ;
if ( indentlevel = = 0 )
func = false ;
}
2009-05-21 17:55:52 +02:00
if ( indentlevel = = 0 & & Token : : simpleMatch ( tok , " ) { " ) )
2009-01-26 20:14:46 +01:00
{
func = true ;
}
if ( indentlevel > 0 & & func & & Token : : Match ( tok , " [{};] " ) )
{
// First token of statement..
const Token * tok1 = tok - > next ( ) ;
if ( ! tok1 )
continue ;
if ( ( tok1 - > str ( ) = = " return " ) | |
2009-03-24 20:59:56 +01:00
( tok1 - > str ( ) = = " throw " ) | |
2009-01-26 20:14:46 +01:00
( tok1 - > str ( ) = = " delete " ) | |
( tok1 - > str ( ) = = " goto " ) | |
( tok1 - > str ( ) = = " else " ) )
continue ;
// Variable declaration?
2009-09-17 21:05:12 +02:00
if ( Token : : Match ( tok1 , " %type% %var% ; %var% = %num% ; " ) )
2009-08-16 21:12:57 +02:00
{
// Tokenizer modify "int i = 0;" to "int i; i = 0;",
// so to handle this situation we just skip
// initialization (see ticket #272).
const unsigned int firstVarId = tok1 - > next ( ) - > varId ( ) ;
const unsigned int secondVarId = tok1 - > tokAt ( 3 ) - > varId ( ) ;
if ( firstVarId > 0 & & firstVarId = = secondVarId )
{
lookupVar ( tok1 - > tokAt ( 6 ) , tok1 - > strAt ( 1 ) ) ;
}
}
else if ( Token : : Match ( tok1 , " %type% %var% [;=] " ) )
2009-01-26 20:14:46 +01:00
{
2009-07-05 22:16:43 +02:00
lookupVar ( tok1 , tok1 - > strAt ( 1 ) ) ;
2009-01-26 20:14:46 +01:00
}
}
}
}
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : lookupVar ( const Token * tok1 , const char varname [ ] )
2009-01-26 20:14:46 +01:00
{
const Token * tok = tok1 ;
// Skip the variable declaration..
2009-07-27 11:24:24 +02:00
while ( tok & & tok - > str ( ) ! = " ; " )
2009-01-26 20:14:46 +01:00
tok = tok - > next ( ) ;
// Check if the variable is used in this indentlevel..
bool used = false , used1 = false ;
int indentlevel = 0 ;
int parlevel = 0 ;
bool for_or_while = false ;
2009-06-12 16:17:51 +02:00
while ( tok )
2009-01-26 20:14:46 +01:00
{
if ( tok - > str ( ) = = " { " )
{
+ + indentlevel ;
}
else if ( tok - > str ( ) = = " } " )
{
2009-06-12 16:17:51 +02:00
if ( indentlevel = = 0 )
break ;
2009-01-26 20:14:46 +01:00
- - indentlevel ;
if ( indentlevel = = 0 )
{
if ( for_or_while & & used )
return ;
2009-03-24 20:28:44 +01:00
used1 | = used ;
2009-01-26 20:14:46 +01:00
used = false ;
}
}
else if ( tok - > str ( ) = = " ( " )
{
+ + parlevel ;
}
else if ( tok - > str ( ) = = " ) " )
{
- - parlevel ;
}
2009-05-27 19:38:26 +02:00
// Bail out if references are used
else if ( Token : : simpleMatch ( tok , ( std : : string ( " & " ) + varname ) . c_str ( ) ) )
{
return ;
}
2009-01-26 20:14:46 +01:00
else if ( tok - > str ( ) = = varname )
{
if ( indentlevel = = 0 | | used1 )
return ;
used = true ;
}
else if ( indentlevel = = 0 )
{
2009-09-29 23:56:43 +02:00
// %unknown% ( %any% ) {
// If %unknown% is anything except if, we assume
// that it is a for or while loop or a macro hiding either one
if ( Token : : simpleMatch ( tok - > next ( ) , " ( " ) & &
Token : : simpleMatch ( tok - > next ( ) - > link ( ) - > next ( ) , " { " ) )
{
if ( tok - > str ( ) ! = " if " )
for_or_while = true ;
}
if ( Token : : simpleMatch ( tok , " do { " ) )
2009-01-26 20:14:46 +01:00
for_or_while = true ;
2009-09-29 23:56:43 +02:00
2009-01-26 20:14:46 +01:00
if ( parlevel = = 0 & & ( tok - > str ( ) = = " ; " ) )
for_or_while = false ;
}
tok = tok - > next ( ) ;
}
2009-06-12 16:17:51 +02:00
// Warning if this variable:
// * not used in this indentlevel
// * used in lower indentlevel
if ( ! used & & used1 )
variableScopeError ( tok1 , varname ) ;
2009-01-26 20:14:46 +01:00
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Check for constant function parameters
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : checkConstantFunctionParameter ( )
2009-01-26 20:14:46 +01:00
{
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( Token : : Match ( tok , " [,(] const std :: %type% %var% [,)] " ) )
{
2009-03-21 17:58:13 +01:00
passedByValueError ( tok , tok - > strAt ( 5 ) ) ;
2009-01-26 20:14:46 +01:00
}
2009-10-05 10:59:28 +02:00
else if ( Token : : Match ( tok , " [,(] const std :: %type% < %type% > %var% [,)] " ) )
{
passedByValueError ( tok , tok - > strAt ( 8 ) ) ;
}
else if ( Token : : Match ( tok , " [,(] const std :: %type% < std :: %type% > %var% [,)] " ) )
{
passedByValueError ( tok , tok - > strAt ( 10 ) ) ;
}
2009-10-06 23:04:54 +02:00
else if ( Token : : Match ( tok , " [,(] const std :: %type% < std :: %type% , std :: %type% > %var% [,)] " ) )
{
passedByValueError ( tok , tok - > strAt ( 14 ) ) ;
}
else if ( Token : : Match ( tok , " [,(] const std :: %type% < %type% , std :: %type% > %var% [,)] " ) )
{
passedByValueError ( tok , tok - > strAt ( 12 ) ) ;
}
else if ( Token : : Match ( tok , " [,(] const std :: %type% < std :: %type% , %type% > %var% [,)] " ) )
{
passedByValueError ( tok , tok - > strAt ( 12 ) ) ;
}
else if ( Token : : Match ( tok , " [,(] const std :: %type% < %type% , %type% > %var% [,)] " ) )
{
passedByValueError ( tok , tok - > strAt ( 10 ) ) ;
}
2009-01-26 20:14:46 +01:00
else if ( Token : : Match ( tok , " [,(] const %type% %var% [,)] " ) )
{
// Check if type is a struct or class.
const std : : string pattern ( std : : string ( " class|struct " ) + tok - > strAt ( 2 ) ) ;
if ( Token : : findmatch ( _tokenizer - > tokens ( ) , pattern . c_str ( ) ) )
{
2009-03-21 17:58:13 +01:00
passedByValueError ( tok , tok - > strAt ( 3 ) ) ;
2009-01-26 20:14:46 +01:00
}
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Check that all struct members are used
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : checkStructMemberUsage ( )
2009-01-26 20:14:46 +01:00
{
const char * structname = 0 ;
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( tok - > fileIndex ( ) ! = 0 )
continue ;
if ( Token : : Match ( tok , " struct|union %type% { " ) )
{
structname = tok - > strAt ( 1 ) ;
// Bail out if struct/union contain any functions
for ( const Token * tok2 = tok - > tokAt ( 2 ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( tok2 - > str ( ) = = " ( " )
{
structname = 0 ;
break ;
}
if ( tok2 - > str ( ) = = " } " )
break ;
}
2009-10-17 17:36:55 +02:00
// Bail out if some data is casted to struct..
2009-10-17 19:31:14 +02:00
const std : : string s ( " ( struct| " + tok - > next ( ) - > str ( ) + " * ) & %var% [ " ) ;
2009-10-17 17:36:55 +02:00
if ( Token : : findmatch ( tok , s . c_str ( ) ) )
structname = 0 ;
2009-01-26 20:14:46 +01:00
}
if ( tok - > str ( ) = = " } " )
structname = 0 ;
if ( structname & & Token : : Match ( tok , " [{;] " ) )
{
const char * varname = 0 ;
if ( Token : : Match ( tok - > next ( ) , " %type% %var% [;[] " ) )
varname = tok - > strAt ( 2 ) ;
else if ( Token : : Match ( tok - > next ( ) , " %type% %type% %var% [ ; [ ] " ))
varname = tok - > strAt ( 3 ) ;
else if ( Token : : Match ( tok - > next ( ) , " %type% * %var% [ ; [ ] " ))
varname = tok - > strAt ( 3 ) ;
else if ( Token : : Match ( tok - > next ( ) , " %type% %type% * %var% [ ; [ ] " ))
varname = tok - > strAt ( 4 ) ;
else
continue ;
const std : : string usagePattern ( " . " + std : : string ( varname ) ) ;
bool used = false ;
for ( const Token * tok2 = _tokenizer - > tokens ( ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( Token : : simpleMatch ( tok2 , usagePattern . c_str ( ) ) )
{
used = true ;
break ;
}
}
if ( ! used )
{
2009-03-21 17:58:13 +01:00
unusedStructMemberError ( tok - > next ( ) , structname , varname ) ;
2009-01-26 20:14:46 +01:00
}
}
}
}
//---------------------------------------------------------------------------
// Check usage of char variables..
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : checkCharVariable ( )
2009-01-26 20:14:46 +01:00
{
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
// Declaring the variable..
2009-02-04 18:12:53 +01:00
if ( Token : : Match ( tok , " [{};(,] signed| char %var% [;=,)] " ) )
2009-01-26 20:14:46 +01:00
{
// Set tok to point to the variable name
tok = tok - > tokAt ( 2 ) ;
2009-02-04 18:12:53 +01:00
if ( tok - > str ( ) = = " char " )
tok = tok - > next ( ) ;
2009-01-26 20:14:46 +01:00
// Check usage of char variable..
int indentlevel = 0 ;
for ( const Token * tok2 = tok - > next ( ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( tok2 - > str ( ) = = " { " )
+ + indentlevel ;
else if ( tok2 - > str ( ) = = " } " )
{
- - indentlevel ;
if ( indentlevel < = 0 )
break ;
}
2009-03-23 19:04:51 +01:00
else if ( tok2 - > str ( ) = = " return " )
continue ;
2009-01-26 20:14:46 +01:00
std : : string temp = " %var% [ " + tok - > str ( ) + " ] " ;
if ( ( tok2 - > str ( ) ! = " . " ) & & Token : : Match ( tok2 - > next ( ) , temp . c_str ( ) ) )
{
2009-03-21 17:58:13 +01:00
charArrayIndexError ( tok2 - > next ( ) ) ;
2009-01-26 20:14:46 +01:00
break ;
}
2009-06-20 19:24:58 +02:00
if ( Token : : Match ( tok2 , " [;{}] %var% = %any% [&|] %any% ; " ) )
2009-01-26 20:14:46 +01:00
{
2009-06-20 19:24:58 +02:00
// is the char variable used in the calculation?
if ( tok2 - > tokAt ( 3 ) - > varId ( ) ! = tok - > varId ( ) & & tok2 - > tokAt ( 5 ) - > varId ( ) ! = tok - > varId ( ) )
continue ;
// it's ok with a bitwise and where the other operand is 0xff or less..
if ( std : : string ( tok2 - > strAt ( 4 ) ) = = " & " )
{
if ( tok2 - > tokAt ( 3 ) - > isNumber ( ) & & MathLib : : isGreater ( " 0x100 " , tok2 - > strAt ( 3 ) ) )
continue ;
if ( tok2 - > tokAt ( 5 ) - > isNumber ( ) & & MathLib : : isGreater ( " 0x100 " , tok2 - > strAt ( 5 ) ) )
continue ;
}
// is the result stored in a short|int|long?
if ( ! Token : : findmatch ( _tokenizer - > tokens ( ) , " short|int|long %varid% " , tok2 - > next ( ) - > varId ( ) ) )
continue ;
// This is an error..
2009-03-21 17:58:13 +01:00
charBitOpError ( tok2 ) ;
2009-01-26 20:14:46 +01:00
break ;
}
}
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Incomplete statement..
//---------------------------------------------------------------------------
2009-07-05 22:16:43 +02:00
void CheckOther : : checkIncompleteStatement ( )
2009-01-26 20:14:46 +01:00
{
int parlevel = 0 ;
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( tok - > str ( ) = = " ( " )
+ + parlevel ;
else if ( tok - > str ( ) = = " ) " )
- - parlevel ;
if ( parlevel ! = 0 )
continue ;
2009-05-21 17:55:52 +02:00
if ( Token : : simpleMatch ( tok , " = { " ) )
2009-02-11 16:17:13 +01:00
{
2009-02-12 13:59:43 +01:00
/* We are in an assignment, so it's not a statement.
* Skip until " ; " */
2009-07-27 11:24:24 +02:00
while ( tok - > str ( ) ! = " ; " )
2009-02-12 13:59:43 +01:00
{
int level = 0 ;
do
{
if ( tok - > str ( ) = = " ( " | | tok - > str ( ) = = " { " )
+ + level ;
else if ( tok - > str ( ) = = " ) " | | tok - > str ( ) = = " } " )
- - level ;
tok = tok - > next ( ) ;
if ( tok = = NULL )
return ;
}
while ( level > 0 ) ;
}
2009-02-11 16:17:13 +01:00
continue ;
}
2009-02-05 19:57:53 +01:00
if ( Token : : Match ( tok , " [;{}] %str% " ) & & ! Token : : Match ( tok - > tokAt ( 2 ) , " [,}] " ) )
2009-01-26 20:14:46 +01:00
{
2009-03-21 17:58:13 +01:00
constStatementError ( tok - > next ( ) , " string " ) ;
2009-01-26 20:14:46 +01:00
}
2009-02-05 19:57:53 +01:00
if ( Token : : Match ( tok , " [;{}] %num% " ) & & ! Token : : Match ( tok - > tokAt ( 2 ) , " [,}] " ) )
2009-01-26 20:14:46 +01:00
{
2009-03-21 17:58:13 +01:00
constStatementError ( tok - > next ( ) , " numeric " ) ;
2009-01-26 20:14:46 +01:00
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// str plus char
//---------------------------------------------------------------------------
void CheckOther : : strPlusChar ( )
{
bool charVars [ 10000 ] = { 0 } ;
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
// Declaring char variable..
if ( Token : : Match ( tok , " char %var% [;=] " ) )
{
unsigned int varid = tok - > next ( ) - > varId ( ) ;
if ( varid > 0 & & varid < 10000 )
charVars [ varid ] = true ;
}
//
else if ( Token : : Match ( tok , " [=(] %str% + %any% " ) )
{
// char constant..
const char * s = tok - > strAt ( 3 ) ;
if ( * s = = ' \' ' )
2009-03-21 17:58:13 +01:00
strPlusChar ( tok - > next ( ) ) ;
2009-01-26 20:14:46 +01:00
// char variable..
unsigned int varid = tok - > tokAt ( 3 ) - > varId ( ) ;
if ( varid > 0 & & varid < 10000 & & charVars [ varid ] )
2009-03-21 17:58:13 +01:00
strPlusChar ( tok - > next ( ) ) ;
2009-01-26 20:14:46 +01:00
}
}
}
2009-02-04 19:49:19 +01:00
2009-10-11 17:10:20 +02:00
void CheckOther : : nullPointerAfterLoop ( )
2009-03-27 17:19:34 +01:00
{
// Locate insufficient null-pointer handling after loop
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( ! Token : : Match ( tok , " while ( %var% ) " ) )
continue ;
const unsigned int varid ( tok - > tokAt ( 2 ) - > varId ( ) ) ;
if ( varid = = 0 )
continue ;
2009-08-11 17:18:01 +02:00
const std : : string varname ( tok - > strAt ( 2 ) ) ;
2009-03-27 17:19:34 +01:00
// Locate the end of the while loop..
const Token * tok2 = tok - > tokAt ( 4 ) ;
2009-08-17 22:23:37 +02:00
if ( tok2 - > str ( ) = = " { " )
tok2 = tok2 - > link ( ) ;
else
2009-03-27 17:19:34 +01:00
{
2009-08-17 22:23:37 +02:00
while ( tok2 & & tok2 - > str ( ) ! = " ; " )
tok2 = tok2 - > next ( ) ;
2009-03-27 17:19:34 +01:00
}
// Goto next token
2009-08-17 22:23:37 +02:00
if ( tok2 )
tok2 = tok2 - > next ( ) ;
2009-03-27 17:19:34 +01:00
// Check if the variable is dereferenced..
while ( tok2 )
{
2009-10-05 13:46:38 +02:00
if ( tok2 - > str ( ) = = " { " | | tok2 - > str ( ) = = " } " | | tok2 - > str ( ) = = " break " )
2009-03-27 17:19:34 +01:00
break ;
if ( tok2 - > varId ( ) = = varid )
{
if ( tok2 - > next ( ) - > str ( ) = = " . " | | Token : : Match ( tok2 - > next ( ) , " = %varid% . " , varid ) )
2009-05-10 08:43:16 +02:00
{
// Is this variable a pointer?
2009-10-08 10:55:37 +02:00
const Token * tok3 = Token : : findmatch ( _tokenizer - > tokens ( ) , " %type% * %varid% [;)=] " , varid ) ;
2009-05-10 08:43:16 +02:00
if ( ! tok3 )
break ;
if ( ! tok3 - > previous ( ) | |
Token : : Match ( tok3 - > previous ( ) , " [({};] " ) | |
tok3 - > previous ( ) - > isName ( ) )
{
2009-08-11 17:18:01 +02:00
nullPointerError ( tok2 , varname ) ;
2009-05-10 08:43:16 +02:00
}
}
2009-03-27 17:19:34 +01:00
break ;
}
tok2 = tok2 - > next ( ) ;
}
}
2009-10-11 17:10:20 +02:00
}
2009-07-20 18:53:41 +02:00
2009-10-11 17:10:20 +02:00
void CheckOther : : nullPointerLinkedList ( )
{
2009-07-31 10:49:43 +02:00
// looping through items in a linked list in a inner loop..
for ( const Token * tok1 = _tokenizer - > tokens ( ) ; tok1 ; tok1 = tok1 - > next ( ) )
{
// search for a "for" token..
if ( ! Token : : simpleMatch ( tok1 , " for ( " ) )
continue ;
if ( ! Token : : simpleMatch ( tok1 - > next ( ) - > link ( ) , " ) { " ) )
continue ;
// is there any dereferencing occuring in the for statement..
unsigned int parlevel2 = 1 ;
for ( const Token * tok2 = tok1 - > tokAt ( 2 ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
// Parantheses..
if ( tok2 - > str ( ) = = " ( " )
+ + parlevel2 ;
else if ( tok2 - > str ( ) = = " ) " )
{
if ( parlevel2 < = 1 )
break ;
- - parlevel2 ;
}
// Dereferencing a variable inside the "for" parantheses..
else if ( Token : : Match ( tok2 , " %var% . %var% " ) )
{
const unsigned int varid ( tok2 - > varId ( ) ) ;
if ( varid = = 0 )
continue ;
2009-08-01 11:30:37 +02:00
if ( Token : : Match ( tok2 - > tokAt ( - 2 ) , " %varid% ? " , varid ) )
continue ;
2009-08-11 17:18:01 +02:00
const std : : string varname ( tok2 - > str ( ) ) ;
2009-07-31 10:49:43 +02:00
// Check usage of dereferenced variable in the loop..
unsigned int indentlevel3 = 0 ;
for ( const Token * tok3 = tok1 - > next ( ) - > link ( ) ; tok3 ; tok3 = tok3 - > next ( ) )
{
if ( tok3 - > str ( ) = = " { " )
+ + indentlevel3 ;
else if ( tok3 - > str ( ) = = " } " )
{
if ( indentlevel3 < = 1 )
break ;
- - indentlevel3 ;
}
else if ( Token : : Match ( tok3 , " while ( %varid% &&|) " , varid ) )
{
// Make sure there is a "break" to prevent segmentation faults..
unsigned int indentlevel4 = indentlevel3 ;
2009-10-07 22:38:21 +02:00
for ( const Token * tok4 = tok3 - > next ( ) - > link ( ) ; tok4 ; tok4 = tok4 - > next ( ) )
2009-07-31 10:49:43 +02:00
{
if ( tok4 - > str ( ) = = " { " )
+ + indentlevel4 ;
else if ( tok4 - > str ( ) = = " } " )
{
if ( indentlevel4 < = 1 )
{
2009-10-08 10:55:37 +02:00
// Is this variable a pointer?
const Token * tempTok = Token : : findmatch ( _tokenizer - > tokens ( ) , " %type% * %varid% [;)=] " , varid ) ;
if ( tempTok )
nullPointerError ( tok1 , varname ) ;
2009-07-31 10:49:43 +02:00
break ;
}
- - indentlevel4 ;
}
else if ( tok4 - > str ( ) = = " break " )
break ;
}
}
}
}
}
}
2009-10-11 17:10:20 +02:00
}
void CheckOther : : nullPointerStructByDeRefAndChec ( )
{
2009-07-31 10:49:43 +02:00
2009-07-23 14:13:46 +02:00
// Dereferencing a struct pointer and then checking if it's NULL..
2009-07-20 18:53:41 +02:00
for ( const Token * tok1 = _tokenizer - > tokens ( ) ; tok1 ; tok1 = tok1 - > next ( ) )
{
2009-07-20 19:30:33 +02:00
if ( Token : : Match ( tok1 , " [{};] %var% = %var% . %var% " ) )
2009-07-20 18:53:41 +02:00
{
2009-07-20 19:30:33 +02:00
if ( std : : string ( tok1 - > strAt ( 1 ) ) = = tok1 - > strAt ( 3 ) )
continue ;
tok1 = tok1 - > tokAt ( 3 ) ;
2009-07-21 17:00:11 +02:00
const unsigned int varid1 ( tok1 - > varId ( ) ) ;
if ( varid1 = = 0 )
2009-07-20 19:10:33 +02:00
continue ;
2009-08-11 17:18:01 +02:00
const std : : string varname ( tok1 - > str ( ) ) ;
2009-07-23 19:59:29 +02:00
// Checking if the struct pointer is non-null before the assignment..
{
const Token * tok2 = _tokenizer - > tokens ( ) ;
while ( tok2 )
{
if ( tok2 = = tok1 )
break ;
if ( Token : : Match ( tok2 , " if|while ( !| %varid% ) " , varid1 ) )
break ;
tok2 = tok2 - > next ( ) ;
}
if ( tok2 ! = tok1 )
continue ;
}
2009-07-20 18:53:41 +02:00
unsigned int indentlevel2 = 0 ;
for ( const Token * tok2 = tok1 - > tokAt ( 3 ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( tok2 - > str ( ) = = " { " )
+ + indentlevel2 ;
2009-07-20 19:30:33 +02:00
2009-07-20 18:53:41 +02:00
else if ( tok2 - > str ( ) = = " } " )
{
if ( indentlevel2 = = 0 )
break ;
- - indentlevel2 ;
}
2009-07-20 19:30:33 +02:00
2009-08-12 18:54:52 +02:00
// goto destination..
else if ( tok2 - > isName ( ) & & Token : : simpleMatch ( tok2 - > next ( ) , " : " ) )
break ;
2009-07-21 12:09:58 +02:00
// Reassignment of the struct
else if ( tok2 - > varId ( ) = = varid1 )
{
2009-07-27 11:25:41 +02:00
if ( tok2 - > next ( ) - > str ( ) = = " = " )
2009-07-21 12:09:58 +02:00
break ;
if ( Token : : Match ( tok2 - > tokAt ( - 2 ) , " [,(] & " ) )
break ;
}
2009-07-29 11:17:22 +02:00
// Loop..
/** @todo don't bail out if the variable is not used in the loop */
else if ( tok2 - > str ( ) = = " do " )
break ;
2009-07-21 12:09:58 +02:00
// return at base level => stop checking
else if ( indentlevel2 = = 0 & & tok2 - > str ( ) = = " return " )
2009-07-20 19:59:55 +02:00
break ;
2009-07-21 17:00:11 +02:00
else if ( Token : : Match ( tok2 , " if ( !| %varid% ) " , varid1 ) )
2009-07-20 18:53:41 +02:00
{
2009-10-08 10:55:37 +02:00
// Is this variable a pointer?
const Token * tempTok = Token : : findmatch ( _tokenizer - > tokens ( ) , " %type% * %varid% [;)=] " , varid1 ) ;
if ( tempTok )
nullPointerError ( tok1 , varname , tok2 - > linenr ( ) ) ;
2009-07-21 17:00:11 +02:00
break ;
2009-07-20 18:53:41 +02:00
}
}
}
}
2009-07-23 14:13:46 +02:00
2009-10-11 17:10:20 +02:00
}
void CheckOther : : nullPointerByDeRefAndChec ( )
{
2009-07-23 14:13:46 +02:00
// Dereferencing a pointer and then checking if it's NULL..
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
if ( tok - > str ( ) = = " if " & & Token : : Match ( tok - > previous ( ) , " ; if ( ! %var% ) " ) )
{
const unsigned int varid ( tok - > tokAt ( 3 ) - > varId ( ) ) ;
if ( varid = = 0 )
continue ;
2009-08-11 17:18:01 +02:00
const std : : string varname ( tok - > strAt ( 3 ) ) ;
2009-07-25 20:36:02 +02:00
const Token * decltok = Token : : findmatch ( _tokenizer - > tokens ( ) , " %varid% " , varid ) ;
if ( ! Token : : Match ( decltok - > tokAt ( - 3 ) , " [;,(] %var% * " ) )
continue ;
for ( const Token * tok1 = tok - > previous ( ) ; tok1 & & tok1 ! = decltok ; tok1 = tok1 - > previous ( ) )
2009-07-23 14:13:46 +02:00
{
if ( tok1 - > varId ( ) = = varid )
{
2009-08-28 08:48:37 +02:00
if ( Token : : Match ( tok1 - > tokAt ( - 2 ) , " [=;{}] * " ) )
2009-07-23 14:13:46 +02:00
{
2009-08-11 17:18:01 +02:00
nullPointerError ( tok1 , varname ) ;
2009-07-23 14:13:46 +02:00
break ;
}
2009-07-23 19:02:14 +02:00
else if ( tok1 - > previous ( ) & & tok1 - > previous ( ) - > str ( ) = = " & " )
{
break ;
}
2009-07-23 14:13:46 +02:00
else if ( tok1 - > next ( ) & & tok1 - > next ( ) - > str ( ) = = " = " )
{
break ;
}
}
else if ( tok1 - > str ( ) = = " { " ||
tok1 - > str ( ) = = " } " )
break ;
2009-08-12 18:54:52 +02:00
// goto destination..
else if ( tok1 - > isName ( ) & & Token : : simpleMatch ( tok1 - > next ( ) , " : " ) )
break ;
2009-07-23 14:13:46 +02:00
}
}
}
2009-03-27 17:19:34 +01:00
}
2009-10-19 17:32:43 +02:00
void CheckOther : : nullPointerConditionalAssignment ( )
{
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
// 1. Initialize..
2009-10-20 20:57:38 +02:00
if ( ! Token : : Match ( tok , " ; %var% = 0 ; " ) )
2009-10-19 17:32:43 +02:00
continue ;
const unsigned int varid ( tok - > next ( ) - > varId ( ) ) ;
if ( ! varid )
continue ;
2009-10-20 20:57:38 +02:00
for ( const Token * tok2 = tok - > tokAt ( 4 ) ; tok2 ; tok2 = tok2 - > next ( ) )
2009-10-19 17:32:43 +02:00
{
if ( tok2 - > str ( ) = = " { " | | tok2 - > str ( ) = = " } " )
break ;
if ( Token : : simpleMatch ( tok2 , " if ( " ) )
{
const Token * tok3 = tok2 ;
tok3 = tok3 - > next ( ) - > link ( ) ;
if ( ! tok3 )
break ;
2009-10-30 15:14:24 +01:00
// check if the condition contains the variable..
for ( const Token * tok4 = tok2 - > tokAt ( 2 ) ; tok4 & & tok4 ! = tok3 ; tok4 = tok4 - > next ( ) )
{
if ( tok4 - > varId ( ) = = varid )
{
// The condition contains the variable..
// to avoid false positives I bail out..
tok3 = 0 ;
break ;
}
}
if ( ! tok3 )
break ;
2009-10-19 17:32:43 +02:00
if ( tok3 - > next ( ) - > str ( ) = = " { " )
{
tok2 = tok3 - > next ( ) - > link ( ) ;
if ( ! tok2 )
break ;
}
continue ;
}
if ( Token : : Match ( tok2 , " else !!if " ) )
break ;
2009-10-20 20:57:38 +02:00
if ( Token : : Match ( tok2 , " %varid% " , varid ) )
{
if ( Token : : Match ( tok2 , " %varid% . %var% ( " , varid ) )
2009-11-01 12:08:37 +01:00
{
const Token * tempTok = Token : : findmatch ( _tokenizer - > tokens ( ) , " %type% * %varid% [;)=] " , varid ) ;
if ( tempTok )
nullPointerError ( tok2 , tok - > next ( ) - > str ( ) ) ;
}
2009-10-20 20:57:38 +02:00
break ;
}
2009-10-19 17:32:43 +02:00
}
}
}
2009-10-11 17:10:20 +02:00
void CheckOther : : nullPointer ( )
{
nullPointerAfterLoop ( ) ;
nullPointerLinkedList ( ) ;
nullPointerStructByDeRefAndChec ( ) ;
nullPointerByDeRefAndChec ( ) ;
2009-10-19 17:32:43 +02:00
nullPointerConditionalAssignment ( ) ;
2009-10-11 17:10:20 +02:00
}
2009-03-27 17:19:34 +01:00
2009-11-03 17:03:53 +01:00
static const Token * uninitvar_checkscope ( const Token * const tokens , const Token * tok , const unsigned int varid , bool & init , const bool pointer , const bool array )
2009-10-29 21:34:43 +01:00
{
/* limit the checking in conditional code..
* int x ;
* if ( y )
* x = 33 ;
* if ( y )
* return x ;
*/
bool limit = false ;
for ( ; tok ; tok = tok - > next ( ) )
{
if ( tok - > str ( ) = = " } " )
return 0 ;
// todo: handle for/while
2009-10-30 14:52:20 +01:00
if ( Token : : Match ( tok , " for|while|switch " ) )
2009-10-29 21:34:43 +01:00
{
init = true ;
return 0 ;
}
if ( tok - > str ( ) = = " if " )
{
bool canInit = false ;
bool ifInit = true ;
while ( tok - > str ( ) = = " if " )
{
// goto "("
tok = tok - > next ( ) ;
// goto ")"
tok = tok ? tok - > link ( ) : 0 ;
2009-10-30 18:28:01 +01:00
// Check if the condition contains the variable
if ( tok )
{
for ( const Token * tok2 = tok - > link ( ) ; tok2 & & tok2 ! = tok ; tok2 = tok2 - > next ( ) )
{
// The variable may be initialized..
// if (someFunction(&var)) ..
if ( tok2 - > varId ( ) )
{
init = true ;
return 0 ;
}
}
}
2009-10-29 21:34:43 +01:00
// goto "{"
tok = tok ? tok - > next ( ) : 0 ;
if ( ! Token : : simpleMatch ( tok , " { " ) )
return 0 ;
// Recursively check into the if ..
bool init2 = false ;
2009-11-03 17:03:53 +01:00
const Token * tokerr = uninitvar_checkscope ( tokens , tok - > next ( ) , varid , init2 , pointer , array ) ;
2009-10-29 21:34:43 +01:00
if ( ! limit & & tokerr )
return tokerr ;
// if the scope didn't initialize then this whole if-chain is treated as non-initializing
ifInit & = init2 ;
canInit | = init2 ;
// goto "}"
tok = tok - > link ( ) ;
// there is no else => not initialized
if ( Token : : Match ( tok , " } !!else " ) )
{
ifInit = false ;
break ;
}
// parse next "if"..
tok = tok - > tokAt ( 2 ) ;
if ( tok - > str ( ) = = " if " )
continue ;
// there is no "if"..
init2 = false ;
2009-11-03 17:03:53 +01:00
tokerr = uninitvar_checkscope ( tokens , tok - > next ( ) , varid , init2 , pointer , array ) ;
2009-10-29 21:34:43 +01:00
if ( ! limit & & tokerr )
return tokerr ;
ifInit & = init2 ;
canInit | = init2 ;
tok = tok - > link ( ) ;
if ( ! tok )
return 0 ;
}
if ( ifInit )
{
init = true ;
return 0 ;
}
if ( canInit )
{
limit = true ;
}
}
2009-11-02 16:28:15 +01:00
if ( Token : : Match ( tok , " %varid% " , varid ) )
2009-10-29 21:34:43 +01:00
{
2009-11-02 16:28:15 +01:00
if ( Token : : simpleMatch ( tok - > previous ( ) , " >> " ) | | Token : : simpleMatch ( tok - > next ( ) , " = " ) )
{
init = true ;
return 0 ;
}
2009-11-03 21:02:16 +01:00
if ( Token : : simpleMatch ( tok - > next ( ) , " [ " ) )
{
2009-11-03 22:48:41 +01:00
const Token * tok2 = tok - > next ( ) - > link ( ) ;
2009-11-03 21:02:16 +01:00
if ( Token : : simpleMatch ( tok2 ? tok2 - > next ( ) : 0 , " = " ) )
{
init = true ;
return 0 ;
}
}
2009-10-29 21:34:43 +01:00
}
2009-10-30 14:06:40 +01:00
if ( Token : : Match ( tok , " %var% ( " ) )
{
2009-10-31 16:36:56 +01:00
if ( Token : : Match ( tok , " strlen ( %varid% ) " , varid ) )
return tok - > tokAt ( 2 ) ;
if ( Token : : Match ( tok , " strcpy|strcat|strncpy|strncat|memcpy ( %any% , %varid% [,)] " , varid ) )
return tok - > tokAt ( 4 ) ;
2009-11-03 17:03:53 +01:00
if ( Token : : Match ( tok , " strcat|strncat ( %varid% , " , varid ) )
return tok - > tokAt ( 3 ) ;
2009-11-06 19:06:45 +01:00
if ( Token : : Match ( tok , " strncpy ( %varid% " , varid ) )
{
tok = tok - > tokAt ( 3 ) ;
continue ;
}
2009-11-03 17:03:53 +01:00
if ( Token : : Match ( tok , " asm ( ) " ) )
{
init = true ;
return 0 ;
}
2009-10-31 16:36:56 +01:00
2009-10-30 14:06:40 +01:00
// is the variable passed as a parameter to some function?
unsigned int parlevel = 0 ;
for ( const Token * tok2 = tok - > next ( ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
2009-11-03 17:03:53 +01:00
if ( tok2 - > str ( ) = = " ( " )
2009-10-30 14:06:40 +01:00
+ + parlevel ;
2009-11-03 17:03:53 +01:00
else if ( tok2 - > str ( ) = = " ) " )
2009-10-30 14:06:40 +01:00
{
if ( parlevel < = 1 )
break ;
- - parlevel ;
}
else if ( tok2 - > varId ( ) = = varid )
{
// it is possible that the variable is initialized here
init = true ;
return 0 ;
}
}
}
2009-11-06 16:02:13 +01:00
if ( tok - > str ( ) = = " return " )
{
for ( const Token * tok2 = tok ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( tok2 - > str ( ) = = " ; " )
return 0 ;
if ( tok2 - > varId ( ) = = varid )
break ;
}
}
2009-10-30 14:31:37 +01:00
if ( tok - > varId ( ) = = varid )
{
2009-11-08 07:31:01 +01:00
if ( array & & ! Token : : simpleMatch ( tok - > next ( ) , " [ " ) )
continue ;
2009-11-08 09:54:08 +01:00
2009-10-30 14:31:37 +01:00
if ( Token : : simpleMatch ( tok - > previous ( ) , " return " ) )
return tok ;
2009-11-02 19:58:49 +01:00
if ( Token : : simpleMatch ( tok - > previous ( ) , " = " ) )
2009-11-03 17:03:53 +01:00
{
2009-11-05 21:07:04 +01:00
if ( ! Token : : Match ( tok - > tokAt ( - 3 ) , " . %var% = " ) )
2009-11-03 17:03:53 +01:00
{
2009-11-05 21:07:04 +01:00
if ( ! Token : : Match ( tok - > tokAt ( - 3 ) , " [;{}] %var% = " ) )
2009-11-03 17:03:53 +01:00
return tok ;
2009-11-05 21:07:04 +01:00
const unsigned int varid2 = tok - > tokAt ( - 2 ) - > varId ( ) ;
if ( varid2 )
{
const Token * tok2 = Token : : findmatch ( tokens , " %varid% " , varid2 ) ;
if ( tok2 & & ! Token : : simpleMatch ( tok2 - > previous ( ) , " * " ) )
return tok ;
}
2009-11-03 17:03:53 +01:00
}
}
2009-11-02 19:58:49 +01:00
2009-10-30 14:31:37 +01:00
if ( pointer & & Token : : simpleMatch ( tok - > next ( ) , " . " ) )
return tok ;
2009-10-31 16:36:56 +01:00
if ( array & & Token : : simpleMatch ( tok - > next ( ) , " [ " ) )
{
init = true ;
return 0 ;
}
2009-10-30 14:31:37 +01:00
}
2009-10-29 21:34:43 +01:00
}
return 0 ;
}
void CheckOther : : uninitvar ( )
{
2009-10-30 13:43:00 +01:00
// start of function..
2009-10-29 21:34:43 +01:00
const Token * tok = _tokenizer - > tokens ( ) ;
2009-10-30 13:43:00 +01:00
while ( 0 ! = ( tok = Token : : findmatch ( tok , " ) const| { " ) ) )
2009-10-29 21:34:43 +01:00
{
2009-10-30 13:43:00 +01:00
// Scan through this scope and check all variables..
unsigned int indentlevel = 0 ;
for ( ; tok ; tok = tok - > next ( ) )
{
if ( tok - > str ( ) = = " { " )
+ + indentlevel ;
else if ( tok - > str ( ) = = " } " )
{
if ( indentlevel < = 1 )
break ;
- - indentlevel ;
}
2009-11-07 13:19:25 +01:00
2009-11-07 09:10:15 +01:00
if ( Token : : Match ( tok , " [{};] %var% = malloc|kmalloc ( " ) | |
2009-11-07 13:19:25 +01:00
Token : : Match ( tok , " [{};] %var% = new char [ " ) )
2009-11-07 09:10:15 +01:00
{
// check that the variable id is non-zero
const unsigned int varid = tok - > next ( ) - > varId ( ) ;
if ( varid = = 0 )
continue ;
// goto ')'
2009-11-07 14:54:12 +01:00
tok = tok - > tokAt ( 4 ) ;
if ( tok - > str ( ) = = " ( " )
tok = tok - > link ( ) ;
2009-11-07 09:10:15 +01:00
if ( ! tok )
break ;
// check if data is accessed uninitialized..
for ( const Token * tok2 = tok - > next ( ) ; tok2 ; tok2 = tok2 - > next ( ) )
{
if ( tok2 - > str ( ) = = " { " | | tok2 - > str ( ) = = " } " )
break ;
if ( tok2 - > varId ( ) = = varid )
break ;
if ( Token : : Match ( tok2 , " strcat|strncat|strlen ( %varid% " , varid ) )
uninitdataError ( tok2 , tok2 - > strAt ( 2 ) ) ;
}
}
else if ( Token : : Match ( tok , " [{};] %type% *| %var% [;[] " ) )
2009-10-30 13:43:00 +01:00
{
2009-10-30 15:23:27 +01:00
if ( Token : : Match ( tok - > next ( ) , " return|goto " ) )
continue ;
2009-10-30 18:28:01 +01:00
2009-10-30 14:31:37 +01:00
// if it's a pointer, dereferencing is forbidden
const bool pointer ( tok - > strAt ( 2 ) = = std : : string ( " * " ) ) ;
2009-10-31 10:30:32 +01:00
// classes are initialized by their constructors
if ( ! pointer & & ! tok - > next ( ) - > isStandardType ( ) )
continue ;
2009-10-30 13:43:00 +01:00
// goto the variable
tok = tok - > tokAt ( 2 ) ;
if ( tok - > str ( ) = = " * " )
tok = tok - > next ( ) ;
2009-10-29 21:34:43 +01:00
2009-10-30 13:43:00 +01:00
// check that the variable id is non-zero
if ( tok - > varId ( ) = = 0 )
continue ;
2009-10-29 21:34:43 +01:00
2009-10-31 16:36:56 +01:00
// Is it an array?
const bool array ( tok - > next ( ) - > str ( ) = = " [ " ) ;
2009-11-06 16:50:02 +01:00
if ( array )
{
// is the array initialized?
if ( Token : : simpleMatch ( tok - > next ( ) , " [ ] = " ) | |
Token : : Match ( tok - > next ( ) , " [ %any% ] = " ) )
continue ;
}
2009-10-31 16:36:56 +01:00
2009-10-30 13:43:00 +01:00
// check if variable is accessed uninitialized..
bool init = false ;
2009-11-03 17:03:53 +01:00
const Token * tokerr = uninitvar_checkscope ( _tokenizer - > tokens ( ) , tok - > next ( ) , tok - > varId ( ) , init , pointer , array ) ;
2009-10-30 13:43:00 +01:00
if ( tokerr )
uninitvarError ( tokerr , tok - > str ( ) ) ;
}
}
2009-10-29 21:34:43 +01:00
}
}
2009-07-05 22:16:43 +02:00
void CheckOther : : checkZeroDivision ( )
2009-03-28 07:49:47 +01:00
{
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
2009-09-01 21:06:46 +02:00
2009-09-01 16:00:26 +02:00
if ( Token : : Match ( tok , " / %num% " ) & &
2009-09-01 21:06:46 +02:00
MathLib : : isInt ( tok - > next ( ) - > str ( ) ) & &
MathLib : : toLongNumber ( tok - > next ( ) - > str ( ) ) = = 0L )
2009-08-23 05:34:19 +02:00
{
2009-03-29 18:47:05 +02:00
zerodivError ( tok ) ;
2009-08-23 05:34:19 +02:00
}
2009-09-01 21:06:46 +02:00
else if ( Token : : Match ( tok , " div|ldiv|lldiv|imaxdiv ( %num% , %num% ) " ) & &
MathLib : : isInt ( tok - > tokAt ( 4 ) - > str ( ) ) & &
MathLib : : toLongNumber ( tok - > tokAt ( 4 ) - > str ( ) ) = = 0L )
2009-08-23 05:34:19 +02:00
{
zerodivError ( tok ) ;
}
2009-03-28 07:49:47 +01:00
}
}
2009-07-25 00:36:15 +02:00
void CheckOther : : postIncrement ( )
{
for ( const Token * tok = _tokenizer - > tokens ( ) ; tok ; tok = tok - > next ( ) )
{
2009-07-25 19:36:57 +02:00
if ( Token : : simpleMatch ( tok , " for ( " ) )
2009-07-25 00:36:15 +02:00
{
2009-07-25 19:36:57 +02:00
const Token * tok2 = tok - > next ( ) - > link ( ) ;
if ( tok2 )
tok2 = tok2 - > tokAt ( - 3 ) ;
2009-07-25 00:36:15 +02:00
if ( Token : : Match ( tok2 , " ; %var% ++|-- ) " ) )
{
2009-07-26 11:46:00 +02:00
if ( tok2 - > next ( ) - > varId ( ) = = 0 )
continue ;
2009-07-25 00:36:15 +02:00
// Take a look at the variable declaration
const Token * decltok = Token : : findmatch ( _tokenizer - > tokens ( ) , " %varid% " , tok2 - > tokAt ( 1 ) - > varId ( ) ) ;
const std : : string classDef = std : : string ( " class " ) + std : : string ( decltok - > previous ( ) - > strAt ( 0 ) ) ;
// Is the variable an iterator?
if ( decltok & & Token : : Match ( decltok - > previous ( ) , " iterator|const_iterator " ) )
postIncrementError ( tok2 , tok2 - > strAt ( 1 ) , ( std : : string ( " ++ " ) = = tok2 - > strAt ( 2 ) ) ) ;
// Is the variable a class?
2009-07-25 01:23:30 +02:00
else if ( Token : : findmatch ( _tokenizer - > tokens ( ) , classDef . c_str ( ) ) )
2009-07-25 00:36:15 +02:00
postIncrementError ( tok2 , tok2 - > strAt ( 1 ) , ( std : : string ( " ++ " ) = = tok2 - > strAt ( 2 ) ) ) ;
break ;
}
}
}
}
2009-03-28 07:49:47 +01:00
2009-03-21 17:58:13 +01:00
void CheckOther : : cstyleCastError ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " cstyleCast " , " C-style pointer casting " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : redundantIfDelete0Error ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " redundantIfDelete0 " , " Redundant condition. It is safe to deallocate a NULL pointer " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : redundantIfRemoveError ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " redundantIfRemove " , " Redundant condition. The remove function in the STL will not do anything if element doesn't exist " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : dangerousUsageStrtolError ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : error , " dangerousUsageStrtol " , " Invalid radix in call to strtol or strtoul. Must be 0 or 2-36 " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : sprintfOverlappingDataError ( const Token * tok , const std : : string & varname )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : error , " sprintfOverlappingData " , " Overlapping data buffer " + varname + " \n When using sprintf the same buffer must not be used both for output and input. The behaviour is undefined when that happens. \n For example: 'sprintf(str, \" <%s> \" ,str);' " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : udivError ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : error , " udivError " , " Unsigned division. The result will be wrong. " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : udivWarning ( const Token * tok )
{
2009-09-15 20:46:47 +02:00
reportError ( tok , Severity : : possibleStyle , " udivWarning " , " Division with signed and unsigned operators " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : unusedStructMemberError ( const Token * tok , const std : : string & structname , const std : : string & varname )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " unusedStructMember " , " struct or union member ' " + structname + " :: " + varname + " ' is never used " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : passedByValueError ( const Token * tok , const std : : string & parname )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " passedByValue " , " Function parameter ' " + parname + " ' is passed by value. It could be passed by reference instead. " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : constStatementError ( const Token * tok , const std : : string & type )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " constStatement " , " Redundant code: Found a statement that begins with " + type + " constant " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : charArrayIndexError ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " charArrayIndex " , " Warning - using char variable as array index " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : charBitOpError ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " charBitOp " , " Warning - using char variable in bit operation " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : variableScopeError ( const Token * tok , const std : : string & varname )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " variableScope " , " The scope of the variable " + varname + " can be limited " ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : conditionAlwaysTrueFalse ( const Token * tok , const std : : string & truefalse )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : style , " conditionAlwaysTrueFalse " , " Condition is always " + truefalse ) ;
2009-03-21 17:58:13 +01:00
}
void CheckOther : : strPlusChar ( const Token * tok )
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : error , " strPlusChar " , " Unusual pointer arithmetic " ) ;
2009-03-21 17:58:13 +01:00
}
2009-08-11 17:18:01 +02:00
void CheckOther : : nullPointerError ( const Token * tok , const std : : string & varname )
2009-03-27 17:19:34 +01:00
{
2009-08-11 17:18:01 +02:00
reportError ( tok , Severity : : error , " nullPointer " , " Possible null pointer dereference: " + varname ) ;
2009-03-27 17:19:34 +01:00
}
2009-03-28 07:49:47 +01:00
2009-08-21 12:42:40 +02:00
void CheckOther : : nullPointerError ( const Token * tok , const std : : string & varname , const int line )
{
2009-08-21 14:50:13 +02:00
reportError ( tok , Severity : : error , " nullPointer " , " Possible null pointer dereference: " + varname + " - otherwise it is redundant to check if " + varname + " is null at line " + MathLib : : toString < long > ( line ) ) ;
2009-08-21 12:42:40 +02:00
}
2009-11-07 09:10:15 +01:00
void CheckOther : : uninitdataError ( const Token * tok , const std : : string & varname )
{
reportError ( tok , Severity : : error , " uninitdata " , " Data is allocated but not initialized: " + varname ) ;
}
2009-10-29 21:34:43 +01:00
void CheckOther : : uninitvarError ( const Token * tok , const std : : string & varname )
{
reportError ( tok , Severity : : error , " uninitvar " , " Uninitialized variable: " + varname ) ;
}
2009-03-29 18:47:05 +02:00
void CheckOther : : zerodivError ( const Token * tok )
2009-03-28 07:49:47 +01:00
{
2009-07-13 10:16:31 +02:00
reportError ( tok , Severity : : error , " zerodiv " , " Division by zero " ) ;
2009-03-28 07:49:47 +01:00
}
2009-07-25 00:36:15 +02:00
void CheckOther : : postIncrementError ( const Token * tok , const std : : string & var_name , const bool isIncrement )
{
2009-07-25 01:23:30 +02:00
std : : string type = ( isIncrement ? " Incrementing " : " Decrementing " ) ;
reportError ( tok , Severity : : possibleStyle , " postIncrementDecrement " , ( " Pre- " + type + " variable ' " + var_name + " ' is preferred to Post- " + type ) ) ;
2009-07-25 00:36:15 +02:00
}