Fix 10023: ValueFlow; Wrong result of post-increment in reverse analysis (#3289)
This commit is contained in:
parent
e3b7ceec7e
commit
b23c5aa742
|
@ -42,6 +42,11 @@ struct ReverseTraversal {
|
||||||
bool updateRecursive(Token* start) {
|
bool updateRecursive(Token* start) {
|
||||||
bool continueB = true;
|
bool continueB = true;
|
||||||
visitAstNodes(start, [&](Token* tok) {
|
visitAstNodes(start, [&](Token* tok) {
|
||||||
|
const Token* parent = tok->astParent();
|
||||||
|
while (Token::simpleMatch(parent, ":"))
|
||||||
|
parent = parent->astParent();
|
||||||
|
if (isUnevaluated(tok) || isDeadCode(tok, parent))
|
||||||
|
return ChildrenToVisit::none;
|
||||||
continueB &= update(tok);
|
continueB &= update(tok);
|
||||||
if (continueB)
|
if (continueB)
|
||||||
return ChildrenToVisit::op1_and_op2;
|
return ChildrenToVisit::op1_and_op2;
|
||||||
|
@ -73,9 +78,11 @@ struct ReverseTraversal {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* isDeadCode(Token* tok) {
|
Token* isDeadCode(Token* tok, const Token* end = nullptr) {
|
||||||
int opSide = 0;
|
int opSide = 0;
|
||||||
for (; tok && tok->astParent(); tok = tok->astParent()) {
|
for (; tok && tok->astParent(); tok = tok->astParent()) {
|
||||||
|
if (tok == end)
|
||||||
|
break;
|
||||||
Token* parent = tok->astParent();
|
Token* parent = tok->astParent();
|
||||||
if (Token::simpleMatch(parent, ":")) {
|
if (Token::simpleMatch(parent, ":")) {
|
||||||
if (astIsLHS(tok))
|
if (astIsLHS(tok))
|
||||||
|
@ -178,8 +185,7 @@ struct ReverseTraversal {
|
||||||
}
|
}
|
||||||
if (!continueB)
|
if (!continueB)
|
||||||
break;
|
break;
|
||||||
Analyzer::Action a = valueFlowGenericForward(assignTop->astOperand2(), analyzer, settings);
|
if (!updateRecursive(assignTop->astOperand2()))
|
||||||
if (a.isModified())
|
|
||||||
break;
|
break;
|
||||||
tok = previousBeforeAstLeftmostLeaf(assignTop)->next();
|
tok = previousBeforeAstLeftmostLeaf(assignTop)->next();
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -133,6 +133,7 @@ private:
|
||||||
TEST_CASE(array_index_53); // #4750
|
TEST_CASE(array_index_53); // #4750
|
||||||
TEST_CASE(array_index_54); // #10268
|
TEST_CASE(array_index_54); // #10268
|
||||||
TEST_CASE(array_index_55); // #10254
|
TEST_CASE(array_index_55); // #10254
|
||||||
|
TEST_CASE(array_index_57); // #10023
|
||||||
TEST_CASE(array_index_multidim);
|
TEST_CASE(array_index_multidim);
|
||||||
TEST_CASE(array_index_switch_in_for);
|
TEST_CASE(array_index_switch_in_for);
|
||||||
TEST_CASE(array_index_for_in_for); // FP: #2634
|
TEST_CASE(array_index_for_in_for); // FP: #2634
|
||||||
|
@ -1593,6 +1594,34 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void array_index_57() {
|
||||||
|
check("void f(std::vector<int>& v) {\n"
|
||||||
|
" int a[3] = { 1, 2, 3 };\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
" for (auto& x : v) {\n"
|
||||||
|
" int c = a[i++];\n"
|
||||||
|
" if (i == 3)\n"
|
||||||
|
" i = 0;\n"
|
||||||
|
" x = c;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(std::vector<int>& v) {\n"
|
||||||
|
" int a[3] = { 1, 2, 3 };\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
" for (auto& x : v) {\n"
|
||||||
|
" int c = a[i++];\n"
|
||||||
|
" if (i == 4)\n"
|
||||||
|
" i = 0;\n"
|
||||||
|
" x = c;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS(
|
||||||
|
"[test.cpp:6] -> [test.cpp:5]: (warning) Either the condition 'i==4' is redundant or the array 'a[3]' is accessed at index 3, which is out of bounds.\n",
|
||||||
|
errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void array_index_multidim() {
|
void array_index_multidim() {
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
|
@ -728,9 +728,8 @@ private:
|
||||||
" if (!p)\n"
|
" if (!p)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}");
|
"}");
|
||||||
TODO_ASSERT_EQUALS(
|
ASSERT_EQUALS(
|
||||||
"[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n",
|
"[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n",
|
||||||
"",
|
|
||||||
errout.str());
|
errout.str());
|
||||||
|
|
||||||
// while
|
// while
|
||||||
|
|
Loading…
Reference in New Issue