Skip to content

Commit f093692

Browse files
pfultz2danmar
authored andcommitted
ValueFlow: Set values in else branch even when the first branch modifies the value (danmar#1309)
* Set values in else branch even when the first branch modifies the value * Move tests * Add check for goto * Remvoe todo * Also check scope is noreturn * Use isEscapeScope when variables are changed
1 parent 01ceb9b commit f093692

File tree

2 files changed

+75
-4
lines changed

2 files changed

+75
-4
lines changed

lib/valueflow.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,14 @@ static bool evalAssignment(ValueFlow::Value &lhsValue, const std::string &assign
15431543
return true;
15441544
}
15451545

1546+
static bool isEscapeScope(const Token* tok, TokenList * tokenlist)
1547+
{
1548+
if(!Token::simpleMatch(tok, "{"))
1549+
return false;
1550+
return Token::findmatch(tok, "return|continue|break|throw|goto", tok->link()) ||
1551+
(tokenlist && tokenlist->getSettings()->library.isScopeNoReturn(tok->link(), nullptr));
1552+
}
1553+
15461554
static bool valueFlowForward(Token * const startToken,
15471555
const Token * const endToken,
15481556
const Variable * const var,
@@ -1848,8 +1856,8 @@ static bool valueFlowForward(Token * const startToken,
18481856

18491857
// noreturn scopes..
18501858
if ((number_of_if > 0 || Token::findmatch(tok2, "%varid%", start, varid)) &&
1851-
(Token::findmatch(start, "return|continue|break|throw", end) ||
1852-
(Token::simpleMatch(end,"} else {") && Token::findmatch(end, "return|continue|break|throw", end->linkAt(2))))) {
1859+
(isEscapeScope(start, tokenlist) ||
1860+
(Token::simpleMatch(end,"} else {") && isEscapeScope(end->tokAt(2), tokenlist)))) {
18531861
if (settings->debugwarnings)
18541862
bailout(tokenlist, errorLogger, tok2, "variable " + var->name() + ". noreturn conditional scope.");
18551863
return false;
@@ -1859,8 +1867,7 @@ static bool valueFlowForward(Token * const startToken,
18591867
if ((!read || number_of_if == 0) &&
18601868
Token::simpleMatch(tok2, "if (") &&
18611869
!(Token::simpleMatch(end, "} else {") &&
1862-
(Token::findmatch(end, "%varid%", end->linkAt(2), varid) ||
1863-
Token::findmatch(end, "return|continue|break|throw", end->linkAt(2))))) {
1870+
isEscapeScope(end->tokAt(2), tokenlist))) {
18641871
++number_of_if;
18651872
tok2 = end;
18661873
} else {

test/testvalueflow.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,23 @@ class TestValueFlow : public TestFixture {
15831583
"}";
15841584
ASSERT_EQUALS(false, testValueOfX(code, 9U, 0));
15851585

1586+
code = "void f(int i) {\n"
1587+
" bool x = false;\n"
1588+
" if (i == 0) { x = true; }\n"
1589+
" else if (x && i == 1) {}\n"
1590+
"}\n";
1591+
ASSERT_EQUALS(true, testValueOfX(code, 4U, 0));
1592+
1593+
code = "void f(int i) {\n"
1594+
" bool x = false;\n"
1595+
" while(i > 0) {\n"
1596+
" i++;\n"
1597+
" if (i == 0) { x = true; }\n"
1598+
" else if (x && i == 1) {}\n"
1599+
" }\n"
1600+
"}\n";
1601+
ASSERT_EQUALS(false, testValueOfX(code, 6U, 0));
1602+
15861603
// multivariables
15871604
code = "void f(int a) {\n"
15881605
" int x = a;\n"
@@ -3137,6 +3154,53 @@ class TestValueFlow : public TestFixture {
31373154
"}";
31383155
values = tokenValues(code, "x ; }");
31393156
ASSERT_EQUALS(true, values.empty());
3157+
3158+
code = "void b(bool d, bool e) {\n"
3159+
" int c;\n"
3160+
" if (d)\n"
3161+
" c = 0;\n"
3162+
" if (e)\n"
3163+
" goto;\n"
3164+
" c++;\n"
3165+
"}\n";
3166+
values = tokenValues(code, "c ++ ; }");
3167+
ASSERT_EQUALS(true, values.empty());
3168+
3169+
code = "void b(bool d, bool e) {\n"
3170+
" int c;\n"
3171+
" if (d)\n"
3172+
" c = 0;\n"
3173+
" if (e)\n"
3174+
" return;\n"
3175+
" c++;\n"
3176+
"}\n";
3177+
values = tokenValues(code, "c ++ ; }");
3178+
ASSERT_EQUALS(true, values.empty());
3179+
3180+
code = "void b(bool d, bool e) {\n"
3181+
" int c;\n"
3182+
" if (d)\n"
3183+
" c = 0;\n"
3184+
" if (e)\n"
3185+
" exit();\n"
3186+
" c++;\n"
3187+
"}\n";
3188+
values = tokenValues(code, "c ++ ; }");
3189+
ASSERT_EQUALS(true, values.empty());
3190+
3191+
code = "void b(bool d, bool e) {\n"
3192+
" int c;\n"
3193+
" if (d)\n"
3194+
" c = 0;\n"
3195+
" else if (!d)\n"
3196+
" c = 0;\n"
3197+
" c++;\n"
3198+
"}\n";
3199+
values = tokenValues(code, "c ++ ; }");
3200+
ASSERT_EQUALS(true, values.size() == 2);
3201+
ASSERT_EQUALS(true, values.front().isUninitValue() || values.back().isUninitValue());
3202+
ASSERT_EQUALS(true, values.front().isPossible() || values.back().isPossible());
3203+
ASSERT_EQUALS(true, values.front().intvalue == 0 || values.back().intvalue == 0);
31403204
}
31413205
};
31423206

0 commit comments

Comments
 (0)