ValueFlow: better handling of ? when condition result is known
This commit is contained in:
parent
453b5577cd
commit
1f98af654a
|
@ -363,33 +363,42 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2()) {
|
else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2()) {
|
||||||
// is condition only depending on 1 variable?
|
// is condition always true/false?
|
||||||
std::stack<const Token*> tokens;
|
if (parent->astOperand1()->values.size() == 1U && parent->astOperand1()->values.front().isKnown()) {
|
||||||
tokens.push(parent->astOperand1());
|
const ValueFlow::Value &condvalue = parent->astOperand1()->values.front();
|
||||||
unsigned int varId = 0;
|
const bool cond(condvalue.tokvalue || condvalue.intvalue != 0);
|
||||||
while (!tokens.empty()) {
|
const std::list<ValueFlow::Value> &values = cond ? tok->astOperand1()->values : tok->astOperand2()->values;
|
||||||
const Token *t = tokens.top();
|
if (std::find(values.begin(), values.end(), value) != values.end())
|
||||||
tokens.pop();
|
setTokenValue(parent, value);
|
||||||
if (!t)
|
} else {
|
||||||
continue;
|
// is condition only depending on 1 variable?
|
||||||
tokens.push(t->astOperand1());
|
std::stack<const Token*> tokens;
|
||||||
tokens.push(t->astOperand2());
|
tokens.push(parent->astOperand1());
|
||||||
if (t->varId()) {
|
unsigned int varId = 0;
|
||||||
if (varId > 0 || value.varId != 0U)
|
while (!tokens.empty()) {
|
||||||
return;
|
const Token *t = tokens.top();
|
||||||
varId = t->varId();
|
tokens.pop();
|
||||||
} else if (t->str() == "(" && Token::Match(t->previous(), "%name%"))
|
if (!t)
|
||||||
return; // function call
|
continue;
|
||||||
|
tokens.push(t->astOperand1());
|
||||||
|
tokens.push(t->astOperand2());
|
||||||
|
if (t->varId()) {
|
||||||
|
if (varId > 0 || value.varId != 0U)
|
||||||
|
return;
|
||||||
|
varId = t->varId();
|
||||||
|
} else if (t->str() == "(" && Token::Match(t->previous(), "%name%"))
|
||||||
|
return; // function call
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueFlow::Value v(value);
|
||||||
|
v.conditional = true;
|
||||||
|
v.changeKnownToPossible();
|
||||||
|
|
||||||
|
if (varId)
|
||||||
|
v.varId = varId;
|
||||||
|
|
||||||
|
setTokenValue(parent, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueFlow::Value v(value);
|
|
||||||
v.conditional = true;
|
|
||||||
v.changeKnownToPossible();
|
|
||||||
|
|
||||||
if (varId)
|
|
||||||
v.varId = varId;
|
|
||||||
|
|
||||||
setTokenValue(parent, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculations..
|
// Calculations..
|
||||||
|
|
|
@ -36,6 +36,18 @@ namespace ValueFlow {
|
||||||
explicit Value(long long val = 0) : intvalue(val), tokvalue(nullptr), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
explicit Value(long long val = 0) : intvalue(val), tokvalue(nullptr), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
||||||
Value(const Token *c, long long val) : intvalue(val), tokvalue(nullptr), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
Value(const Token *c, long long val) : intvalue(val), tokvalue(nullptr), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
||||||
|
|
||||||
|
bool operator==(const Value &rhs) const {
|
||||||
|
return intvalue == rhs.intvalue &&
|
||||||
|
tokvalue == rhs.tokvalue &&
|
||||||
|
varvalue == rhs.varvalue &&
|
||||||
|
condition == rhs.condition &&
|
||||||
|
varId == rhs.varId &&
|
||||||
|
conditional == rhs.conditional &&
|
||||||
|
inconclusive == rhs.inconclusive &&
|
||||||
|
defaultArg == rhs.defaultArg &&
|
||||||
|
valueKind == rhs.valueKind;
|
||||||
|
}
|
||||||
|
|
||||||
/** int value */
|
/** int value */
|
||||||
long long intvalue;
|
long long intvalue;
|
||||||
|
|
||||||
|
|
|
@ -327,6 +327,11 @@ private:
|
||||||
ASSERT_EQUALS(2, values.front().intvalue);
|
ASSERT_EQUALS(2, values.front().intvalue);
|
||||||
ASSERT_EQUALS(3, values.back().intvalue);
|
ASSERT_EQUALS(3, values.back().intvalue);
|
||||||
|
|
||||||
|
code = "x = (2<5) ? 2 : 3;\n";
|
||||||
|
values = tokenValues(code, "?");
|
||||||
|
ASSERT_EQUALS(1U, values.size());
|
||||||
|
ASSERT_EQUALS(2, values.front().intvalue);
|
||||||
|
|
||||||
// !
|
// !
|
||||||
code = "void f(int x) {\n"
|
code = "void f(int x) {\n"
|
||||||
" a = !x;\n"
|
" a = !x;\n"
|
||||||
|
|
Loading…
Reference in New Issue