function variable usage : Added a simple check
This commit is contained in:
parent
b2e55216ab
commit
b1ee3c5d31
|
@ -821,5 +821,87 @@ void CheckOther::unreachableCode()
|
|||
tok = TOKEN::findmatch( tok, "[;{}] return" );
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Usage of function variables
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckOther::functionVariableUsage()
|
||||
{
|
||||
// Parse all executing scopes..
|
||||
const TOKEN *tok1 = TOKEN::findmatch( _tokenizer->tokens(), ") const| {" );
|
||||
while ( tok1 )
|
||||
{
|
||||
// Varname, usage {1=declare, 2=read, 4=write}
|
||||
std::map<std::string, unsigned int> varUsage;
|
||||
static const unsigned int USAGE_DECLARE = 1;
|
||||
static const unsigned int USAGE_READ = 2;
|
||||
static const unsigned int USAGE_WRITE = 4;
|
||||
|
||||
int indentlevel = 0;
|
||||
for ( const TOKEN *tok = tok1; tok; tok = tok->next )
|
||||
{
|
||||
if ( tok->str() == "{" )
|
||||
++indentlevel;
|
||||
else if ( tok->str() == "}" )
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel <= 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( TOKEN::Match(tok, "[;{}] %type% %var% ;|=") )
|
||||
{
|
||||
if ( TOKEN::Match(tok->next, "delete|return") )
|
||||
varUsage[ tok->strAt(2) ] |= USAGE_READ;
|
||||
else
|
||||
varUsage[ tok->strAt(2) ] = USAGE_DECLARE;
|
||||
}
|
||||
|
||||
else if ( TOKEN::Match(tok, "[;{}] %var% =") )
|
||||
{
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check usage of all variables in the current scope..
|
||||
for ( std::map<std::string, unsigned int>::const_iterator it = varUsage.begin(); it != varUsage.end(); ++it )
|
||||
{
|
||||
std::string varname = it->first;
|
||||
unsigned int usage = it->second;
|
||||
|
||||
if ( ! ( usage & USAGE_DECLARE ) )
|
||||
continue;
|
||||
|
||||
if ( usage == USAGE_DECLARE )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1->next) << ": Unused variable '" << varname << "'";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
else if ( ! (usage & USAGE_READ) )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1->next) << ": Variable '" << varname << "' is assigned a value that is never used";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
else if ( ! (usage & USAGE_WRITE) )
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1->next) << ": Variable '" << varname << "' is not assigned a value";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Goto next executing scope..
|
||||
tok1 = TOKEN::findmatch( tok1->next, ") const| {" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,10 @@ public:
|
|||
void CheckIncompleteStatement();
|
||||
|
||||
/** Unreachable code below a 'return' */
|
||||
void unreachableCode();
|
||||
void unreachableCode();
|
||||
|
||||
/** Unused function variables */
|
||||
void functionVariableUsage();
|
||||
private:
|
||||
void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[] );
|
||||
|
||||
|
|
|
@ -56,6 +56,9 @@ private:
|
|||
TEST_CASE( structmember1 );
|
||||
TEST_CASE( structmember2 );
|
||||
TEST_CASE( structmember3 );
|
||||
|
||||
TEST_CASE( localvar1 );
|
||||
TEST_CASE( localvar2 );
|
||||
}
|
||||
|
||||
void structmember1()
|
||||
|
@ -111,6 +114,45 @@ private:
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void functionVariableUsage( const char code[] )
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for unused variables..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
checkOther.functionVariableUsage();
|
||||
}
|
||||
|
||||
void localvar1()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int i = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
||||
}
|
||||
|
||||
void localvar2()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" return i;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestUnusedVar )
|
||||
|
|
Loading…
Reference in New Issue