Refactoring: Global/Static variables, FunctionList, GlobalFunctions and UsedGlobalFunctions are now private members of Tokenizer class.
Class GlobalFunction is now private subclass of Tokenizer. Global functions CheckGlobalFunctionUsage, FillFunctionList and GetFunctionTokenByName are now member functions of Tokenizer.
This commit is contained in:
parent
2cbfa6b60b
commit
08b25dc0d4
|
@ -257,7 +257,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Find function..
|
// Find function..
|
||||||
const TOKEN *ftok = GetFunctionTokenByName( tok->str );
|
const TOKEN *ftok = _tokenizer->GetFunctionTokenByName( tok->str );
|
||||||
if ( ! ftok )
|
if ( ! ftok )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, const char types
|
||||||
++par;
|
++par;
|
||||||
if ( Match(tok, "[,()] %var1% [,()]", varnames) )
|
if ( Match(tok, "[,()] %var1% [,()]", varnames) )
|
||||||
{
|
{
|
||||||
const TOKEN *ftok = GetFunctionTokenByName(funcname);
|
const TOKEN *ftok = _tokenizer->GetFunctionTokenByName(funcname);
|
||||||
const char *parname = GetParameterName( ftok, par );
|
const char *parname = GetParameterName( ftok, par );
|
||||||
if ( ! parname )
|
if ( ! parname )
|
||||||
return "use";
|
return "use";
|
||||||
|
|
202
CommonCheck.cpp
202
CommonCheck.cpp
|
@ -32,30 +32,9 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#endif
|
#endif
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
extern bool CheckCodingStyle;
|
|
||||||
bool OnlyReportUniqueErrors;
|
bool OnlyReportUniqueErrors;
|
||||||
std::ostringstream errout;
|
std::ostringstream errout;
|
||||||
static std::list<const TOKEN *> FunctionList;
|
|
||||||
|
|
||||||
class GlobalFunction
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
unsigned int _FileId;
|
|
||||||
std::string _FuncName;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GlobalFunction( const unsigned int FileId, const char FuncName[] )
|
|
||||||
{
|
|
||||||
_FileId = FileId;
|
|
||||||
_FuncName = FuncName;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int file_id() const { return _FileId; }
|
|
||||||
const std::string &name() const { return _FuncName; }
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::list< GlobalFunction > GlobalFunctions;
|
|
||||||
static std::list< GlobalFunction > UsedGlobalFunctions;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -122,118 +101,6 @@ bool IsStandardType(const char str[])
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void FillFunctionList(const unsigned int file_id)
|
|
||||||
{
|
|
||||||
FunctionList.clear();
|
|
||||||
|
|
||||||
std::list<const char *> _usedfunc;
|
|
||||||
if ( file_id == 0 )
|
|
||||||
{
|
|
||||||
GlobalFunctions.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool staticfunc = false;
|
|
||||||
bool classfunc = false;
|
|
||||||
|
|
||||||
int indentlevel = 0;
|
|
||||||
for ( const TOKEN *tok = tokens; tok; tok = tok->next )
|
|
||||||
{
|
|
||||||
if ( tok->str[0] == '{' )
|
|
||||||
indentlevel++;
|
|
||||||
|
|
||||||
else if ( tok->str[0] == '}' )
|
|
||||||
indentlevel--;
|
|
||||||
|
|
||||||
|
|
||||||
if (indentlevel > 0)
|
|
||||||
{
|
|
||||||
if ( CheckCodingStyle )
|
|
||||||
{
|
|
||||||
const char *funcname = 0;
|
|
||||||
|
|
||||||
if ( Match(tok,"%var% (") )
|
|
||||||
funcname = tok->str;
|
|
||||||
else if ( Match(tok, "= %var% ;") ||
|
|
||||||
Match(tok, "= %var% ,") )
|
|
||||||
funcname = tok->next->str;
|
|
||||||
|
|
||||||
if ( std::find(_usedfunc.begin(), _usedfunc.end(), funcname) == _usedfunc.end() )
|
|
||||||
_usedfunc.push_back( funcname );
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr("};", tok->str[0]))
|
|
||||||
staticfunc = classfunc = false;
|
|
||||||
|
|
||||||
else if ( strcmp( tok->str, "static" ) == 0 )
|
|
||||||
staticfunc = true;
|
|
||||||
|
|
||||||
else if ( strcmp( tok->str, "::" ) == 0 )
|
|
||||||
classfunc = true;
|
|
||||||
|
|
||||||
else if (Match(tok, "%var% ("))
|
|
||||||
{
|
|
||||||
// Check if this is the first token of a function implementation..
|
|
||||||
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
|
|
||||||
{
|
|
||||||
if ( tok2->str[0] == ';' )
|
|
||||||
{
|
|
||||||
tok = tok2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( tok2->str[0] == '{' )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( tok2->str[0] == ')' )
|
|
||||||
{
|
|
||||||
if ( Match(tok2, ") {") )
|
|
||||||
{
|
|
||||||
if (CheckCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0)
|
|
||||||
GlobalFunctions.push_back( GlobalFunction(file_id, tok->str) );
|
|
||||||
FunctionList.push_back( tok );
|
|
||||||
tok = tok2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tok = tok2;
|
|
||||||
while (tok->next && !strchr(";{", tok->next->str[0]))
|
|
||||||
tok = tok->next;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::list<const char *>::const_iterator it = _usedfunc.begin(); it != _usedfunc.end(); ++it)
|
|
||||||
{
|
|
||||||
if ( *it != 0 )
|
|
||||||
{
|
|
||||||
UsedGlobalFunctions.push_back( GlobalFunction(file_id, *it) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const TOKEN *GetFunctionTokenByName( const char funcname[] )
|
|
||||||
{
|
|
||||||
std::list<const TOKEN *>::const_iterator it;
|
|
||||||
for ( it = FunctionList.begin(); it != FunctionList.end(); it++ )
|
|
||||||
{
|
|
||||||
if ( strcmp( (*it)->str, funcname ) == 0 )
|
|
||||||
{
|
|
||||||
return *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const char *GetParameterName( const TOKEN *ftok, int par )
|
const char *GetParameterName( const TOKEN *ftok, int par )
|
||||||
{
|
{
|
||||||
int _par = 1;
|
int _par = 1;
|
||||||
|
@ -248,75 +115,6 @@ const char *GetParameterName( const TOKEN *ftok, int par )
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames)
|
|
||||||
{
|
|
||||||
// Iterator for GlobalFunctions
|
|
||||||
std::list<GlobalFunction>::const_iterator func;
|
|
||||||
|
|
||||||
// Iterator for UsedGlobalFunctions
|
|
||||||
std::list<GlobalFunction>::const_iterator usedfunc;
|
|
||||||
|
|
||||||
unsigned int i1 = 0;
|
|
||||||
unsigned int i2 = 1;
|
|
||||||
|
|
||||||
// Check that every function in GlobalFunctions are used
|
|
||||||
for ( func = GlobalFunctions.begin(); func != GlobalFunctions.end(); func++ )
|
|
||||||
{
|
|
||||||
if ( GlobalFunctions.size() > 100 )
|
|
||||||
{
|
|
||||||
++i1;
|
|
||||||
if ( i1 > (i2 * GlobalFunctions.size()) / 100 )
|
|
||||||
{
|
|
||||||
if ( (i2 % 10) == 0 )
|
|
||||||
std::cout << i2 << "%";
|
|
||||||
else
|
|
||||||
std::cout << ".";
|
|
||||||
std::cout.flush();
|
|
||||||
++i2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &funcname = func->name();
|
|
||||||
|
|
||||||
if ( funcname == "main" || funcname == "WinMain" )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check if this global function is used in any of the other files..
|
|
||||||
bool UsedOtherFile = false;
|
|
||||||
bool UsedAnyFile = false;
|
|
||||||
for ( usedfunc = UsedGlobalFunctions.begin(); usedfunc != UsedGlobalFunctions.end(); usedfunc++ )
|
|
||||||
{
|
|
||||||
if ( funcname == usedfunc->name() )
|
|
||||||
{
|
|
||||||
UsedAnyFile = true;
|
|
||||||
if (func->file_id() != usedfunc->file_id())
|
|
||||||
{
|
|
||||||
UsedOtherFile = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! UsedAnyFile )
|
|
||||||
{
|
|
||||||
std::ostringstream errmsg;
|
|
||||||
errmsg << "[" << filenames[func->file_id()] << "]: "
|
|
||||||
<< "The function '" << func->name() << "' is never used.";
|
|
||||||
ReportErr( errmsg.str() );
|
|
||||||
}
|
|
||||||
else if ( ! UsedOtherFile )
|
|
||||||
{
|
|
||||||
std::ostringstream errmsg;
|
|
||||||
errmsg << "[" << filenames[func->file_id()] << "]: "
|
|
||||||
<< "The linkage of the function '" << func->name() << "' can be local (static) instead of global";
|
|
||||||
ReportErr( errmsg.str() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
|
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define CommonCheckH
|
#define CommonCheckH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -47,10 +47,9 @@ bool IsNumber(const char str[]);
|
||||||
|
|
||||||
bool IsStandardType(const char str[]);
|
bool IsStandardType(const char str[]);
|
||||||
|
|
||||||
void FillFunctionList(const unsigned int file_id);
|
|
||||||
const TOKEN *GetFunctionTokenByName( const char funcname[] );
|
|
||||||
const char *GetParameterName( const TOKEN *ftok, int par );
|
const char *GetParameterName( const TOKEN *ftok, int par );
|
||||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
|
||||||
|
|
||||||
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
||||||
|
|
||||||
|
|
22
cppcheck.cpp
22
cppcheck.cpp
|
@ -18,7 +18,7 @@
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
|
|
||||||
#include "preprocessor.h" // preprocessor.
|
#include "preprocessor.h" // preprocessor.
|
||||||
#include "tokenize.h" // <- Tokenizer
|
|
||||||
#include "CommonCheck.h"
|
#include "CommonCheck.h"
|
||||||
#include "CheckMemoryLeak.h"
|
#include "CheckMemoryLeak.h"
|
||||||
#include "CheckBufferOverrun.h"
|
#include "CheckBufferOverrun.h"
|
||||||
|
@ -87,6 +87,7 @@ void CppCheck::check(int argc, char* argv[])
|
||||||
ShowAll = _settings._showAll;
|
ShowAll = _settings._showAll;
|
||||||
CheckCodingStyle = _settings._checkCodingStyle;
|
CheckCodingStyle = _settings._checkCodingStyle;
|
||||||
ErrorsOnly = _settings._errorsOnly;
|
ErrorsOnly = _settings._errorsOnly;
|
||||||
|
_tokenizer.settings( _settings );
|
||||||
|
|
||||||
std::vector<std::string> filenames;
|
std::vector<std::string> filenames;
|
||||||
// --recursive was used
|
// --recursive was used
|
||||||
|
@ -174,7 +175,7 @@ void CppCheck::check(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
errout.str("");
|
errout.str("");
|
||||||
std::cout << "Checking usage of global functions (this may take several minutes)..\n";
|
std::cout << "Checking usage of global functions (this may take several minutes)..\n";
|
||||||
CheckGlobalFunctionUsage(filenames);
|
_tokenizer.CheckGlobalFunctionUsage(filenames);
|
||||||
if ( ! errout.str().empty() )
|
if ( ! errout.str().empty() )
|
||||||
{
|
{
|
||||||
std::cerr << "\n";
|
std::cerr << "\n";
|
||||||
|
@ -191,28 +192,27 @@ void CppCheck::check(int argc, char* argv[])
|
||||||
|
|
||||||
void CppCheck::checkFile(const std::string &code, const char FileName[], unsigned int FileId)
|
void CppCheck::checkFile(const std::string &code, const char FileName[], unsigned int FileId)
|
||||||
{
|
{
|
||||||
Tokenizer tokenizer;
|
|
||||||
|
|
||||||
OnlyReportUniqueErrors = true;
|
OnlyReportUniqueErrors = true;
|
||||||
|
|
||||||
// Tokenize the file
|
// Tokenize the file
|
||||||
{
|
{
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.Tokenize(istr, FileName);
|
_tokenizer.Tokenize(istr, FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
FillFunctionList(FileId);
|
_tokenizer.FillFunctionList(FileId);
|
||||||
|
|
||||||
// Check that the memsets are valid.
|
// Check that the memsets are valid.
|
||||||
// The 'memset' function can do dangerous things if used wrong.
|
// The 'memset' function can do dangerous things if used wrong.
|
||||||
// Important: The checking doesn't work on simplified tokens list.
|
// Important: The checking doesn't work on simplified tokens list.
|
||||||
CheckClass checkClass( &tokenizer );
|
CheckClass checkClass( &_tokenizer );
|
||||||
checkClass.CheckMemset();
|
checkClass.CheckMemset();
|
||||||
|
|
||||||
|
|
||||||
// Check for unsigned divisions where one operand is signed
|
// Check for unsigned divisions where one operand is signed
|
||||||
// Very important to run it before 'SimplifyTokenList'
|
// Very important to run it before 'SimplifyTokenList'
|
||||||
CheckOther checkOther( &tokenizer );
|
CheckOther checkOther( &_tokenizer );
|
||||||
checkOther.CheckUnsignedDivision();
|
checkOther.CheckUnsignedDivision();
|
||||||
|
|
||||||
// Give warning when using char variable as array index
|
// Give warning when using char variable as array index
|
||||||
|
@ -229,14 +229,14 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
tokenizer.SimplifyTokenList();
|
_tokenizer.SimplifyTokenList();
|
||||||
|
|
||||||
// Memory leak
|
// Memory leak
|
||||||
CheckMemoryLeakClass checkMemoryLeak( &tokenizer );
|
CheckMemoryLeakClass checkMemoryLeak( &_tokenizer );
|
||||||
checkMemoryLeak.CheckMemoryLeak();
|
checkMemoryLeak.CheckMemoryLeak();
|
||||||
|
|
||||||
// Buffer overruns..
|
// Buffer overruns..
|
||||||
CheckBufferOverrunClass checkBufferOverrun( &tokenizer );
|
CheckBufferOverrunClass checkBufferOverrun( &_tokenizer );
|
||||||
checkBufferOverrun.CheckBufferOverrun();
|
checkBufferOverrun.CheckBufferOverrun();
|
||||||
|
|
||||||
// Check that all class constructors are ok.
|
// Check that all class constructors are ok.
|
||||||
|
@ -303,7 +303,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up tokens..
|
// Clean up tokens..
|
||||||
tokenizer.DeallocateTokens();
|
_tokenizer.DeallocateTokens();
|
||||||
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "tokenize.h" // <- Tokenizer
|
||||||
/**
|
/**
|
||||||
* This is the base class which will use other classes to do
|
* This is the base class which will use other classes to do
|
||||||
* static code analysis for C and C++ code to find possible
|
* static code analysis for C and C++ code to find possible
|
||||||
|
@ -37,6 +37,7 @@ class CppCheck
|
||||||
private:
|
private:
|
||||||
void checkFile(const std::string &code, const char FileName[], unsigned int FileId);
|
void checkFile(const std::string &code, const char FileName[], unsigned int FileId);
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
|
Tokenizer _tokenizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPPCHECK_H
|
#endif // CPPCHECK_H
|
||||||
|
|
|
@ -45,7 +45,10 @@ private:
|
||||||
tokenizer.SimplifyTokenList();
|
tokenizer.SimplifyTokenList();
|
||||||
|
|
||||||
// Fill function list
|
// Fill function list
|
||||||
FillFunctionList(0);
|
Settings settings;
|
||||||
|
settings._checkCodingStyle = true;
|
||||||
|
tokenizer.settings( settings );
|
||||||
|
tokenizer.FillFunctionList(0);
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
|
@ -50,7 +50,10 @@ private:
|
||||||
tokenizer.TokenizeCode( istr );
|
tokenizer.TokenizeCode( istr );
|
||||||
|
|
||||||
// Fill function list
|
// Fill function list
|
||||||
FillFunctionList(0);
|
Settings settings;
|
||||||
|
settings._checkCodingStyle = true;
|
||||||
|
tokenizer.settings( settings );
|
||||||
|
tokenizer.FillFunctionList(0);
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
|
@ -50,7 +50,10 @@ private:
|
||||||
|
|
||||||
// Check for memory leaks..
|
// Check for memory leaks..
|
||||||
ShowAll = false;
|
ShowAll = false;
|
||||||
FillFunctionList(0);
|
Settings settings;
|
||||||
|
settings._checkCodingStyle = true;
|
||||||
|
tokenizer.settings( settings );
|
||||||
|
tokenizer.FillFunctionList(0);
|
||||||
CheckMemoryLeakClass checkMemoryLeak( &tokenizer );
|
CheckMemoryLeakClass checkMemoryLeak( &tokenizer );
|
||||||
checkMemoryLeak.CheckMemoryLeak();
|
checkMemoryLeak.CheckMemoryLeak();
|
||||||
|
|
||||||
|
|
189
tokenize.cpp
189
tokenize.cpp
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <stdlib.h> // <- strtoul
|
#include <stdlib.h> // <- strtoul
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -1115,8 +1116,196 @@ void Tokenizer::DeallocateTokens()
|
||||||
delete dsymlist;
|
delete dsymlist;
|
||||||
dsymlist = next;
|
dsymlist = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Files.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const TOKEN *Tokenizer::GetFunctionTokenByName( const char funcname[] ) const
|
||||||
|
{
|
||||||
|
std::list<const TOKEN *>::const_iterator it;
|
||||||
|
for ( it = FunctionList.begin(); it != FunctionList.end(); it++ )
|
||||||
|
{
|
||||||
|
if ( strcmp( (*it)->str, funcname ) == 0 )
|
||||||
|
{
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Tokenizer::FillFunctionList(const unsigned int file_id)
|
||||||
|
{
|
||||||
|
FunctionList.clear();
|
||||||
|
|
||||||
|
std::list<const char *> _usedfunc;
|
||||||
|
if ( file_id == 0 )
|
||||||
|
{
|
||||||
|
GlobalFunctions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool staticfunc = false;
|
||||||
|
bool classfunc = false;
|
||||||
|
|
||||||
|
int indentlevel = 0;
|
||||||
|
for ( const TOKEN *tok = tokens; tok; tok = tok->next )
|
||||||
|
{
|
||||||
|
if ( tok->str[0] == '{' )
|
||||||
|
indentlevel++;
|
||||||
|
|
||||||
|
else if ( tok->str[0] == '}' )
|
||||||
|
indentlevel--;
|
||||||
|
|
||||||
|
|
||||||
|
if (indentlevel > 0)
|
||||||
|
{
|
||||||
|
if ( _settings._checkCodingStyle )
|
||||||
|
{
|
||||||
|
const char *funcname = 0;
|
||||||
|
|
||||||
|
if ( Match(tok,"%var% (") )
|
||||||
|
funcname = tok->str;
|
||||||
|
else if ( Match(tok, "= %var% ;") ||
|
||||||
|
Match(tok, "= %var% ,") )
|
||||||
|
funcname = tok->next->str;
|
||||||
|
|
||||||
|
if ( std::find(_usedfunc.begin(), _usedfunc.end(), funcname) == _usedfunc.end() )
|
||||||
|
_usedfunc.push_back( funcname );
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr("};", tok->str[0]))
|
||||||
|
staticfunc = classfunc = false;
|
||||||
|
|
||||||
|
else if ( strcmp( tok->str, "static" ) == 0 )
|
||||||
|
staticfunc = true;
|
||||||
|
|
||||||
|
else if ( strcmp( tok->str, "::" ) == 0 )
|
||||||
|
classfunc = true;
|
||||||
|
|
||||||
|
else if (Match(tok, "%var% ("))
|
||||||
|
{
|
||||||
|
// Check if this is the first token of a function implementation..
|
||||||
|
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
|
||||||
|
{
|
||||||
|
if ( tok2->str[0] == ';' )
|
||||||
|
{
|
||||||
|
tok = tok2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( tok2->str[0] == '{' )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( tok2->str[0] == ')' )
|
||||||
|
{
|
||||||
|
if ( Match(tok2, ") {") )
|
||||||
|
{
|
||||||
|
if (_settings._checkCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0)
|
||||||
|
GlobalFunctions.push_back( GlobalFunction(file_id, tok->str) );
|
||||||
|
FunctionList.push_back( tok );
|
||||||
|
tok = tok2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tok = tok2;
|
||||||
|
while (tok->next && !strchr(";{", tok->next->str[0]))
|
||||||
|
tok = tok->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::list<const char *>::const_iterator it = _usedfunc.begin(); it != _usedfunc.end(); ++it)
|
||||||
|
{
|
||||||
|
if ( *it != 0 )
|
||||||
|
{
|
||||||
|
UsedGlobalFunctions.push_back( GlobalFunction(file_id, *it) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void Tokenizer::CheckGlobalFunctionUsage(const std::vector<std::string> &filenames)
|
||||||
|
{
|
||||||
|
// Iterator for GlobalFunctions
|
||||||
|
std::list<GlobalFunction>::const_iterator func;
|
||||||
|
|
||||||
|
// Iterator for UsedGlobalFunctions
|
||||||
|
std::list<GlobalFunction>::const_iterator usedfunc;
|
||||||
|
|
||||||
|
unsigned int i1 = 0;
|
||||||
|
unsigned int i2 = 1;
|
||||||
|
|
||||||
|
// Check that every function in GlobalFunctions are used
|
||||||
|
for ( func = GlobalFunctions.begin(); func != GlobalFunctions.end(); func++ )
|
||||||
|
{
|
||||||
|
if ( GlobalFunctions.size() > 100 )
|
||||||
|
{
|
||||||
|
++i1;
|
||||||
|
if ( i1 > (i2 * GlobalFunctions.size()) / 100 )
|
||||||
|
{
|
||||||
|
if ( (i2 % 10) == 0 )
|
||||||
|
std::cout << i2 << "%";
|
||||||
|
else
|
||||||
|
std::cout << ".";
|
||||||
|
std::cout.flush();
|
||||||
|
++i2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &funcname = func->name();
|
||||||
|
|
||||||
|
if ( funcname == "main" || funcname == "WinMain" )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if this global function is used in any of the other files..
|
||||||
|
bool UsedOtherFile = false;
|
||||||
|
bool UsedAnyFile = false;
|
||||||
|
for ( usedfunc = UsedGlobalFunctions.begin(); usedfunc != UsedGlobalFunctions.end(); usedfunc++ )
|
||||||
|
{
|
||||||
|
if ( funcname == usedfunc->name() )
|
||||||
|
{
|
||||||
|
UsedAnyFile = true;
|
||||||
|
if (func->file_id() != usedfunc->file_id())
|
||||||
|
{
|
||||||
|
UsedOtherFile = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! UsedAnyFile )
|
||||||
|
{
|
||||||
|
std::ostringstream errmsg;
|
||||||
|
errmsg << "[" << filenames[func->file_id()] << "]: "
|
||||||
|
<< "The function '" << func->name() << "' is never used.";
|
||||||
|
ReportErr( errmsg.str() );
|
||||||
|
}
|
||||||
|
else if ( ! UsedOtherFile )
|
||||||
|
{
|
||||||
|
std::ostringstream errmsg;
|
||||||
|
errmsg << "[" << filenames[func->file_id()] << "]: "
|
||||||
|
<< "The linkage of the function '" << func->name() << "' can be local (static) instead of global";
|
||||||
|
ReportErr( errmsg.str() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Tokenizer::settings( const Settings &settings )
|
||||||
|
{
|
||||||
|
_settings = settings;
|
||||||
|
}
|
||||||
|
|
33
tokenize.h
33
tokenize.h
|
@ -21,12 +21,13 @@
|
||||||
#ifndef tokenizeH
|
#ifndef tokenizeH
|
||||||
#define tokenizeH
|
#define tokenizeH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
class TOKEN
|
class TOKEN
|
||||||
{
|
{
|
||||||
|
@ -89,10 +90,33 @@ public:
|
||||||
|
|
||||||
std::vector<std::string> *getFiles();
|
std::vector<std::string> *getFiles();
|
||||||
|
|
||||||
std::vector<std::string> Files;
|
|
||||||
|
|
||||||
|
|
||||||
|
void FillFunctionList(const unsigned int file_id);
|
||||||
|
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
|
||||||
|
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
||||||
|
void settings( const Settings &settings );
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalFunction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned int _FileId;
|
||||||
|
std::string _FuncName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlobalFunction( const unsigned int FileId, const char FuncName[] )
|
||||||
|
{
|
||||||
|
_FileId = FileId;
|
||||||
|
_FuncName = FuncName;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int file_id() const { return _FileId; }
|
||||||
|
const std::string &name() const { return _FuncName; }
|
||||||
|
};
|
||||||
|
|
||||||
void Define(const char Name[], const char Value[]);
|
void Define(const char Name[], const char Value[]);
|
||||||
|
|
||||||
void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
||||||
|
@ -107,6 +131,11 @@ private:
|
||||||
|
|
||||||
TOKEN *tokens_back;
|
TOKEN *tokens_back;
|
||||||
std::map<std::string, unsigned int> TypeSize;
|
std::map<std::string, unsigned int> TypeSize;
|
||||||
|
std::list<const TOKEN *> FunctionList;
|
||||||
|
std::list< GlobalFunction > GlobalFunctions;
|
||||||
|
std::list< GlobalFunction > UsedGlobalFunctions;
|
||||||
|
std::vector<std::string> Files;
|
||||||
|
Settings _settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue