ValueFlow: analysis in condition.
This commit is contained in:
parent
dec251ac44
commit
ef81bc363a
|
@ -815,6 +815,37 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
values.push_back(ValueFlow::Value(tok, numtok ? MathLib::toLongNumber(numtok->str()) : 0LL));
|
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();
|
const Token *top = tok->astTop();
|
||||||
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
|
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
|
||||||
// does condition reassign variable?
|
// does condition reassign variable?
|
||||||
|
|
|
@ -1059,7 +1059,7 @@ private:
|
||||||
" p = q;\n"
|
" p = q;\n"
|
||||||
" if (p || *p) { }\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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -777,6 +777,19 @@ private:
|
||||||
" a = x;\n"
|
" a = x;\n"
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
|
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() {
|
void valueFlowBitAnd() {
|
||||||
|
|
Loading…
Reference in New Issue