Refactoring: The Tokenizer::FillFunctionList has no use of its parameter. Enabled the CheckFunctionUsage

This commit is contained in:
Daniel Marjamäki 2008-11-23 06:21:44 +00:00
parent b8c7543149
commit 0c9784fc0c
12 changed files with 179 additions and 171 deletions

View File

@ -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() );
*/
}
}
}

View File

@ -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;
};

View File

@ -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();

View File

@ -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;

View File

@ -49,7 +49,7 @@ private:
Settings settings;
settings._checkCodingStyle = true;
tokenizer.settings( settings );
tokenizer.FillFunctionList(0);
tokenizer.FillFunctionList();
// Clear the error buffer..
errout.str("");

View File

@ -53,7 +53,7 @@ private:
Settings settings;
settings._checkCodingStyle = true;
tokenizer.settings( settings );
tokenizer.FillFunctionList(0);
tokenizer.FillFunctionList();
// Clear the error buffer..
errout.str("");

View File

@ -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();
}

View File

@ -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>

View File

@ -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 );
}

View File

@ -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 );

View File

@ -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();

View File

@ -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;