Check Function Usage: Removed much of the old checking and made some refactoring
This commit is contained in:
parent
6687bc7b9a
commit
07b5ebe72b
31
cppcheck.cpp
31
cppcheck.cpp
|
@ -18,6 +18,7 @@
|
|||
#include "cppcheck.h"
|
||||
|
||||
#include "preprocessor.h" // preprocessor.
|
||||
#include "tokenize.h" // <- Tokenizer
|
||||
|
||||
#include "CheckMemoryLeak.h"
|
||||
#include "CheckBufferOverrun.h"
|
||||
|
@ -35,12 +36,9 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CppCheck::CppCheck() : _tokenizer( this )
|
||||
CppCheck::CppCheck()
|
||||
{
|
||||
_settings._debug = false;
|
||||
_settings._showAll = false;
|
||||
_settings._checkCodingStyle = false;
|
||||
_settings._errorsOnly = false;
|
||||
|
||||
}
|
||||
|
||||
CppCheck::~CppCheck()
|
||||
|
@ -53,6 +51,8 @@ void CppCheck::check(int argc, char* argv[])
|
|||
std::vector<std::string> pathnames;
|
||||
bool Recursive = false;
|
||||
|
||||
Settings _settings;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--debug") == 0)
|
||||
|
@ -76,8 +76,6 @@ void CppCheck::check(int argc, char* argv[])
|
|||
pathnames.push_back( argv[i] );
|
||||
}
|
||||
|
||||
_tokenizer.settings( _settings );
|
||||
|
||||
std::vector<std::string> filenames;
|
||||
// --recursive was used
|
||||
if ( Recursive )
|
||||
|
@ -140,7 +138,7 @@ void CppCheck::check(int argc, char* argv[])
|
|||
Preprocessor preprocessor( this );
|
||||
preprocessor.preprocess(fin, code, fname);
|
||||
for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
|
||||
checkFile(it->second, filenames[c].c_str(), c);
|
||||
checkFile(it->second, filenames[c].c_str(), c, _settings);
|
||||
|
||||
if (_settings._errorsOnly)
|
||||
{
|
||||
|
@ -164,7 +162,7 @@ void CppCheck::check(int argc, char* argv[])
|
|||
{
|
||||
errout.str("");
|
||||
std::cout << "Checking usage of global functions (this may take several minutes)..\n";
|
||||
_tokenizer.CheckGlobalFunctionUsage(filenames);
|
||||
//_tokenizer.CheckGlobalFunctionUsage(filenames);
|
||||
if ( ! errout.str().empty() )
|
||||
{
|
||||
std::cerr << "\n";
|
||||
|
@ -179,8 +177,11 @@ void CppCheck::check(int argc, char* argv[])
|
|||
// CppCheck - A function that checks a specified file
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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, Settings &_settings)
|
||||
{
|
||||
Tokenizer _tokenizer;
|
||||
_tokenizer.settings( _settings );
|
||||
|
||||
// Tokenize the file
|
||||
{
|
||||
std::istringstream istr(code);
|
||||
|
@ -288,10 +289,6 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne
|
|||
// mean that an ';' has been added by accident
|
||||
checkOther.CheckIncompleteStatement();
|
||||
}
|
||||
|
||||
// Clean up tokens..
|
||||
_tokenizer.DeallocateTokens();
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -308,6 +305,12 @@ void CppCheck::reportErr( const std::string &errmsg)
|
|||
|
||||
void CppCheck::reportErr( const TOKEN *token, const std::string &errmsg)
|
||||
{
|
||||
/*
|
||||
std::string message = _tokenizer.fileLine( token ) + errmsg;
|
||||
reportErr( message );
|
||||
*/
|
||||
reportErr( errmsg );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
11
cppcheck.h
11
cppcheck.h
|
@ -23,7 +23,6 @@
|
|||
#include <list>
|
||||
#include <sstream>
|
||||
#include "settings.h"
|
||||
#include "tokenize.h" // <- Tokenizer
|
||||
#include "errorlogger.h"
|
||||
|
||||
/**
|
||||
|
@ -38,15 +37,13 @@ class CppCheck : public ErrorLogger
|
|||
virtual ~CppCheck();
|
||||
void check(int argc, char* argv[]);
|
||||
|
||||
virtual void reportErr( const TOKEN *token, const std::string &errmsg);
|
||||
virtual void reportErr( const std::string &errmsg);
|
||||
|
||||
private:
|
||||
void checkFile(const std::string &code, const char FileName[], unsigned int FileId);
|
||||
Settings _settings;
|
||||
Tokenizer _tokenizer;
|
||||
void checkFile(const std::string &code, const char FileName[], unsigned int FileId, Settings &_settings);
|
||||
std::list<std::string> _errorList;
|
||||
std::ostringstream errout;
|
||||
|
||||
void reportErr( const std::string &errmsg);
|
||||
void reportErr( const TOKEN *token, const std::string &errmsg);
|
||||
};
|
||||
|
||||
#endif // CPPCHECK_H
|
||||
|
|
|
@ -39,7 +39,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -43,7 +43,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -37,7 +37,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -39,7 +39,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -38,7 +38,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -37,7 +37,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
<Unit filename="CheckBufferOverrun.h" />
|
||||
<Unit filename="CheckClass.cpp" />
|
||||
<Unit filename="CheckClass.h" />
|
||||
<Unit filename="CheckFunctionUsage.cpp" />
|
||||
<Unit filename="CheckFunctionUsage.h" />
|
||||
<Unit filename="CheckHeaders.cpp" />
|
||||
<Unit filename="CheckHeaders.h" />
|
||||
<Unit filename="CheckMemoryLeak.cpp" />
|
||||
|
@ -35,6 +37,7 @@
|
|||
<Unit filename="FileLister.h" />
|
||||
<Unit filename="cppcheck.cpp" />
|
||||
<Unit filename="cppcheck.h" />
|
||||
<Unit filename="errorlogger.h" />
|
||||
<Unit filename="preprocessor.cpp" />
|
||||
<Unit filename="preprocessor.h" />
|
||||
<Unit filename="settings.cpp" />
|
||||
|
|
|
@ -42,7 +42,7 @@ private:
|
|||
std::string tok(const char code[])
|
||||
{
|
||||
std::istringstream istr(code);
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.TokenizeCode( istr );
|
||||
tokenizer.SimplifyTokenList();
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ private:
|
|||
" \"def\"\n";
|
||||
|
||||
// tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(filedata);
|
||||
tokenizer.TokenizeCode(istr, 0);
|
||||
|
@ -89,7 +89,7 @@ private:
|
|||
std::string filedata(10000,'a');
|
||||
|
||||
// tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(filedata);
|
||||
tokenizer.TokenizeCode(istr, 0);
|
||||
|
@ -111,7 +111,7 @@ private:
|
|||
"}\n";
|
||||
|
||||
// tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(filedata);
|
||||
tokenizer.TokenizeCode(istr, 0);
|
||||
|
@ -142,7 +142,7 @@ private:
|
|||
"void b()\n"
|
||||
"{ }\n";
|
||||
// tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode(istr, 0);
|
||||
|
|
|
@ -44,7 +44,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
|
@ -37,7 +37,7 @@ private:
|
|||
void check( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer( this );
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode( istr );
|
||||
|
|
105
tokenize.cpp
105
tokenize.cpp
|
@ -48,12 +48,11 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
Tokenizer::Tokenizer(ErrorLogger *errorLogger)
|
||||
Tokenizer::Tokenizer()
|
||||
{
|
||||
_tokens = 0;
|
||||
tokens_back = 0;
|
||||
dsymlist = 0;
|
||||
_errorLogger = errorLogger;
|
||||
}
|
||||
|
||||
Tokenizer::~Tokenizer()
|
||||
|
@ -1155,12 +1154,6 @@ 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;
|
||||
|
||||
|
@ -1173,23 +1166,8 @@ void Tokenizer::FillFunctionList(const unsigned int file_id)
|
|||
else if ( tok->str[0] == '}' )
|
||||
indentlevel--;
|
||||
|
||||
|
||||
if (indentlevel > 0)
|
||||
{
|
||||
if ( _settings._checkCodingStyle )
|
||||
{
|
||||
const char *funcname = 0;
|
||||
|
||||
if ( Tokenizer::Match(tok,"%var% (") )
|
||||
funcname = tok->str;
|
||||
else if ( Tokenizer::Match(tok, "= %var% ;") ||
|
||||
Tokenizer::Match(tok, "= %var% ,") )
|
||||
funcname = tok->next->str;
|
||||
|
||||
if ( std::find(_usedfunc.begin(), _usedfunc.end(), funcname) == _usedfunc.end() )
|
||||
_usedfunc.push_back( funcname );
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1222,8 +1200,6 @@ void Tokenizer::FillFunctionList(const unsigned int file_id)
|
|||
{
|
||||
if ( Tokenizer::Match(tok2, ") {") )
|
||||
{
|
||||
if (_settings._checkCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0)
|
||||
GlobalFunctions.push_back( GlobalFunction(file_id, tok->str) );
|
||||
FunctionList.push_back( tok );
|
||||
tok = tok2;
|
||||
}
|
||||
|
@ -1266,87 +1242,8 @@ void Tokenizer::FillFunctionList(const unsigned int file_id)
|
|||
FunctionList.erase( FunctionList.begin() + func1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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.";
|
||||
_errorLogger->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";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n";
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void Tokenizer::settings( const Settings &settings )
|
||||
|
|
37
tokenize.h
37
tokenize.h
|
@ -61,16 +61,17 @@ public:
|
|||
};
|
||||
|
||||
class Tokenizer
|
||||
{
|
||||
{
|
||||
private:
|
||||
// Deallocate lists..
|
||||
void DeallocateTokens();
|
||||
|
||||
public:
|
||||
Tokenizer(ErrorLogger *errorLogger);
|
||||
Tokenizer();
|
||||
~Tokenizer();
|
||||
|
||||
void Tokenize(std::istream &code, const char FileName[]);
|
||||
|
||||
// Deallocate lists..
|
||||
void DeallocateTokens();
|
||||
|
||||
// Simplify tokenlist
|
||||
// -----------------------------
|
||||
void SimplifyTokenList();
|
||||
|
@ -99,16 +100,12 @@ public:
|
|||
|
||||
std::vector<std::string> *getFiles();
|
||||
|
||||
|
||||
|
||||
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 );
|
||||
const TOKEN *tokens() const;
|
||||
|
||||
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
|
@ -120,23 +117,6 @@ private:
|
|||
struct DefineSymbol *next;
|
||||
};
|
||||
|
||||
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 addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
||||
|
@ -154,15 +134,12 @@ private:
|
|||
TOKEN *tokens_back;
|
||||
std::map<std::string, unsigned int> TypeSize;
|
||||
std::vector<const TOKEN *> FunctionList;
|
||||
std::list< GlobalFunction > GlobalFunctions;
|
||||
std::list< GlobalFunction > UsedGlobalFunctions;
|
||||
std::vector<std::string> Files;
|
||||
Settings _settings;
|
||||
|
||||
|
||||
struct DefineSymbol * dsymlist;
|
||||
TOKEN *_tokens;
|
||||
ErrorLogger *_errorLogger;
|
||||
TOKEN *_tokens;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue