ValueFlow: better analysis in valueFlowAfterCondition of 'if|while ( %var% )' etc

This commit is contained in:
Daniel Marjamäki 2014-06-18 06:57:48 +02:00
parent 9999ce9468
commit 13761927ff
2 changed files with 21 additions and 2 deletions

View File

@ -780,14 +780,23 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
} }
if (!vartok->isName() || !numtok->isNumber()) if (!vartok->isName() || !numtok->isNumber())
continue; continue;
} else if (tok->str() == "!") { } else if (tok->str() == "!") {
vartok = tok->astOperand1(); vartok = tok->astOperand1();
numtok = nullptr; numtok = nullptr;
if (!vartok || !vartok->isName()) if (!vartok || !vartok->isName())
continue; continue;
} else if (tok->isName() &&
(Token::Match(tok->astParent(), "%oror%|&&") ||
Token::Match(tok->tokAt(-2), "if|while ( %var% )"))) {
vartok = tok;
numtok = nullptr;
} else { } else {
continue; continue;
} }
const unsigned int varid = vartok->varId(); const unsigned int varid = vartok->varId();
if (varid == 0U) if (varid == 0U)
continue; continue;
@ -821,11 +830,11 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
Token *startToken = nullptr; Token *startToken = nullptr;
if (Token::Match(tok, "==|>=|<=|!") && Token::simpleMatch(top->link(), ") {")) if (Token::Match(tok, "==|>=|<=|!") && Token::simpleMatch(top->link(), ") {"))
startToken = top->link()->next(); startToken = top->link()->next();
else if (tok->str() == "!=" && Token::simpleMatch(top->link()->linkAt(1), "} else {")) else if (Token::Match(tok, "%var%|!=") && Token::simpleMatch(top->link()->linkAt(1), "} else {"))
startToken = top->link()->linkAt(1)->tokAt(2); startToken = top->link()->linkAt(1)->tokAt(2);
bool ok = true; bool ok = true;
if (startToken) if (startToken)
ok &= valueFlowForward(startToken->next(), startToken->link(), var, varid, values, true, tokenlist, errorLogger, settings); ok = valueFlowForward(startToken->next(), startToken->link(), var, varid, values, true, tokenlist, errorLogger, settings);
// After conditional code.. // After conditional code..
if (ok && !scopeEnd.empty() && Token::simpleMatch(top->link(), ") {")) { if (ok && !scopeEnd.empty() && Token::simpleMatch(top->link(), ") {")) {

View File

@ -761,6 +761,16 @@ private:
"}"; "}";
ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 2U, 0));
// if (var)
code = "void f(int x) {\n"
" if (x) { a = x; }\n" // <- x is not 0
" else { b = x; }\n" // <- x is 0
" c = x;\n" // <- x might be 0
"}";
ASSERT_EQUALS(false, testValueOfX(code, 2U, 0));
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
ASSERT_EQUALS(true, testValueOfX(code, 4U, 0));
// After while // After while
code = "void f(int x) {\n" code = "void f(int x) {\n"
" while (x != 3) {}\n" " while (x != 3) {}\n"