Fixed #4138 - False positive about variable assigned a value that is never

used in loops
This commit is contained in:
kbajaj91 2012-09-04 13:06:04 +02:00 committed by PKEuS
parent f8591f9004
commit be716e81d3
3 changed files with 129 additions and 17 deletions

View File

@ -599,7 +599,7 @@ static const Token * skipBracketsAndMembers(const Token *tok)
//---------------------------------------------------------------------------
// Usage of function variables
//---------------------------------------------------------------------------
void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const scope, Variables& variables)
void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const scope, Variables& variables, bool insideLoop, std::vector<unsigned int> &usedVariables)
{
// Find declarations if the scope is executable..
if (scope->type != Scope::eClass && scope->type != Scope::eUnion && scope->type != Scope::eStruct) {
@ -653,12 +653,21 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
}
}
if (scope->classDef->str() == "for" || scope->classDef->str() == "while") {
insideLoop = true;
}
// Check variable usage
for (const Token *tok = scope->classDef->next(); tok && tok != scope->classEnd; tok = tok->next()) {
if (tok->str() == "for") {
if (tok->str() == "for" || tok->str() == "while") {
for (std::list<Scope*>::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) {
if ((*i)->classDef == tok) { // Find associated scope
checkFunctionVariableUsage_iterateScopes(*i, variables); // Scan child scope
checkFunctionVariableUsage_iterateScopes(*i, variables, true, usedVariables); // Scan child scope
insideLoop = false;
std::vector<unsigned int>::iterator it;
for (it = usedVariables.begin(); it != usedVariables.end(); it++) {
variables.read((*it));
}
tok = (*i)->classStart->link();
break;
}
@ -669,7 +678,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
if (tok->str() == "{") {
for (std::list<Scope*>::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) {
if ((*i)->classStart == tok) { // Find associated scope
checkFunctionVariableUsage_iterateScopes(*i, variables); // Scan child scope
checkFunctionVariableUsage_iterateScopes(*i, variables, insideLoop, usedVariables); // Scan child scope
tok = tok->link();
break;
}
@ -872,48 +881,70 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
variables.read(tok->next()->varId());
} else // addressof
variables.use(tok->next()->varId()); // use = read + write
} else if (Token::Match(tok, ">> %var%"))
usedVariables.push_back(tok->next()->varId());
} else if (Token::Match(tok, ">> %var%")) {
variables.use(tok->next()->varId()); // use = read + write
else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]"))
usedVariables.push_back(tok->next()->varId());
} else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]")) {
variables.read(tok->varId());
usedVariables.push_back(tok->next()->varId());
}
// function parameter
else if (Token::Match(tok, "[(,] %var% ["))
else if (Token::Match(tok, "[(,] %var% [")) {
variables.use(tok->next()->varId()); // use = read + write
else if (Token::Match(tok, "[(,] %var% [,)]") && tok->previous()->str() != "*") {
usedVariables.push_back(tok->next()->varId());
} else if (Token::Match(tok, "[(,] %var% [,)]") && tok->previous()->str() != "*") {
variables.use(tok->next()->varId()); // use = read + write
usedVariables.push_back(tok->next()->varId());
} else if (Token::Match(tok, "[(,] (") &&
Token::Match(tok->next()->link(), ") %var% [,)]"))
Token::Match(tok->next()->link(), ") %var% [,)]")) {
variables.use(tok->next()->link()->next()->varId()); // use = read + write
usedVariables.push_back(tok->next()->link()->next()->varId());
}
// function
else if (Token::Match(tok, "%var% (")) {
variables.read(tok->varId());
if (Token::Match(tok->tokAt(2), "%var% ="))
usedVariables.push_back(tok->varId());
if (Token::Match(tok->tokAt(2), "%var% =")) {
variables.read(tok->tokAt(2)->varId());
usedVariables.push_back(tok->tokAt(2)->varId());
}
}
else if (Token::Match(tok, "[{,] %var% [,}]"))
else if (Token::Match(tok, "[{,] %var% [,}]")) {
variables.read(tok->next()->varId());
usedVariables.push_back(tok->next()->varId());
}
else if (Token::Match(tok, "%var% ."))
else if (Token::Match(tok, "%var% .")) {
variables.use(tok->varId()); // use = read + write
usedVariables.push_back(tok->varId());
}
else if (tok->isExtendedOp() &&
Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new") && tok->strAt(2) != "=")
Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new") && tok->strAt(2) != "=") {
variables.readAll(tok->next()->varId());
usedVariables.push_back(tok->next()->varId());
}
else if (Token::Match(tok, "%var%") && tok->next() && (tok->next()->str() == ")" || tok->next()->isExtendedOp()))
else if (Token::Match(tok, "%var%") && tok->next() && (tok->next()->str() == ")" || tok->next()->isExtendedOp())) {
variables.readAll(tok->varId());
usedVariables.push_back(tok->varId());
}
else if (Token::Match(tok, "%var% ;") && Token::Match(tok->previous(), "[;{}:]"))
else if (Token::Match(tok, "%var% ;") && Token::Match(tok->previous(), "[;{}:]")) {
variables.readAll(tok->varId());
usedVariables.push_back(tok->varId());
}
else if (Token::Match(tok, "++|-- %var%")) {
if (!Token::Match(tok->previous(), "[;{}:]"))
variables.use(tok->next()->varId());
else
variables.modified(tok->next()->varId());
usedVariables.push_back(tok->next()->varId());
}
else if (Token::Match(tok, "%var% ++|--")) {
@ -921,6 +952,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
variables.use(tok->varId());
else
variables.modified(tok->varId());
usedVariables.push_back(tok->varId());
}
else if (tok->isAssignmentOp()) {
@ -930,6 +962,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
variables.write(tok2->varId());
else
variables.read(tok2->varId());
usedVariables.push_back(tok2->varId());
}
}
}
@ -952,7 +985,8 @@ void CheckUnusedVar::checkFunctionVariableUsage()
// varId, usage {read, write, modified}
Variables variables;
checkFunctionVariableUsage_iterateScopes(&*scope, variables);
std::vector<unsigned int> usedVariables;
checkFunctionVariableUsage_iterateScopes(&*scope, variables, false, usedVariables);
// Check usage of all variables in the current scope..

View File

@ -64,7 +64,7 @@ public:
}
/** @brief %Check for unused function variables */
void checkFunctionVariableUsage_iterateScopes(const Scope* const scope, Variables& variables);
void checkFunctionVariableUsage_iterateScopes(const Scope* const scope, Variables& variables, bool insideLoop, std::vector<unsigned int> &usedVariables);
void checkVariableUsage(const Scope* const scope, const Token* start, Variables& variables);
void checkFunctionVariableUsage();

View File

@ -589,6 +589,84 @@ private:
" int i = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int i = 0,code=10;\n"
" for(i = 0; i < 10; i++) {\n"
" std::cout<<code<<std::endl;\n"
" code += 2;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int i = 0,code=10,d=10;\n"
" for(i = 0; i < 10; i++) {\n"
" std::cout<<code<<std::endl;\n"
" code += 2;\n"
" d += code;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'd' is assigned a value that is never used\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int code=10;\n"
" while(code < 20) {\n"
" std::cout<<code<<std::endl;\n"
" code += 2;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int code=10,d=10;\n"
" while(code < 20) {\n"
" std::cout<<code<<std::endl;\n"
" code += 2;\n"
" d += code;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'd' is assigned a value that is never used\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int code=10;\n"
" for(int i=0; i < 10; i++) {\n"
" if(true) {\n"
" std::cout<<code<<std::endl;\n"
" code += 2;\n"
" }\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int code=10;\n"
" for(int i=0; i < 10; i++) {\n"
" if(true) {\n"
" std::cout<<code<<std::endl;\n"
" }\n"
" code += 2;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" int code=10;\n"
" while(code < 20) {\n"
" if(true) {\n"
" std::cout<<code<<std::endl;\n"
" code += 2;\n"
" }\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void localvar2() {