ValueFlow: analysis in condition.

This commit is contained in:
Daniel Marjamäki 2014-06-19 17:29:41 +02:00
parent dec251ac44
commit ef81bc363a
3 changed files with 45 additions and 1 deletions

View File

@ -815,6 +815,37 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
std::list<ValueFlow::Value> values;
values.push_back(ValueFlow::Value(tok, numtok ? MathLib::toLongNumber(numtok->str()) : 0LL));
if (Token::Match(tok->astParent(), "%oror%|&&")) {
Token *parent = const_cast<Token*>(tok->astParent());
const std::string &op(parent->str());
if (parent->astOperand1() == tok &&
((op == "&&" && Token::Match(tok, "==|>=|<=|!")) ||
(op == "||" && Token::Match(tok, "%var%|!=")))) {
bool assign = false;
for (; !assign && parent && parent->str() == op; parent = const_cast<Token*>(parent->astParent())) {
std::stack<Token *> tokens;
tokens.push(const_cast<Token*>(parent->astOperand2()));
while (!tokens.empty()) {
Token *rhstok = tokens.top();
tokens.pop();
if (!rhstok)
continue;
tokens.push(const_cast<Token*>(rhstok->astOperand1()));
tokens.push(const_cast<Token*>(rhstok->astOperand2()));
if (rhstok->varId() == varid)
setTokenValue(rhstok, values.front());
if (Token::Match(rhstok, "++|--|=") && Token::Match(rhstok->astOperand1(),"%varid%",varid)) {
assign = true;
break;
}
}
while (parent->astParent() && parent == parent->astParent()->astOperand2())
parent = const_cast<Token*>(parent->astParent());
}
}
}
const Token *top = tok->astTop();
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
// does condition reassign variable?

View File

@ -1059,7 +1059,7 @@ private:
" p = q;\n"
" if (p || *p) { }\n"
"}");
TODO_ASSERT_EQUALS("error", "", errout.str());
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:5]: (warning) Possible null pointer dereference: p - otherwise it is redundant to check it against null.\n", errout.str());
}
}

View File

@ -777,6 +777,19 @@ private:
" a = x;\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
// In condition, after && and ||
code = "void f(int x) {\n"
" a = (x != 3 ||\n"
" x);\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
code = "void f(int x) {\n"
" a = (x == 4 &&\n"
" x);\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 4));
}
void valueFlowBitAnd() {