diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 800244dcf..0d51ab3e1 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -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 &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::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::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::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 usedVariables; + checkFunctionVariableUsage_iterateScopes(&*scope, variables, false, usedVariables); // Check usage of all variables in the current scope.. diff --git a/lib/checkunusedvar.h b/lib/checkunusedvar.h index a98e63903..fde1e011c 100644 --- a/lib/checkunusedvar.h +++ b/lib/checkunusedvar.h @@ -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 &usedVariables); void checkVariableUsage(const Scope* const scope, const Token* start, Variables& variables); void checkFunctionVariableUsage(); diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 1a2339741..3c7baac29 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -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<