Function list: Remove functions with duplicate names to prevent false positives
This commit is contained in:
parent
2e445b195c
commit
63bc26d662
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
#define UNIT_TESTING // Get access to "private" data in Tokenizer
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
|
|
||||||
class TestTokenizer : public TestFixture
|
class TestTokenizer : public TestFixture
|
||||||
|
@ -38,6 +39,8 @@ private:
|
||||||
TEST_CASE( longtok );
|
TEST_CASE( longtok );
|
||||||
|
|
||||||
TEST_CASE( inlineasm );
|
TEST_CASE( inlineasm );
|
||||||
|
|
||||||
|
TEST_CASE( dupfuncname );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,9 +62,9 @@ private:
|
||||||
" \"def\"\n";
|
" \"def\"\n";
|
||||||
|
|
||||||
// tokenize..
|
// tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
tokenizer.TokenizeCode(istr, 0);
|
tokenizer.TokenizeCode(istr, 0);
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
|
@ -85,9 +88,9 @@ private:
|
||||||
std::string filedata(10000,'a');
|
std::string filedata(10000,'a');
|
||||||
|
|
||||||
// tokenize..
|
// tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
tokenizer.TokenizeCode(istr, 0);
|
tokenizer.TokenizeCode(istr, 0);
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
|
@ -109,9 +112,9 @@ private:
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// tokenize..
|
// tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
tokenizer.getFiles()->push_back( "test.cpp" );
|
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
tokenizer.TokenizeCode(istr, 0);
|
tokenizer.TokenizeCode(istr, 0);
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
|
@ -131,6 +134,27 @@ private:
|
||||||
|
|
||||||
tokenizer.DeallocateTokens();
|
tokenizer.DeallocateTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dupfuncname()
|
||||||
|
{
|
||||||
|
const char code[] = "void a()\n"
|
||||||
|
"{ }\n"
|
||||||
|
"void a(int i)\n"
|
||||||
|
"{ }\n"
|
||||||
|
"void b()\n"
|
||||||
|
"{ }\n";
|
||||||
|
// tokenize..
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
tokenizer.getFiles()->push_back( "test.cpp" );
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.TokenizeCode(istr, 0);
|
||||||
|
|
||||||
|
tokenizer.FillFunctionList(0);
|
||||||
|
|
||||||
|
ASSERT_EQUALS( 1, tokenizer.FunctionList.size() );
|
||||||
|
ASSERT_EQUALS( std::string("b"), tokenizer.FunctionList[0]->str );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestTokenizer )
|
REGISTER_TEST( TestTokenizer )
|
||||||
|
|
526
tokenize.cpp
526
tokenize.cpp
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdlib.h> // <- strtoul
|
#include <stdlib.h> // <- strtoul
|
||||||
|
@ -42,41 +42,41 @@
|
||||||
#define _strdup(str) strdup(str)
|
#define _strdup(str) strdup(str)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
Tokenizer::Tokenizer()
|
Tokenizer::Tokenizer()
|
||||||
{
|
{
|
||||||
_tokens = 0;
|
_tokens = 0;
|
||||||
tokens_back = 0;
|
tokens_back = 0;
|
||||||
dsymlist = 0;
|
dsymlist = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokenizer::~Tokenizer()
|
Tokenizer::~Tokenizer()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Helper functions..
|
||||||
|
|
||||||
|
TOKEN *Tokenizer::_gettok(TOKEN *tok, int index)
|
||||||
|
{
|
||||||
|
while (tok && index>0)
|
||||||
|
{
|
||||||
|
tok = tok->next;
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const TOKEN *Tokenizer::tokens() const
|
||||||
|
{
|
||||||
|
return _tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Helper functions..
|
|
||||||
|
|
||||||
TOKEN *Tokenizer::_gettok(TOKEN *tok, int index)
|
|
||||||
{
|
|
||||||
while (tok && index>0)
|
|
||||||
{
|
|
||||||
tok = tok->next;
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const TOKEN *Tokenizer::tokens() const
|
|
||||||
{
|
|
||||||
return _tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Defined symbols.
|
// Defined symbols.
|
||||||
|
@ -84,11 +84,11 @@ const TOKEN *Tokenizer::tokens() const
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::string> *Tokenizer::getFiles()
|
std::vector<std::string> *Tokenizer::getFiles()
|
||||||
{
|
{
|
||||||
return &Files;
|
return &Files;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::Define(const char Name[], const char Value[])
|
void Tokenizer::Define(const char Name[], const char Value[])
|
||||||
{
|
{
|
||||||
|
@ -755,13 +755,13 @@ void Tokenizer::SimplifyTokenList()
|
||||||
DeleteNextToken(tok);
|
DeleteNextToken(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Match(tok, "sizeof ( * %var% )"))
|
else if (Match(tok, "sizeof ( * %var% )"))
|
||||||
{
|
{
|
||||||
tok->setstr("100");
|
tok->setstr("100");
|
||||||
for ( int i = 0; i < 4; ++i )
|
for ( int i = 0; i < 4; ++i )
|
||||||
DeleteNextToken(tok);
|
DeleteNextToken(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,23 +1016,23 @@ void Tokenizer::SimplifyTokenList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace NULL with 0..
|
// Replace NULL with 0..
|
||||||
for ( TOKEN *tok = _tokens; tok; tok = tok->next )
|
for ( TOKEN *tok = _tokens; tok; tok = tok->next )
|
||||||
{
|
{
|
||||||
if ( Match(tok, "NULL") )
|
if ( Match(tok, "NULL") )
|
||||||
tok->setstr("0");
|
tok->setstr("0");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace pointer casts of 0.. "(char *)0" => "0"
|
// Replace pointer casts of 0.. "(char *)0" => "0"
|
||||||
for ( TOKEN *tok = _tokens; tok; tok = tok->next )
|
for ( TOKEN *tok = _tokens; tok; tok = tok->next )
|
||||||
{
|
{
|
||||||
if ( Match(tok->next, "( %type% * ) 0") || Match(tok->next,"( %type% %type% * ) 0") )
|
if ( Match(tok->next, "( %type% * ) 0") || Match(tok->next,"( %type% %type% * ) 0") )
|
||||||
{
|
{
|
||||||
while (!Match(tok->next,"0"))
|
while (!Match(tok->next,"0"))
|
||||||
DeleteNextToken(tok);
|
DeleteNextToken(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -1111,197 +1111,225 @@ void Tokenizer::DeallocateTokens()
|
||||||
free(dsymlist->value);
|
free(dsymlist->value);
|
||||||
delete dsymlist;
|
delete dsymlist;
|
||||||
dsymlist = next;
|
dsymlist = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
Files.clear();
|
Files.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const TOKEN *Tokenizer::GetFunctionTokenByName( const char funcname[] ) const
|
const TOKEN *Tokenizer::GetFunctionTokenByName( const char funcname[] ) const
|
||||||
{
|
{
|
||||||
std::list<const TOKEN *>::const_iterator it;
|
for ( unsigned int i = 0; i < FunctionList.size(); ++i )
|
||||||
for ( it = FunctionList.begin(); it != FunctionList.end(); it++ )
|
{
|
||||||
{
|
if ( strcmp( FunctionList[i]->str, funcname ) == 0 )
|
||||||
if ( strcmp( (*it)->str, funcname ) == 0 )
|
{
|
||||||
{
|
return FunctionList[i];
|
||||||
return *it;
|
}
|
||||||
}
|
}
|
||||||
}
|
return NULL;
|
||||||
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::FillFunctionList(const unsigned int file_id)
|
||||||
void Tokenizer::CheckGlobalFunctionUsage(const std::vector<std::string> &filenames)
|
{
|
||||||
{
|
FunctionList.clear();
|
||||||
// Iterator for GlobalFunctions
|
|
||||||
std::list<GlobalFunction>::const_iterator func;
|
std::list<const char *> _usedfunc;
|
||||||
|
if ( file_id == 0 )
|
||||||
// Iterator for UsedGlobalFunctions
|
{
|
||||||
std::list<GlobalFunction>::const_iterator usedfunc;
|
GlobalFunctions.clear();
|
||||||
|
}
|
||||||
unsigned int i1 = 0;
|
|
||||||
unsigned int i2 = 1;
|
bool staticfunc = false;
|
||||||
|
bool classfunc = false;
|
||||||
// Check that every function in GlobalFunctions are used
|
|
||||||
for ( func = GlobalFunctions.begin(); func != GlobalFunctions.end(); func++ )
|
int indentlevel = 0;
|
||||||
{
|
for ( const TOKEN *tok = _tokens; tok; tok = tok->next )
|
||||||
if ( GlobalFunctions.size() > 100 )
|
{
|
||||||
{
|
if ( tok->str[0] == '{' )
|
||||||
++i1;
|
indentlevel++;
|
||||||
if ( i1 > (i2 * GlobalFunctions.size()) / 100 )
|
|
||||||
{
|
else if ( tok->str[0] == '}' )
|
||||||
if ( (i2 % 10) == 0 )
|
indentlevel--;
|
||||||
std::cout << i2 << "%";
|
|
||||||
else
|
|
||||||
std::cout << ".";
|
if (indentlevel > 0)
|
||||||
std::cout.flush();
|
{
|
||||||
++i2;
|
if ( _settings._checkCodingStyle )
|
||||||
}
|
{
|
||||||
}
|
const char *funcname = 0;
|
||||||
|
|
||||||
const std::string &funcname = func->name();
|
if ( Match(tok,"%var% (") )
|
||||||
|
funcname = tok->str;
|
||||||
if ( funcname == "main" || funcname == "WinMain" )
|
else if ( Match(tok, "= %var% ;") ||
|
||||||
continue;
|
Match(tok, "= %var% ,") )
|
||||||
|
funcname = tok->next->str;
|
||||||
// Check if this global function is used in any of the other files..
|
|
||||||
bool UsedOtherFile = false;
|
if ( std::find(_usedfunc.begin(), _usedfunc.end(), funcname) == _usedfunc.end() )
|
||||||
bool UsedAnyFile = false;
|
_usedfunc.push_back( funcname );
|
||||||
for ( usedfunc = UsedGlobalFunctions.begin(); usedfunc != UsedGlobalFunctions.end(); usedfunc++ )
|
}
|
||||||
{
|
|
||||||
if ( funcname == usedfunc->name() )
|
continue;
|
||||||
{
|
}
|
||||||
UsedAnyFile = true;
|
|
||||||
if (func->file_id() != usedfunc->file_id())
|
if (strchr("};", tok->str[0]))
|
||||||
{
|
staticfunc = classfunc = false;
|
||||||
UsedOtherFile = true;
|
|
||||||
break;
|
else if ( strcmp( tok->str, "static" ) == 0 )
|
||||||
}
|
staticfunc = true;
|
||||||
}
|
|
||||||
}
|
else if ( strcmp( tok->str, "::" ) == 0 )
|
||||||
|
classfunc = true;
|
||||||
if ( ! UsedAnyFile )
|
|
||||||
{
|
else if (Match(tok, "%var% ("))
|
||||||
std::ostringstream errmsg;
|
{
|
||||||
errmsg << "[" << filenames[func->file_id()] << "]: "
|
// Check if this is the first token of a function implementation..
|
||||||
<< "The function '" << func->name() << "' is never used.";
|
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
|
||||||
ReportErr( errmsg.str() );
|
{
|
||||||
}
|
if ( tok2->str[0] == ';' )
|
||||||
else if ( ! UsedOtherFile )
|
{
|
||||||
{
|
tok = tok2;
|
||||||
std::ostringstream errmsg;
|
break;
|
||||||
errmsg << "[" << filenames[func->file_id()] << "]: "
|
}
|
||||||
<< "The linkage of the function '" << func->name() << "' can be local (static) instead of global";
|
|
||||||
ReportErr( errmsg.str() );
|
else if ( tok2->str[0] == '{' )
|
||||||
}
|
{
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
std::cout << "\n";
|
|
||||||
}
|
else if ( tok2->str[0] == ')' )
|
||||||
//---------------------------------------------------------------------------
|
{
|
||||||
|
if ( Match(tok2, ") {") )
|
||||||
void Tokenizer::settings( const Settings &settings )
|
{
|
||||||
{
|
if (_settings._checkCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0)
|
||||||
_settings = settings;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the FunctionList functions with duplicate names, remove them
|
||||||
|
// TODO this will need some better handling
|
||||||
|
for ( unsigned int func1 = 0; func1 < FunctionList.size(); )
|
||||||
|
{
|
||||||
|
bool hasDuplicates = false;
|
||||||
|
for ( unsigned int func2 = func1 + 1; func2 < FunctionList.size(); )
|
||||||
|
{
|
||||||
|
if ( strcmp(FunctionList[func1]->str, FunctionList[func2]->str) == 0 )
|
||||||
|
{
|
||||||
|
hasDuplicates = true;
|
||||||
|
FunctionList.erase( FunctionList.begin() + func2 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++func2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! hasDuplicates )
|
||||||
|
{
|
||||||
|
++func1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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.";
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
192
tokenize.h
192
tokenize.h
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
|
@ -22,11 +22,11 @@
|
||||||
#define tokenizeH
|
#define tokenizeH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include <list>
|
#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"
|
#include "settings.h"
|
||||||
|
|
||||||
class TOKEN
|
class TOKEN
|
||||||
|
@ -57,95 +57,99 @@ public:
|
||||||
unsigned int FileIndex;
|
unsigned int FileIndex;
|
||||||
unsigned int linenr;
|
unsigned int linenr;
|
||||||
TOKEN *next;
|
TOKEN *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Tokenizer
|
class Tokenizer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Tokenizer();
|
Tokenizer();
|
||||||
~Tokenizer();
|
~Tokenizer();
|
||||||
|
|
||||||
void Tokenize(std::istream &code, const char FileName[]);
|
void Tokenize(std::istream &code, const char FileName[]);
|
||||||
|
|
||||||
// Deallocate lists..
|
// Deallocate lists..
|
||||||
void DeallocateTokens();
|
void DeallocateTokens();
|
||||||
|
|
||||||
// Simplify tokenlist
|
// Simplify tokenlist
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
void SimplifyTokenList();
|
void SimplifyTokenList();
|
||||||
|
|
||||||
void TokenizeCode(std::istream &code, const unsigned int FileIndex=0);
|
void TokenizeCode(std::istream &code, const unsigned int FileIndex=0);
|
||||||
|
|
||||||
// Helper functions for handling the tokens list..
|
// Helper functions for handling the tokens list..
|
||||||
static const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]);
|
static const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]);
|
||||||
static const TOKEN *gettok(const TOKEN *tok, int index);
|
static const TOKEN *gettok(const TOKEN *tok, int index);
|
||||||
static const char *getstr(const TOKEN *tok, int index);
|
static const char *getstr(const TOKEN *tok, int index);
|
||||||
|
|
||||||
// Return size.
|
// Return size.
|
||||||
int SizeOfType(const char type[]);
|
int SizeOfType(const char type[]);
|
||||||
|
|
||||||
void initTokens();
|
void initTokens();
|
||||||
|
|
||||||
std::vector<std::string> *getFiles();
|
std::vector<std::string> *getFiles();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FillFunctionList(const unsigned int file_id);
|
void FillFunctionList(const unsigned int file_id);
|
||||||
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
|
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
|
||||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
||||||
void settings( const Settings &settings );
|
void settings( const Settings &settings );
|
||||||
const TOKEN *tokens() const;
|
const TOKEN *tokens() const;
|
||||||
private:
|
|
||||||
|
|
||||||
struct DefineSymbol
|
#ifndef UNIT_TESTING
|
||||||
{
|
private:
|
||||||
char *name;
|
#endif
|
||||||
char *value;
|
|
||||||
struct DefineSymbol *next;
|
struct DefineSymbol
|
||||||
};
|
{
|
||||||
|
char *name;
|
||||||
class GlobalFunction
|
char *value;
|
||||||
{
|
struct DefineSymbol *next;
|
||||||
private:
|
};
|
||||||
unsigned int _FileId;
|
|
||||||
std::string _FuncName;
|
class GlobalFunction
|
||||||
|
{
|
||||||
public:
|
private:
|
||||||
GlobalFunction( const unsigned int FileId, const char FuncName[] )
|
unsigned int _FileId;
|
||||||
{
|
std::string _FuncName;
|
||||||
_FileId = FileId;
|
|
||||||
_FuncName = FuncName;
|
public:
|
||||||
}
|
GlobalFunction( const unsigned int FileId, const char FuncName[] )
|
||||||
|
{
|
||||||
unsigned int file_id() const { return _FileId; }
|
_FileId = FileId;
|
||||||
const std::string &name() const { return _FuncName; }
|
_FuncName = FuncName;
|
||||||
};
|
}
|
||||||
|
|
||||||
void Define(const char Name[], const char Value[]);
|
unsigned int file_id() const { return _FileId; }
|
||||||
|
const std::string &name() const { return _FuncName; }
|
||||||
void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
};
|
||||||
|
|
||||||
void combine_2tokens(TOKEN *tok, const char str1[], const char str2[]);
|
void Define(const char Name[], const char Value[]);
|
||||||
|
|
||||||
void DeleteNextToken(TOKEN *tok);
|
void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
||||||
|
|
||||||
TOKEN *_gettok(TOKEN *tok, int index);
|
void combine_2tokens(TOKEN *tok, const char str1[], const char str2[]);
|
||||||
|
|
||||||
void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n);
|
void DeleteNextToken(TOKEN *tok);
|
||||||
|
|
||||||
TOKEN *tokens_back;
|
TOKEN *_gettok(TOKEN *tok, int index);
|
||||||
std::map<std::string, unsigned int> TypeSize;
|
|
||||||
std::list<const TOKEN *> FunctionList;
|
void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n);
|
||||||
std::list< GlobalFunction > GlobalFunctions;
|
|
||||||
std::list< GlobalFunction > UsedGlobalFunctions;
|
TOKEN *tokens_back;
|
||||||
std::vector<std::string> Files;
|
std::map<std::string, unsigned int> TypeSize;
|
||||||
Settings _settings;
|
std::vector<const TOKEN *> FunctionList;
|
||||||
|
std::list< GlobalFunction > GlobalFunctions;
|
||||||
|
std::list< GlobalFunction > UsedGlobalFunctions;
|
||||||
struct DefineSymbol * dsymlist;
|
std::vector<std::string> Files;
|
||||||
TOKEN *_tokens;
|
Settings _settings;
|
||||||
};
|
|
||||||
|
|
||||||
|
struct DefineSymbol * dsymlist;
|
||||||
|
TOKEN *_tokens;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue