CheckUnusedVar: Fix FP for assignment in while

This commit is contained in:
Daniel Marjamäki 2016-01-01 12:14:18 +01:00
parent e69e952c46
commit dea41e2390
2 changed files with 29 additions and 15 deletions

View File

@ -770,7 +770,6 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
break;
}
// bailout when for_each is used
if (Token::Match(tok, "%name% (") && Token::simpleMatch(tok->linkAt(1), ") {") && !Token::Match(tok, "if|for|while|switch")) {
// does the name contain "for_each" or "foreach"?
@ -861,9 +860,6 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
}
}
else if (Token::Match(tok->tokAt(-2), "while|if") && tok->strAt(1) == "=" && tok->varId() && tok->varId() == tok->tokAt(2)->varId()) {
variables.use(tok->tokAt(2)->varId(), tok);
}
// assignment
else if (Token::Match(tok, "*| ++|--| %name% ++|--| %assign%") ||
Token::Match(tok, "*| ( const| %type% *| ) %name% %assign%")) {
@ -893,6 +889,17 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
const unsigned int varid1 = tok->varId();
const Token * const start = tok;
// assignment in while head..
bool inwhile = false;
{
const Token *parent = tok->astParent();
while (parent) {
if (Token::simpleMatch(parent->previous(), "while ("))
inwhile = true;
parent = parent->astParent();
}
}
tok = doAssignment(variables, tok, dereference, scope);
if (tok && tok->isAssignmentOp() && tok->str() != "=") {
@ -914,7 +921,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
variables.read(varid1, tok);
} else {
Variables::VariableUsage *var = variables.find(varid1);
if (var && start->strAt(-1) == ",") {
if (var && (inwhile || start->strAt(-1) == ",")) {
variables.use(varid1, tok);
} else if (var && var->_type == Variables::reference) {
variables.writeAliases(varid1, tok);

View File

@ -144,7 +144,6 @@ private:
TEST_CASE(localvarFor); // for ( ; var; )
TEST_CASE(localvarForEach); // #4155 - BOOST_FOREACH, hlist_for_each, etc
TEST_CASE(localvarShift1); // 1 >> var
TEST_CASE(localvarShift2); // x = x >> 1
TEST_CASE(localvarShift3); // x << y
TEST_CASE(localvarCast);
TEST_CASE(localvarClass);
@ -156,6 +155,7 @@ private:
TEST_CASE(localvarNULL); // #4203 - Setting NULL value is not redundant - it is safe
TEST_CASE(localvarUnusedGoto); // #4447, #4558 goto
TEST_CASE(localvarRangeBasedFor); // #7075
TEST_CASE(localvarAssignInWhile);
TEST_CASE(localvarCpp11Initialization);
@ -3238,15 +3238,6 @@ private:
ASSERT_EQUALS("", errout.str());
}
void localvarShift2() {
functionVariableUsage("int foo()\n"
"{\n"
" int var = 1;\n"
" while (var = var >> 1) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void localvarShift3() { // #3509
functionVariableUsage("int foo()\n"
"{\n"
@ -3859,6 +3850,22 @@ private:
ASSERT_EQUALS("", errout.str());
}
void localvarAssignInWhile() {
functionVariableUsage("void foo() {\n"
" int a = 0;\n"
" do {\n"
" dostuff(a);\n"
" } while((a + = x) < 30);\n"
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("int foo() {\n"
" int var = 1;\n"
" while (var = var >> 1) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void chainedAssignment() {
// #5466
functionVariableUsage("void NotUsed(double* pdD, int n) {\n"