Refactoring: The Tokenizer::FillFunctionList has no use of its parameter. Enabled the CheckFunctionUsage
This commit is contained in:
parent
b8c7543149
commit
0c9784fc0c
|
@ -19,7 +19,7 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
#include "CheckFunctionUsage.h"
|
||||
#include "tokenize.h"
|
||||
#include "tokenize.h"
|
||||
#include <sstream>
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -29,102 +29,109 @@
|
|||
//---------------------------------------------------------------------------
|
||||
// FUNCTION USAGE - Check for unused functions etc
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckFunctionUsage::CheckFunctionUsage( const Tokenizer *tokenizer, ErrorLogger *errorLogger )
|
||||
{
|
||||
_tokenizer = tokenizer;
|
||||
_errorLogger = errorLogger;
|
||||
functions.clear();
|
||||
}
|
||||
|
||||
CheckFunctionUsage::~CheckFunctionUsage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CheckFunctionUsage::parseTokens( const std::string &filename )
|
||||
{
|
||||
// Function declarations..
|
||||
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next )
|
||||
{
|
||||
if ( tok->FileIndex != 0 )
|
||||
continue;
|
||||
|
||||
const TOKEN *funcname = 0;
|
||||
|
||||
if ( TOKEN::Match( tok, "%type% %var% (" ) )
|
||||
funcname = tok->at(1);
|
||||
else if ( TOKEN::Match(tok, "%type% * %var% (") )
|
||||
funcname = tok->at(2);
|
||||
|
||||
if ( TOKEN::Match(funcname, "%var% ( )") || TOKEN::Match(funcname, "%var% ( %type%") )
|
||||
{
|
||||
FunctionUsage &func = functions[ funcname->str ];
|
||||
|
||||
// No filename set yet..
|
||||
if (func.filename.empty())
|
||||
func.filename = filename;
|
||||
|
||||
// Multiple files => filename = "+"
|
||||
else if (func.filename != filename)
|
||||
{
|
||||
func.filename = "+";
|
||||
func.usedOtherFile |= func.usedSameFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function usage..
|
||||
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next )
|
||||
{
|
||||
const TOKEN *funcname = 0;
|
||||
|
||||
if ( TOKEN::Match( tok, "[;{}.)[=] %var% (" ) )
|
||||
funcname = tok;
|
||||
|
||||
else if ( TOKEN::Match(tok, "= %var% ;") )
|
||||
funcname = tok->next;
|
||||
|
||||
if ( funcname )
|
||||
{
|
||||
FunctionUsage &func = functions[ funcname->str ];
|
||||
|
||||
if ( func.filename.empty() || func.filename == "+" )
|
||||
func.usedOtherFile = true;
|
||||
|
||||
else
|
||||
func.usedSameFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CheckFunctionUsage::check()
|
||||
{
|
||||
for ( std::map<std::string, FunctionUsage>::const_iterator it = functions.begin(); it != functions.end(); ++it )
|
||||
{
|
||||
const FunctionUsage &func = it->second;
|
||||
if ( func.usedOtherFile || func.filename.empty() )
|
||||
continue;
|
||||
if ( ! func.usedSameFile )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "The function '" << it->first << "' is never used.";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
}
|
||||
else if ( ! func.usedOtherFile )
|
||||
{
|
||||
/*
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage.";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CheckFunctionUsage::CheckFunctionUsage( ErrorLogger *errorLogger )
|
||||
{
|
||||
_errorLogger = errorLogger;
|
||||
functions.clear();
|
||||
}
|
||||
|
||||
CheckFunctionUsage::~CheckFunctionUsage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
||||
{
|
||||
// Function declarations..
|
||||
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next )
|
||||
{
|
||||
if ( tok->FileIndex != 0 )
|
||||
continue;
|
||||
|
||||
const TOKEN *funcname = 0;
|
||||
|
||||
if ( TOKEN::Match( tok, "%type% %var% (" ) )
|
||||
funcname = tok->at(1);
|
||||
else if ( TOKEN::Match(tok, "%type% * %var% (") )
|
||||
funcname = tok->at(2);
|
||||
|
||||
// Check that ") {" is found..
|
||||
for (const TOKEN *tok2 = funcname; tok2; tok2 = tok2->next)
|
||||
{
|
||||
if ( TOKEN::Match(tok2, ")") )
|
||||
{
|
||||
if ( ! TOKEN::Match(tok2, ") {") )
|
||||
funcname = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( TOKEN::Match(funcname, "%var% ( )") || TOKEN::Match(funcname, "%var% ( %type%") )
|
||||
{
|
||||
FunctionUsage &func = functions[ funcname->str ];
|
||||
|
||||
// No filename set yet..
|
||||
if (func.filename.empty())
|
||||
func.filename = tokenizer.getFiles()->at(0);
|
||||
|
||||
// Multiple files => filename = "+"
|
||||
else if (func.filename != tokenizer.getFiles()->at(0))
|
||||
{
|
||||
func.filename = "+";
|
||||
func.usedOtherFile |= func.usedSameFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function usage..
|
||||
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next )
|
||||
{
|
||||
const TOKEN *funcname = 0;
|
||||
|
||||
if ( TOKEN::Match( tok, "[;{}.,()[=] %var% [(),;]" ) )
|
||||
funcname = tok->next;
|
||||
|
||||
if ( funcname )
|
||||
{
|
||||
FunctionUsage &func = functions[ funcname->str ];
|
||||
|
||||
if ( func.filename.empty() || func.filename == "+" )
|
||||
func.usedOtherFile = true;
|
||||
|
||||
else
|
||||
func.usedSameFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CheckFunctionUsage::check()
|
||||
{
|
||||
for ( std::map<std::string, FunctionUsage>::const_iterator it = functions.begin(); it != functions.end(); ++it )
|
||||
{
|
||||
const FunctionUsage &func = it->second;
|
||||
if ( func.usedOtherFile || func.filename.empty() )
|
||||
continue;
|
||||
if ( ! func.usedSameFile )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "The function '" << it->first << "' is never used.";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
}
|
||||
else if ( ! func.usedOtherFile )
|
||||
{
|
||||
/*
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage.";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,44 +21,43 @@
|
|||
#ifndef CheckFunctionUsageH
|
||||
#define CheckFunctionUsageH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "tokenize.h"
|
||||
#include "errorlogger.h"
|
||||
|
||||
class CheckFunctionUsage
|
||||
{
|
||||
public:
|
||||
CheckFunctionUsage( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
||||
~CheckFunctionUsage();
|
||||
|
||||
// Parse current tokens and determine..
|
||||
// * Check what functions are used
|
||||
|
||||
#include "tokenize.h"
|
||||
#include "errorlogger.h"
|
||||
|
||||
class CheckFunctionUsage
|
||||
{
|
||||
public:
|
||||
CheckFunctionUsage( ErrorLogger *errorLogger );
|
||||
~CheckFunctionUsage();
|
||||
|
||||
// Parse current tokens and determine..
|
||||
// * Check what functions are used
|
||||
// * What functions are declared
|
||||
void parseTokens( const std::string &filename );
|
||||
|
||||
|
||||
void check();
|
||||
|
||||
private:
|
||||
const Tokenizer *_tokenizer;
|
||||
ErrorLogger *_errorLogger;
|
||||
|
||||
|
||||
class FunctionUsage
|
||||
{
|
||||
public:
|
||||
FunctionUsage()
|
||||
{
|
||||
filename = "";
|
||||
usedOtherFile = false;
|
||||
usedSameFile = false;
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
bool usedSameFile;
|
||||
bool usedOtherFile;
|
||||
};
|
||||
|
||||
void parseTokens( const Tokenizer &tokenizer );
|
||||
|
||||
|
||||
void check();
|
||||
|
||||
private:
|
||||
ErrorLogger *_errorLogger;
|
||||
|
||||
|
||||
class FunctionUsage
|
||||
{
|
||||
public:
|
||||
FunctionUsage()
|
||||
{
|
||||
filename = "";
|
||||
usedOtherFile = false;
|
||||
usedSameFile = false;
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
bool usedSameFile;
|
||||
bool usedOtherFile;
|
||||
};
|
||||
|
||||
std::map<std::string, FunctionUsage> functions;
|
||||
};
|
||||
|
||||
|
|
21
cppcheck.cpp
21
cppcheck.cpp
|
@ -25,6 +25,7 @@
|
|||
#include "CheckClass.h"
|
||||
#include "CheckHeaders.h"
|
||||
#include "CheckOther.h"
|
||||
#include "CheckFunctionUsage.h"
|
||||
#include "FileLister.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -124,6 +125,11 @@ void CppCheck::check(int argc, char* argv[])
|
|||
|
||||
std::sort( filenames.begin(), filenames.end() );
|
||||
|
||||
// Check function usage if "--recursive", "--style" and "--all" was given.
|
||||
CheckFunctionUsage *checkFunctionUsage = NULL;
|
||||
if ( Recursive && _settings._showAll && _settings._checkCodingStyle )
|
||||
checkFunctionUsage = new CheckFunctionUsage( this );
|
||||
|
||||
for (unsigned int c = 0; c < filenames.size(); c++)
|
||||
{
|
||||
errout.str("");
|
||||
|
@ -138,7 +144,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, _settings);
|
||||
checkFile(it->second, filenames[c].c_str(), _settings, checkFunctionUsage);
|
||||
|
||||
if (_settings._errorsOnly)
|
||||
{
|
||||
|
@ -158,11 +164,11 @@ void CppCheck::check(int argc, char* argv[])
|
|||
}
|
||||
|
||||
// This generates false positives - especially for libraries
|
||||
if ( _settings._showAll && _settings._checkCodingStyle && filenames.size() > 1 )
|
||||
if ( checkFunctionUsage )
|
||||
{
|
||||
errout.str("");
|
||||
std::cout << "Checking usage of global functions (this may take several minutes)..\n";
|
||||
//_tokenizer.CheckGlobalFunctionUsage(filenames);
|
||||
checkFunctionUsage->check();
|
||||
if ( ! errout.str().empty() )
|
||||
{
|
||||
std::cerr << "\n";
|
||||
|
@ -170,6 +176,7 @@ void CppCheck::check(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
delete checkFunctionUsage;
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,7 +184,7 @@ 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, Settings &_settings)
|
||||
void CppCheck::checkFile(const std::string &code, const char FileName[], Settings &_settings, CheckFunctionUsage *checkFunctionUsage)
|
||||
{
|
||||
Tokenizer _tokenizer;
|
||||
_tokenizer.settings( _settings );
|
||||
|
@ -188,7 +195,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne
|
|||
_tokenizer.Tokenize(istr, FileName);
|
||||
}
|
||||
|
||||
_tokenizer.FillFunctionList(FileId);
|
||||
_tokenizer.FillFunctionList();
|
||||
|
||||
// Check that the memsets are valid.
|
||||
// The 'memset' function can do dangerous things if used wrong.
|
||||
|
@ -219,6 +226,10 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne
|
|||
|
||||
_tokenizer.SimplifyTokenList();
|
||||
|
||||
|
||||
if ( checkFunctionUsage )
|
||||
checkFunctionUsage->parseTokens(_tokenizer);
|
||||
|
||||
// Memory leak
|
||||
CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this );
|
||||
checkMemoryLeak.CheckMemoryLeak();
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "settings.h"
|
||||
#include "errorlogger.h"
|
||||
|
||||
class CheckFunctionUsage;
|
||||
|
||||
/**
|
||||
* This is the base class which will use other classes to do
|
||||
* static code analysis for C and C++ code to find possible
|
||||
|
@ -38,7 +40,7 @@ class CppCheck : public ErrorLogger
|
|||
void check(int argc, char* argv[]);
|
||||
|
||||
private:
|
||||
void checkFile(const std::string &code, const char FileName[], unsigned int FileId, Settings &_settings);
|
||||
void checkFile(const std::string &code, const char FileName[], Settings &_settings, CheckFunctionUsage *checkFunctionUsage);
|
||||
std::list<std::string> _errorList;
|
||||
std::ostringstream errout;
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ private:
|
|||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
tokenizer.settings( settings );
|
||||
tokenizer.FillFunctionList(0);
|
||||
tokenizer.FillFunctionList();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
|
|
@ -53,7 +53,7 @@ private:
|
|||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
tokenizer.settings( settings );
|
||||
tokenizer.FillFunctionList(0);
|
||||
tokenizer.FillFunctionList();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
|
|
@ -52,7 +52,7 @@ private:
|
|||
settings._checkCodingStyle = true;
|
||||
settings._showAll = false;
|
||||
tokenizer.settings( settings );
|
||||
tokenizer.FillFunctionList(0);
|
||||
tokenizer.FillFunctionList();
|
||||
CheckMemoryLeakClass checkMemoryLeak( &tokenizer, settings, this );
|
||||
checkMemoryLeak.CheckMemoryLeak();
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
<Unit filename="CheckMemoryLeak.h" />
|
||||
<Unit filename="CheckOther.cpp" />
|
||||
<Unit filename="CheckOther.h" />
|
||||
<Unit filename="CommonCheck.cpp" />
|
||||
<Unit filename="CommonCheck.h" />
|
||||
<Unit filename="FileLister.cpp" />
|
||||
<Unit filename="FileLister.h" />
|
||||
<Unit filename="cppcheck.cpp" />
|
||||
|
@ -56,6 +54,8 @@
|
|||
<Unit filename="testtokenize.cpp" />
|
||||
<Unit filename="testunusedprivfunc.cpp" />
|
||||
<Unit filename="testunusedvar.cpp" />
|
||||
<Unit filename="token.cpp" />
|
||||
<Unit filename="token.h" />
|
||||
<Unit filename="tokenize.cpp" />
|
||||
<Unit filename="tokenize.h" />
|
||||
<Extensions>
|
||||
|
|
|
@ -48,11 +48,6 @@ public:
|
|||
_tests.push_back( t );
|
||||
}
|
||||
|
||||
void removeTest( TestFixture *t )
|
||||
{
|
||||
_tests.remove( t );
|
||||
}
|
||||
|
||||
const std::list<TestFixture *> &tests() const
|
||||
{
|
||||
return _tests;
|
||||
|
@ -74,12 +69,6 @@ TestFixture::TestFixture(const std::string &_name) : classname(_name)
|
|||
TestRegistry::theInstance().addTest(this);
|
||||
}
|
||||
|
||||
/*
|
||||
TestFixture::~TestFixture()
|
||||
{
|
||||
TestRegistry::theInstance().removeTest(this);
|
||||
}
|
||||
*/
|
||||
|
||||
bool TestFixture::runTest(const char testname[])
|
||||
{
|
||||
|
@ -130,13 +119,13 @@ void TestFixture::runTests(const char cmd[])
|
|||
}
|
||||
|
||||
|
||||
void TestFixture::reportErr( const std::string &errmsg)
|
||||
{
|
||||
errout << errmsg << std::endl;
|
||||
}
|
||||
|
||||
void TestFixture::reportErr( const TOKEN *token, const std::string &errmsg)
|
||||
{
|
||||
reportErr( errmsg );
|
||||
}
|
||||
void TestFixture::reportErr( const std::string &errmsg)
|
||||
{
|
||||
errout << errmsg << std::endl;
|
||||
}
|
||||
|
||||
void TestFixture::reportErr( const TOKEN *token, const std::string &errmsg)
|
||||
{
|
||||
reportErr( errmsg );
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizer.TokenizeCode(istr, 0);
|
||||
|
||||
tokenizer.FillFunctionList(0);
|
||||
tokenizer.FillFunctionList();
|
||||
|
||||
ASSERT_EQUALS( 1, tokenizer.FunctionList.size() );
|
||||
ASSERT_EQUALS( std::string("b"), tokenizer.FunctionList[0]->str );
|
||||
|
|
|
@ -1032,7 +1032,7 @@ const TOKEN *Tokenizer::GetFunctionTokenByName( const char funcname[] ) const
|
|||
}
|
||||
|
||||
|
||||
void Tokenizer::FillFunctionList(const unsigned int file_id)
|
||||
void Tokenizer::FillFunctionList()
|
||||
{
|
||||
FunctionList.clear();
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
const std::vector<std::string> *getFiles() const;
|
||||
|
||||
void FillFunctionList(const unsigned int file_id);
|
||||
void FillFunctionList();
|
||||
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
|
||||
void settings( const Settings &settings );
|
||||
const TOKEN *tokens() const;
|
||||
|
|
Loading…
Reference in New Issue