Added style checks to check for unused global functions
This commit is contained in:
parent
f8569f0db4
commit
69d33444d4
117
CommonCheck.cpp
117
CommonCheck.cpp
|
@ -6,9 +6,31 @@
|
|||
#include <list>
|
||||
#include <algorithm>
|
||||
//---------------------------------------------------------------------------
|
||||
extern bool CheckCodingStyle;
|
||||
bool OnlyReportUniqueErrors;
|
||||
std::ostringstream errout;
|
||||
static std::list<const TOKEN *> FunctionList;
|
||||
|
||||
class clGlobalFunction
|
||||
{
|
||||
private:
|
||||
unsigned int _FileId;
|
||||
std::string _FuncName;
|
||||
|
||||
public:
|
||||
clGlobalFunction( const unsigned int FileId, const char FuncName[] )
|
||||
{
|
||||
_FileId = FileId;
|
||||
_FuncName = FuncName;
|
||||
}
|
||||
|
||||
const unsigned int file_id() const { return _FileId; }
|
||||
const std::string &name() const { return _FuncName; }
|
||||
};
|
||||
|
||||
static std::list< clGlobalFunction > GlobalFunctions;
|
||||
static std::list< clGlobalFunction > UsedGlobalFunctions;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
std::string FileLine(const TOKEN *tok)
|
||||
|
@ -57,10 +79,19 @@ bool IsStandardType(const char str[])
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void FillFunctionList()
|
||||
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 )
|
||||
{
|
||||
|
@ -70,7 +101,35 @@ void FillFunctionList()
|
|||
else if ( tok->str[0] == '}' )
|
||||
indentlevel--;
|
||||
|
||||
else if (indentlevel==0 && Match(tok, "%var% ("))
|
||||
|
||||
if (indentlevel > 0)
|
||||
{
|
||||
if ( CheckCodingStyle )
|
||||
{
|
||||
const char *funcname = 0;
|
||||
|
||||
if ( Match(tok,"%var% (") )
|
||||
funcname = tok->str;
|
||||
else if ( 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 )
|
||||
|
@ -90,6 +149,8 @@ void FillFunctionList()
|
|||
{
|
||||
if ( Match(tok2, ") {") )
|
||||
{
|
||||
if (CheckCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0)
|
||||
GlobalFunctions.push_back( clGlobalFunction(file_id, tok->str) );
|
||||
FunctionList.push_back( tok );
|
||||
tok = tok2;
|
||||
}
|
||||
|
@ -104,6 +165,14 @@ void FillFunctionList()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::list<const char *>::const_iterator it = _usedfunc.begin(); it != _usedfunc.end(); ++it)
|
||||
{
|
||||
if ( *it != 0 )
|
||||
{
|
||||
UsedGlobalFunctions.push_back( clGlobalFunction(file_id, *it) );
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -121,6 +190,50 @@ const TOKEN *GetFunctionTokenByName( const char funcname[] )
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames)
|
||||
{
|
||||
// Iterator for GlobalFunctions
|
||||
std::list<clGlobalFunction>::const_iterator func;
|
||||
|
||||
// Iterator for UsedGlobalFunctions
|
||||
std::list<clGlobalFunction>::const_iterator usedfunc;
|
||||
|
||||
// Check that every function in GlobalFunctions are used
|
||||
for ( func = GlobalFunctions.begin(); func != GlobalFunctions.end(); func++ )
|
||||
{
|
||||
if ( func->name() == "main" )
|
||||
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 ( func->name() == usedfunc->name() )
|
||||
{
|
||||
UsedAnyFile = true;
|
||||
UsedOtherFile |= (func->file_id() != usedfunc->file_id());
|
||||
}
|
||||
}
|
||||
|
||||
std::string file = "[" + filenames[func->file_id()] + "]: ";
|
||||
|
||||
if ( ! UsedAnyFile )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << file << "The function '" << func->name() << "' is never used.";
|
||||
ReportErr( errmsg.str() );
|
||||
}
|
||||
else if ( ! UsedOtherFile )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << file << "The linkage of the function '" << func->name() << "' can be local (static) instead of global";
|
||||
ReportErr( errmsg.str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
|
||||
{
|
||||
if (!tok)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <list>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
struct TOKEN;
|
||||
|
||||
|
@ -22,9 +23,9 @@ bool IsNumber(const char str[]);
|
|||
|
||||
bool IsStandardType(const char str[]);
|
||||
|
||||
void FillFunctionList();
|
||||
void FillFunctionList(const unsigned int file_id);
|
||||
const TOKEN *GetFunctionTokenByName( const char funcname[] );
|
||||
|
||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
||||
|
||||
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ static void AppendStatement(STATEMENT::etype Type, TOKEN *tok, std::string Var="
|
|||
Statements.push_back(NewStatement);
|
||||
}
|
||||
|
||||
TOKEN *GotoNextStatement(TOKEN *tok)
|
||||
static TOKEN *GotoNextStatement(TOKEN *tok)
|
||||
{
|
||||
if (tok && (tok->str[0]=='{' || tok->str[0]=='}'))
|
||||
return tok->next;
|
||||
|
@ -79,7 +79,7 @@ TOKEN *GotoNextStatement(TOKEN *tok)
|
|||
}
|
||||
|
||||
|
||||
void GetVariableName(TOKEN * &Token, std::string &varname)
|
||||
static void GetVariableName(TOKEN * &Token, std::string &varname)
|
||||
{
|
||||
varname = "";
|
||||
|
||||
|
|
19
main.cpp
19
main.cpp
|
@ -25,7 +25,7 @@ bool ShowAll = false;
|
|||
bool CheckCodingStyle = false;
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void CppCheck(const char FileName[]);
|
||||
static void CppCheck(const char FileName[], unsigned int FileId);
|
||||
|
||||
|
||||
static void AddFiles( std::vector<std::string> &filenames, const char path[], const char pattern[] )
|
||||
|
@ -153,10 +153,21 @@ int main(int argc, char* argv[])
|
|||
for (unsigned int c = 0; c < filenames.size(); c++)
|
||||
{
|
||||
errout.str("");
|
||||
CppCheck(filenames[c].c_str());
|
||||
CppCheck(filenames[c].c_str(), c);
|
||||
std::cerr << errout.str();
|
||||
}
|
||||
|
||||
if ( CheckCodingStyle && filenames.size() > 1 )
|
||||
{
|
||||
errout.str("");
|
||||
CheckGlobalFunctionUsage(filenames);
|
||||
if ( ! errout.str().empty() )
|
||||
{
|
||||
std::cerr << "\n";
|
||||
std::cerr << errout.str();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -164,7 +175,7 @@ int main(int argc, char* argv[])
|
|||
// CppCheck - A function that checks a specified file
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void CppCheck(const char FileName[])
|
||||
static void CppCheck(const char FileName[], unsigned int FileId)
|
||||
{
|
||||
OnlyReportUniqueErrors = true;
|
||||
|
||||
|
@ -175,7 +186,7 @@ static void CppCheck(const char FileName[])
|
|||
Files.clear();
|
||||
Tokenize(FileName);
|
||||
|
||||
FillFunctionList();
|
||||
FillFunctionList(FileId);
|
||||
|
||||
// Check that the memsets are valid.
|
||||
// The 'memset' function can do dangerous things if used wrong.
|
||||
|
|
|
@ -86,7 +86,7 @@ static void check(void (chk)(),
|
|||
if ( chk != CheckUnsignedDivision )
|
||||
SimplifyTokenList();
|
||||
|
||||
FillFunctionList();
|
||||
FillFunctionList(0);
|
||||
|
||||
// Check for buffer overruns..
|
||||
errout.str("");
|
||||
|
@ -579,7 +579,7 @@ static void constructors()
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void operator_eq()
|
||||
static void operator_eq()
|
||||
{
|
||||
const char test1[] = "class Fred\n"
|
||||
"{\n"
|
||||
|
|
|
@ -230,7 +230,7 @@ static void DeleteNextToken(TOKEN *tok)
|
|||
// InsertTokens - Copy and insert tokens
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n)
|
||||
static void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
|
@ -1095,3 +1095,6 @@ void DeallocateTokens()
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue