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,9 +820,34 @@ static bool valueFlowForward(Token * const startToken,
++number_of_if;
tok2 = end;
} else {
if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok2, "variable " + var->name() + " is assigned in conditional code");
return false;
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)
bailout(tokenlist, errorLogger, tok2, "variable " + var->name() + " is assigned in conditional code");
return false;
}
}
}
}

View File

@ -1099,7 +1099,7 @@ private:
"\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() {

View File

@ -871,6 +871,43 @@ private:
" }\n"
"}";
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() {