ValueFlow: handle ~ in setTokenValue

This commit is contained in:
Daniel Marjamäki 2016-11-05 09:29:22 +01:00
parent 40bf269ea0
commit 2885a75ea6
2 changed files with 64 additions and 30 deletions

View File

@ -287,7 +287,7 @@ static bool addValue(Token *tok, const ValueFlow::Value &value)
} }
/** set ValueFlow value and perform calculations if possible */ /** set ValueFlow value and perform calculations if possible */
static void setTokenValue(Token* tok, const ValueFlow::Value &value) static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Settings *settings=nullptr)
{ {
if (!addValue(tok,value)) if (!addValue(tok,value))
return; return;
@ -298,11 +298,11 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
// Cast.. // Cast..
if (parent->str() == "(" && tok == parent->link()->next()) { if (parent->str() == "(" && tok == parent->link()->next()) {
setTokenValue(parent,value); setTokenValue(parent,value,settings);
} }
else if (parent->str() == ":") { else if (parent->str() == ":") {
setTokenValue(parent,value); setTokenValue(parent,value,settings);
} }
else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2() && parent->astOperand1()) { else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2() && parent->astOperand1()) {
@ -311,12 +311,12 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
const ValueFlow::Value &condvalue = parent->astOperand1()->values.front(); const ValueFlow::Value &condvalue = parent->astOperand1()->values.front();
const bool cond(condvalue.tokvalue || condvalue.intvalue != 0); const bool cond(condvalue.tokvalue || condvalue.intvalue != 0);
if (cond && !tok->astOperand1()) { // true condition, no second operator if (cond && !tok->astOperand1()) { // true condition, no second operator
setTokenValue(parent, condvalue); setTokenValue(parent, condvalue, settings);
} else { } else {
const Token *op = cond ? tok->astOperand1() : tok->astOperand2(); const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
const std::list<ValueFlow::Value> &values = op->values; const std::list<ValueFlow::Value> &values = op->values;
if (std::find(values.begin(), values.end(), value) != values.end()) if (std::find(values.begin(), values.end(), value) != values.end())
setTokenValue(parent, value); setTokenValue(parent, value, settings);
} }
} else { } else {
// is condition only depending on 1 variable? // is condition only depending on 1 variable?
@ -345,7 +345,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
if (varId) if (varId)
v.varId = varId; v.varId = varId;
setTokenValue(parent, v); setTokenValue(parent, v, settings);
} }
} }
@ -360,7 +360,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
// known result when a operand is 0. // known result when a operand is 0.
if (Token::Match(parent, "[&*]") && value.isKnown() && value.tokvalue==nullptr && value.intvalue==0) { if (Token::Match(parent, "[&*]") && value.isKnown() && value.tokvalue==nullptr && value.intvalue==0) {
setTokenValue(parent, value); setTokenValue(parent, value, settings);
return; return;
} }
@ -383,27 +383,27 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
switch (parent->str()[0]) { switch (parent->str()[0]) {
case '+': case '+':
result.intvalue = value1->intvalue + value2->intvalue; result.intvalue = value1->intvalue + value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '-': case '-':
result.intvalue = value1->intvalue - value2->intvalue; result.intvalue = value1->intvalue - value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '*': case '*':
result.intvalue = value1->intvalue * value2->intvalue; result.intvalue = value1->intvalue * value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '/': case '/':
if (value2->intvalue == 0) if (value2->intvalue == 0)
break; break;
result.intvalue = value1->intvalue / value2->intvalue; result.intvalue = value1->intvalue / value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '%': case '%':
if (value2->intvalue == 0) if (value2->intvalue == 0)
break; break;
result.intvalue = value1->intvalue % value2->intvalue; result.intvalue = value1->intvalue % value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '=': case '=':
if (parent->str() == "==") { if (parent->str() == "==") {
@ -411,7 +411,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
result.intvalue = 0; result.intvalue = 0;
else else
result.intvalue = value1->intvalue == value2->intvalue; result.intvalue = value1->intvalue == value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
} }
break; break;
case '!': case '!':
@ -420,7 +420,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
result.intvalue = 1; result.intvalue = 1;
else else
result.intvalue = value1->intvalue != value2->intvalue; result.intvalue = value1->intvalue != value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
} }
break; break;
case '>': case '>':
@ -430,9 +430,11 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
result.intvalue = value1->intvalue > value2->intvalue; result.intvalue = value1->intvalue > value2->intvalue;
else if (parent->str() == ">=") else if (parent->str() == ">=")
result.intvalue = value1->intvalue >= value2->intvalue; result.intvalue = value1->intvalue >= value2->intvalue;
else if (parent->str() == ">>")
result.intvalue = value1->intvalue >> value2->intvalue;
else else
break; break;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '<': case '<':
if (value1->tokvalue || value2->tokvalue) if (value1->tokvalue || value2->tokvalue)
@ -441,27 +443,29 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
result.intvalue = value1->intvalue < value2->intvalue; result.intvalue = value1->intvalue < value2->intvalue;
else if (parent->str() == "<=") else if (parent->str() == "<=")
result.intvalue = value1->intvalue <= value2->intvalue; result.intvalue = value1->intvalue <= value2->intvalue;
else if (parent->str() == "<<")
result.intvalue = value1->intvalue << value2->intvalue;
else else
break; break;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '&': case '&':
if (parent->str() == "&") if (parent->str() == "&")
result.intvalue = value1->intvalue & value2->intvalue; result.intvalue = value1->intvalue & value2->intvalue;
else else
result.intvalue = value1->intvalue && value2->intvalue; result.intvalue = value1->intvalue && value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '|': case '|':
if (parent->str() == "|") if (parent->str() == "|")
result.intvalue = value1->intvalue | value2->intvalue; result.intvalue = value1->intvalue | value2->intvalue;
else else
result.intvalue = value1->intvalue || value2->intvalue; result.intvalue = value1->intvalue || value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
case '^': case '^':
result.intvalue = value1->intvalue ^ value2->intvalue; result.intvalue = value1->intvalue ^ value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result, settings);
break; break;
default: default:
// unhandled operator, do nothing // unhandled operator, do nothing
@ -480,7 +484,30 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
continue; continue;
ValueFlow::Value v(*it); ValueFlow::Value v(*it);
v.intvalue = !v.intvalue; v.intvalue = !v.intvalue;
setTokenValue(parent, v); setTokenValue(parent, v, settings);
}
}
// ~
else if (parent->str() == "~") {
std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++it) {
if (it->tokvalue)
continue;
ValueFlow::Value v(*it);
v.intvalue = ~v.intvalue;
unsigned int bits = 0;
if (tok->valueType() &&
tok->valueType()->sign == ValueType::Sign::UNSIGNED &&
tok->valueType()->pointer == 0) {
if (tok->valueType()->type == ValueType::Type::INT)
bits = settings->int_bit;
else if (tok->valueType()->type == ValueType::Type::LONG)
bits = settings->long_bit;
}
if (bits > 0 && bits < 64)
v.intvalue &= (1ULL<<bits) - 1ULL;
setTokenValue(parent, v, settings);
} }
} }
@ -492,7 +519,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
continue; continue;
ValueFlow::Value v(*it); ValueFlow::Value v(*it);
v.intvalue = -v.intvalue; v.intvalue = -v.intvalue;
setTokenValue(parent, v); setTokenValue(parent, v, settings);
} }
} }
@ -522,7 +549,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
setTokenValue(parent, result); setTokenValue(parent, result);
} else if (index >= 0 && index < s.size()) { } else if (index >= 0 && index < s.size()) {
result.intvalue = s[index]; result.intvalue = s[index];
setTokenValue(parent, result); setTokenValue(parent, result, settings);
} }
} else if (value1->tokvalue->str() == "{") { } else if (value1->tokvalue->str() == "{") {
MathLib::bigint index = value2->intvalue; MathLib::bigint index = value2->intvalue;
@ -536,7 +563,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
} }
if (Token::Match(element, "%num% [,}]")) { if (Token::Match(element, "%num% [,}]")) {
result.intvalue = MathLib::toLongNumber(element->str()); result.intvalue = MathLib::toLongNumber(element->str());
setTokenValue(parent, result); setTokenValue(parent, result, settings);
} }
} }
} }
@ -552,15 +579,15 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
ValueFlow::Value value(MathLib::toLongNumber(tok->str())); ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (tok->enumerator() && tok->enumerator()->value_known) { } else if (tok->enumerator() && tok->enumerator()->value_known) {
ValueFlow::Value value(tok->enumerator()->value); ValueFlow::Value value(tok->enumerator()->value);
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) { } else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
ValueFlow::Value value(0); ValueFlow::Value value(0);
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (Token::simpleMatch(tok, "sizeof (") && tok->tokAt(2)) { } else if (Token::simpleMatch(tok, "sizeof (") && tok->tokAt(2)) {
const Token *tok2 = tok->tokAt(2); const Token *tok2 = tok->tokAt(2);
if (tok2->enumerator() && tok2->enumerator()->scope) { if (tok2->enumerator() && tok2->enumerator()->scope) {
@ -575,8 +602,8 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
} }
ValueFlow::Value value(size); ValueFlow::Value value(size);
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value); setTokenValue(const_cast<Token *>(tok), value, settings);
setTokenValue(const_cast<Token *>(tok->next()), value); setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (tok2->type() && tok2->type()->isEnumType()) { } else if (tok2->type() && tok2->type()->isEnumType()) {
long long size = settings->sizeof_int; long long size = settings->sizeof_int;
if (tok2->type()->classScope) { if (tok2->type()->classScope) {
@ -591,8 +618,8 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
} }
ValueFlow::Value value(size); ValueFlow::Value value(size);
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value); setTokenValue(const_cast<Token *>(tok), value, settings);
setTokenValue(const_cast<Token *>(tok->next()), value); setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} }
// skip over enum // skip over enum
tok = tok->linkAt(1); tok = tok->linkAt(1);

View File

@ -339,6 +339,13 @@ private:
ASSERT_EQUALS(1U, values.size()); ASSERT_EQUALS(1U, values.size());
ASSERT_EQUALS(123, values.empty() ? 0 : values.front().intvalue); ASSERT_EQUALS(123, values.empty() ? 0 : values.front().intvalue);
// ~
code = "x = ~0U;";
settings.platform(cppcheck::Platform::Native); // ensure platform is native
values = tokenValues(code,"~");
ASSERT_EQUALS(1U, values.size());
ASSERT_EQUALS(~0U, values.back().intvalue);
// ! // !
code = "void f(int x) {\n" code = "void f(int x) {\n"
" a = !x;\n" " a = !x;\n"