ValueFlow: improved valueflow for loops that assign variable and then break
This commit is contained in:
parent
dc9b1f09ae
commit
ee93d30d94
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue