Fix issue 8296: ValueFlow: value not set in conditional scope in subfunction (#2071)
* Fix issue 8296: ValueFlow: value not set in conditional scope in subfunction * Refactor condition checkingg * Make test case TODO
This commit is contained in:
parent
46c93779d8
commit
9aa97cbb95
|
@ -2145,16 +2145,16 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const ProgramMemory &programMemory = getProgramMemory(tok2, varid, v);
|
const ProgramMemory &programMemory = getProgramMemory(tok2, varid, v);
|
||||||
if (subFunction && conditionIsTrue(condTok, programMemory))
|
const bool isTrue = conditionIsTrue(condTok, programMemory);
|
||||||
|
const bool isFalse = conditionIsFalse(condTok, programMemory);
|
||||||
|
|
||||||
|
if (isTrue)
|
||||||
truevalues.push_back(v);
|
truevalues.push_back(v);
|
||||||
else if (!conditionIsFalse(condTok, programMemory))
|
if (isFalse)
|
||||||
truevalues.push_back(v);
|
|
||||||
if (conditionIsFalse(condTok, programMemory))
|
|
||||||
falsevalues.push_back(v);
|
|
||||||
else if (!subFunction && !conditionIsTrue(condTok, programMemory))
|
|
||||||
falsevalues.push_back(v);
|
falsevalues.push_back(v);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (truevalues.size() != values.size() || condAlwaysTrue) {
|
if (!truevalues.empty() || !falsevalues.empty()) {
|
||||||
// '{'
|
// '{'
|
||||||
const Token * const startToken1 = tok2->linkAt(1)->next();
|
const Token * const startToken1 = tok2->linkAt(1)->next();
|
||||||
|
|
||||||
|
@ -2211,7 +2211,8 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
removeValues(values, falsevalues);
|
removeValues(values, falsevalues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (values.empty())
|
||||||
|
return false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ private:
|
||||||
TEST_CASE(nullpointer32); // #8460
|
TEST_CASE(nullpointer32); // #8460
|
||||||
TEST_CASE(nullpointer33);
|
TEST_CASE(nullpointer33);
|
||||||
TEST_CASE(nullpointer34);
|
TEST_CASE(nullpointer34);
|
||||||
|
TEST_CASE(nullpointer35);
|
||||||
TEST_CASE(nullpointer_addressOf); // address of
|
TEST_CASE(nullpointer_addressOf); // address of
|
||||||
TEST_CASE(nullpointerSwitch); // #2626
|
TEST_CASE(nullpointerSwitch); // #2626
|
||||||
TEST_CASE(nullpointer_cast); // #4692
|
TEST_CASE(nullpointer_cast); // #4692
|
||||||
|
@ -1413,6 +1414,19 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nullpointer35() {
|
||||||
|
check("bool f(int*);\n"
|
||||||
|
"void g(int* x) {\n"
|
||||||
|
" if (f(x)) {\n"
|
||||||
|
" *x = 1;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"void h() {\n"
|
||||||
|
" g(0);\n"
|
||||||
|
"}\n", true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void nullpointer_addressOf() { // address of
|
void nullpointer_addressOf() { // address of
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" struct X *x = 0;\n"
|
" struct X *x = 0;\n"
|
||||||
|
@ -2574,7 +2588,7 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f(int *p = 0) {\n"
|
check("void f(int a, int *p = 0) {\n"
|
||||||
" if (a != 0)\n"
|
" if (a != 0)\n"
|
||||||
" *p = 0;\n"
|
" *p = 0;\n"
|
||||||
"}", true);
|
"}", true);
|
||||||
|
|
|
@ -94,6 +94,7 @@ private:
|
||||||
TEST_CASE(valueFlowSwitchVariable);
|
TEST_CASE(valueFlowSwitchVariable);
|
||||||
|
|
||||||
TEST_CASE(valueFlowForLoop);
|
TEST_CASE(valueFlowForLoop);
|
||||||
|
TEST_CASE(valueFlowSubFunction);
|
||||||
TEST_CASE(valueFlowFunctionReturn);
|
TEST_CASE(valueFlowFunctionReturn);
|
||||||
|
|
||||||
TEST_CASE(valueFlowFunctionDefaultParameter);
|
TEST_CASE(valueFlowFunctionDefaultParameter);
|
||||||
|
@ -2203,7 +2204,7 @@ private:
|
||||||
" else\n"
|
" else\n"
|
||||||
" b = x;\n"
|
" b = x;\n"
|
||||||
"}";
|
"}";
|
||||||
TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 4U, 2));
|
ASSERT_EQUALS(true, testValueOfX(code, 4U, 2));
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 6U, 2));
|
ASSERT_EQUALS(false, testValueOfX(code, 6U, 2));
|
||||||
|
|
||||||
// condition with 2nd variable
|
// condition with 2nd variable
|
||||||
|
@ -2925,6 +2926,26 @@ private:
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 5U, 3));
|
ASSERT_EQUALS(true, testValueOfX(code, 5U, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void valueFlowSubFunction() {
|
||||||
|
const char *code;
|
||||||
|
|
||||||
|
code = "int f(int size) {\n"
|
||||||
|
" int x = 0;\n"
|
||||||
|
" if(size>16) {\n"
|
||||||
|
" x = size;\n"
|
||||||
|
" int a = x;\n"
|
||||||
|
" }\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}\n"
|
||||||
|
"void g(){\n"
|
||||||
|
" f(42);\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 5U, 17));
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 5U, 42));
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 7U, 0));
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 7U, 17));
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 7U, 42));
|
||||||
|
}
|
||||||
void valueFlowFunctionReturn() {
|
void valueFlowFunctionReturn() {
|
||||||
const char *code;
|
const char *code;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue