ValueFlow: improved valueflow for loops that assign variable and then break

This commit is contained in:
Daniel Marjamäki 2014-09-23 16:06:02 +02:00
parent dc9b1f09ae
commit ee93d30d94
3 changed files with 66 additions and 4 deletions

View File

@ -820,12 +820,37 @@ static bool valueFlowForward(Token * const startToken,
++number_of_if; ++number_of_if;
tok2 = end; tok2 = end;
} else { } else {
bool bail = true;
// loop that conditionally set variable and then break => either loop condition is
// redundant or the variable can be unchanged after the loop.
bool loopCondition = false;
if (Token::simpleMatch(tok2, "while (") && Token::Match(tok2->next()->astOperand2(), "%op%"))
loopCondition = true;
else if (Token::simpleMatch(tok2, "for (") &&
Token::simpleMatch(tok2->next()->astOperand2(), ";") &&
Token::simpleMatch(tok2->next()->astOperand2()->astOperand2(), ";") &&
Token::Match(tok2->next()->astOperand2()->astOperand2()->astOperand1(), "%op%"))
loopCondition = true;
if (loopCondition) {
const Token *tok3 = Token::findmatch(start, "%varid%", end, varid);
if (Token::Match(tok3, "%varid% =", varid) &&
tok3->scope()->classEnd &&
Token::Match(tok3->scope()->classEnd->tokAt(-3), "[;}] break ;") &&
!Token::findmatch(tok3->next(), "%varid%", end, varid)) {
bail = false;
tok2 = end;
}
}
if (bail) {
if (settings->debugwarnings) if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok2, "variable " + var->name() + " is assigned in conditional code"); bailout(tokenlist, errorLogger, tok2, "variable " + var->name() + " is assigned in conditional code");
return false; return false;
} }
} }
} }
}
else if (tok2->str() == "}" && indentlevel == varusagelevel) { else if (tok2->str() == "}" && indentlevel == varusagelevel) {
++number_of_if; ++number_of_if;

View File

@ -1099,7 +1099,7 @@ private:
"\n" "\n"
" *p = 0;\n" " *p = 0;\n"
"}"); "}");
TODO_ASSERT_EQUALS("[test.cpp:11]: (error) Possible null pointer dereference: p\n", "", errout.str()); ASSERT_EQUALS("[test.cpp:11]: (error) Possible null pointer dereference: p\n", errout.str());
} }
void nullpointer7() { void nullpointer7() {

View File

@ -871,6 +871,43 @@ private:
" }\n" " }\n"
"}"; "}";
ASSERT_EQUALS(false, testValueOfX(code, 8U, 34)); ASSERT_EQUALS(false, testValueOfX(code, 8U, 34));
// while/for
code = "void f(const int *buf) {\n"
" int x = 0;\n"
" for (int i = 0; i < 10; i++) {\n"
" if (buf[i] == 123) {\n"
" x = i;\n"
" break;\n"
" }\n"
" }\n"
" a = x;\n" // <- x can be 0
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 9U, 0)); // x can be 0 at line 9
code = "void f(const int *buf) {\n"
" int x = 0;\n"
" for (int i = 0; i < 10; i++) {\n"
" if (buf[i] == 123) {\n"
" x = i;\n"
" ;\n" // <- no break
" }\n"
" }\n"
" a = x;\n" // <- x cant be 0
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 9U, 0)); // x cant be 0 at line 9
code = "void f(const int *buf) {\n"
" int x = 0;\n"
" while (++i < 10) {\n"
" if (buf[i] == 123) {\n"
" x = i;\n"
" break;\n"
" }\n"
" }\n"
" a = x;\n" // <- x can be 0
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 9U, 0)); // x can be 0 at line 9
} }
void valueFlowAfterCondition() { void valueFlowAfterCondition() {