ValueFlow: allow more value types

This commit is contained in:
Daniel Marjamäki 2016-11-13 22:33:39 +01:00
parent 7ebfb10edd
commit 4732667488
7 changed files with 89 additions and 50 deletions

View File

@ -121,7 +121,7 @@ bool CheckAutoVariables::isAutoVarArray(const Token *tok)
if (var->isPointer() && !var->isArgument()) { if (var->isPointer() && !var->isArgument()) {
for (std::list<ValueFlow::Value>::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) {
const ValueFlow::Value &val = *it; const ValueFlow::Value &val = *it;
if (val.tokvalue && isAutoVarArray(val.tokvalue)) if (val.isTokValue() && isAutoVarArray(val.tokvalue))
return true; return true;
} }
} }

View File

@ -1134,7 +1134,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
continue; continue;
for (std::list<ValueFlow::Value>::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) {
if (!it->tokvalue) if (!it->isTokValue() || !it->tokvalue)
continue; continue;
const Variable *var = it->tokvalue->variable(); const Variable *var = it->tokvalue->variable();
if (var && var->isArray()) { if (var && var->isArray()) {

View File

@ -475,7 +475,7 @@ static bool findFormat(unsigned int arg, const Token *firstArg,
argTok->variable()->dimensionKnown(0) && argTok->variable()->dimensionKnown(0) &&
argTok->variable()->dimension(0) != 0))) { argTok->variable()->dimension(0) != 0))) {
*formatArgTok = argTok->nextArgument(); *formatArgTok = argTok->nextArgument();
if (argTok->values.size() >= 1 && argTok->values.front().tokvalue && argTok->values.front().tokvalue->tokType() == Token::eString) if (!argTok->values.empty() && argTok->values.front().isTokValue() && argTok->values.front().tokvalue && argTok->values.front().tokvalue->tokType() == Token::eString)
*formatStringTok = argTok->values.front().tokvalue; *formatStringTok = argTok->values.front().tokvalue;
return true; return true;
} }

View File

@ -1325,9 +1325,9 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
for (std::list<ValueFlow::Value>::const_iterator it=tok->values.begin(); it!=tok->values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it=tok->values.begin(); it!=tok->values.end(); ++it) {
if (xml) { if (xml) {
out << " <value "; out << " <value ";
if (it->tokvalue) if (it->isTokValue())
out << "tokvalue=\"" << it->tokvalue << '\"'; out << "tokvalue=\"" << it->tokvalue << '\"';
else else if (it->isIntValue())
out << "intvalue=\"" << it->intvalue << '\"'; out << "intvalue=\"" << it->intvalue << '\"';
if (it->condition) if (it->condition)
out << " condition-line=\"" << it->condition->linenr() << '\"'; out << " condition-line=\"" << it->condition->linenr() << '\"';
@ -1341,9 +1341,9 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
else { else {
if (it != tok->values.begin()) if (it != tok->values.begin())
out << ","; out << ",";
if (it->tokvalue) if (it->isTokValue())
out << it->tokvalue->str(); out << it->tokvalue->str();
else else if (it->isIntValue())
out << it->intvalue; out << it->intvalue;
} }
} }
@ -1363,7 +1363,7 @@ const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Sett
const ValueFlow::Value *ret = nullptr; const ValueFlow::Value *ret = nullptr;
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
if (it->intvalue <= val && !it->tokvalue) { if (it->isIntValue() && it->intvalue <= val) {
if (!ret || ret->inconclusive || (ret->condition && !it->inconclusive)) if (!ret || ret->inconclusive || (ret->condition && !it->inconclusive))
ret = &(*it); ret = &(*it);
if (!ret->inconclusive && !ret->condition) if (!ret->inconclusive && !ret->condition)
@ -1384,7 +1384,7 @@ const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Sett
const ValueFlow::Value *ret = nullptr; const ValueFlow::Value *ret = nullptr;
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
if (it->intvalue >= val && !it->tokvalue) { if (it->isIntValue() && it->intvalue >= val) {
if (!ret || ret->inconclusive || (ret->condition && !it->inconclusive)) if (!ret || ret->inconclusive || (ret->condition && !it->inconclusive))
ret = &(*it); ret = &(*it);
if (!ret->inconclusive && !ret->condition) if (!ret->inconclusive && !ret->condition)
@ -1406,7 +1406,7 @@ const Token *Token::getValueTokenMinStrSize() const
std::size_t minsize = ~0U; std::size_t minsize = ~0U;
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
if (it->tokvalue && it->tokvalue->tokType() == Token::eString) { if (it->isTokValue() && it->tokvalue && it->tokvalue->tokType() == Token::eString) {
std::size_t size = getStrSize(it->tokvalue); std::size_t size = getStrSize(it->tokvalue);
if (!ret || size < minsize) { if (!ret || size < minsize) {
minsize = size; minsize = size;
@ -1423,7 +1423,7 @@ const Token *Token::getValueTokenMaxStrLength() const
std::size_t maxlength = 0U; std::size_t maxlength = 0U;
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
if (it->tokvalue && it->tokvalue->tokType() == Token::eString) { if (it->isTokValue() && it->tokvalue && it->tokvalue->tokType() == Token::eString) {
std::size_t length = getStrLength(it->tokvalue); std::size_t length = getStrLength(it->tokvalue);
if (!ret || length > maxlength) { if (!ret || length > maxlength) {
maxlength = length; maxlength = length;
@ -1448,7 +1448,7 @@ const Token *Token::getValueTokenDeadPointer() const
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
// Is this a pointer alias? // Is this a pointer alias?
if (!it->tokvalue || it->tokvalue->str() != "&") if (!it->isTokValue() || (it->tokvalue && it->tokvalue->str() != "&"))
continue; continue;
// Get variable // Get variable
const Token *vartok = it->tokvalue->astOperand1(); const Token *vartok = it->tokvalue->astOperand1();

View File

@ -749,13 +749,13 @@ public:
std::list<ValueFlow::Value> values; std::list<ValueFlow::Value> values;
bool hasKnownIntValue() const { bool hasKnownIntValue() const {
return values.size() == 1U && values.front().isKnown() && values.front().tokvalue == nullptr; return values.size() == 1U && values.front().isKnown() && values.front().isIntValue();
} }
const ValueFlow::Value * getValue(const MathLib::bigint val) const { const ValueFlow::Value * getValue(const MathLib::bigint val) const {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
if (it->intvalue == val && !it->tokvalue) if (it->isIntValue() && it->intvalue == val)
return &(*it); return &(*it);
} }
return nullptr; return nullptr;
@ -765,7 +765,7 @@ public:
const ValueFlow::Value *ret = nullptr; const ValueFlow::Value *ret = nullptr;
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) { for (it = values.begin(); it != values.end(); ++it) {
if (it->tokvalue) if (!it->isIntValue())
continue; continue;
if ((!ret || it->intvalue > ret->intvalue) && if ((!ret || it->intvalue > ret->intvalue) &&
((it->condition != nullptr) == condition)) ((it->condition != nullptr) == condition))

View File

@ -32,12 +32,15 @@ namespace {
std::map<unsigned int, const Token *> tokvalues; std::map<unsigned int, const Token *> tokvalues;
void setValue(unsigned int varid, const ValueFlow::Value &value) { void setValue(unsigned int varid, const ValueFlow::Value &value) {
if (value.tokvalue) { switch (value.valueType) {
intvalues.erase(varid); case ValueFlow::Value::INT:
tokvalues[varid] = value.tokvalue;
} else {
intvalues[varid] = value.intvalue; intvalues[varid] = value.intvalue;
tokvalues.erase(varid); tokvalues.erase(varid);
break;
case ValueFlow::Value::TOK:
intvalues.erase(varid);
tokvalues[varid] = value.tokvalue;
break;
} }
} }
@ -257,10 +260,10 @@ static bool addValue(Token *tok, const ValueFlow::Value &value)
if (it->intvalue != value.intvalue) if (it->intvalue != value.intvalue)
continue; continue;
// different tokvalue => continue // different types => continue
if ((it->tokvalue == nullptr) != (value.tokvalue == nullptr)) if (it->valueType != value.valueType)
continue; continue;
if ((value.tokvalue != nullptr) && (it->tokvalue != value.tokvalue) && (it->tokvalue->str() != value.tokvalue->str())) if (value.isTokValue() && (it->tokvalue != value.tokvalue) && (it->tokvalue->str() != value.tokvalue->str()))
continue; continue;
// same value, but old value is inconclusive so replace it // same value, but old value is inconclusive so replace it
@ -309,7 +312,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
// is condition always true/false? // is condition always true/false?
if (parent->astOperand1()->values.size() == 1U && parent->astOperand1()->values.front().isKnown()) { if (parent->astOperand1()->values.size() == 1U && parent->astOperand1()->values.front().isKnown()) {
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.isTokValue() || (condvalue.isIntValue() && condvalue.intvalue != 0));
if (cond && !tok->astOperand1()) { // true condition, no second operator if (cond && !tok->astOperand1()) { // true condition, no second operator
setTokenValue(parent, condvalue, settings); setTokenValue(parent, condvalue, settings);
} else { } else {
@ -361,20 +364,20 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
parent->astOperand2()->values.front().isKnown())); parent->astOperand2()->values.front().isKnown()));
// 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.isIntValue() && value.intvalue==0) {
setTokenValue(parent, value, settings); setTokenValue(parent, value, settings);
return; return;
} }
std::list<ValueFlow::Value>::const_iterator value1, value2; std::list<ValueFlow::Value>::const_iterator value1, value2;
for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) { for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) {
if (value1->tokvalue && (!parent->isComparisonOp() || value1->tokvalue->tokType() != Token::eString)) if (value1->isTokValue() && (!parent->isComparisonOp() || value1->tokvalue->tokType() != Token::eString))
continue; continue;
for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) { for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) {
if (value2->tokvalue && (!parent->isComparisonOp() || value2->tokvalue->tokType() != Token::eString || value1->tokvalue)) if (value2->isTokValue() && (!parent->isComparisonOp() || value2->tokvalue->tokType() != Token::eString || value1->isTokValue()))
continue; continue;
if (known || value1->varId == 0U || value2->varId == 0U || if (known || value1->varId == 0U || value2->varId == 0U ||
(value1->varId == value2->varId && value1->varvalue == value2->varvalue && !value1->tokvalue && !value2->tokvalue)) { (value1->varId == value2->varId && value1->varvalue == value2->varvalue && value1->isIntValue() && value2->isIntValue())) {
ValueFlow::Value result(0); ValueFlow::Value result(0);
result.condition = value1->condition ? value1->condition : value2->condition; result.condition = value1->condition ? value1->condition : value2->condition;
result.inconclusive = value1->inconclusive | value2->inconclusive; result.inconclusive = value1->inconclusive | value2->inconclusive;
@ -409,24 +412,30 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
break; break;
case '=': case '=':
if (parent->str() == "==") { if (parent->str() == "==") {
if (value1->tokvalue || value2->tokvalue) if ((value1->isIntValue() && value2->isTokValue()) ||
(value1->isTokValue() && value2->isIntValue())) {
result.intvalue = 0; result.intvalue = 0;
else setTokenValue(parent, result, settings);
} else if (value1->isIntValue() && value2->isIntValue()) {
result.intvalue = value1->intvalue == value2->intvalue; result.intvalue = value1->intvalue == value2->intvalue;
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
}
} }
break; break;
case '!': case '!':
if (parent->str() == "!=") { if (parent->str() == "!=") {
if (value1->tokvalue || value2->tokvalue) if ((value1->isIntValue() && value2->isTokValue()) ||
(value1->isTokValue() && value2->isIntValue())) {
result.intvalue = 1; result.intvalue = 1;
else setTokenValue(parent, result, settings);
} else if (value1->isIntValue() && value2->isIntValue()) {
result.intvalue = value1->intvalue != value2->intvalue; result.intvalue = value1->intvalue != value2->intvalue;
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
}
} }
break; break;
case '>': case '>':
if (value1->tokvalue || value2->tokvalue) if (!value1->isIntValue() || !value2->isIntValue())
break; break;
if (parent->str() == ">") if (parent->str() == ">")
result.intvalue = value1->intvalue > value2->intvalue; result.intvalue = value1->intvalue > value2->intvalue;
@ -439,7 +448,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
break; break;
case '<': case '<':
if (value1->tokvalue || value2->tokvalue) if (!value1->isIntValue() || !value2->isIntValue())
break; break;
if (parent->str() == "<") if (parent->str() == "<")
result.intvalue = value1->intvalue < value2->intvalue; result.intvalue = value1->intvalue < value2->intvalue;
@ -452,6 +461,8 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
break; break;
case '&': case '&':
if (!value1->isIntValue() || !value2->isIntValue())
break;
if (parent->str() == "&") if (parent->str() == "&")
result.intvalue = value1->intvalue & value2->intvalue; result.intvalue = value1->intvalue & value2->intvalue;
else else
@ -459,6 +470,8 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
break; break;
case '|': case '|':
if (!value1->isIntValue() || !value2->isIntValue())
break;
if (parent->str() == "|") if (parent->str() == "|")
result.intvalue = value1->intvalue | value2->intvalue; result.intvalue = value1->intvalue | value2->intvalue;
else else
@ -466,6 +479,8 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
break; break;
case '^': case '^':
if (!value1->isIntValue() || !value2->isIntValue())
break;
result.intvalue = value1->intvalue ^ value2->intvalue; result.intvalue = value1->intvalue ^ value2->intvalue;
setTokenValue(parent, result, settings); setTokenValue(parent, result, settings);
break; break;
@ -482,7 +497,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
else if (parent->str() == "!") { else if (parent->str() == "!") {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++it) { for (it = tok->values.begin(); it != tok->values.end(); ++it) {
if (it->tokvalue) if (!it->isIntValue())
continue; continue;
ValueFlow::Value v(*it); ValueFlow::Value v(*it);
v.intvalue = !v.intvalue; v.intvalue = !v.intvalue;
@ -494,7 +509,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
else if (parent->str() == "~") { else if (parent->str() == "~") {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++it) { for (it = tok->values.begin(); it != tok->values.end(); ++it) {
if (it->tokvalue) if (!it->isIntValue())
continue; continue;
ValueFlow::Value v(*it); ValueFlow::Value v(*it);
v.intvalue = ~v.intvalue; v.intvalue = ~v.intvalue;
@ -518,7 +533,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
else if (parent->str() == "-" && !parent->astOperand2()) { else if (parent->str() == "-" && !parent->astOperand2()) {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++it) { for (it = tok->values.begin(); it != tok->values.end(); ++it) {
if (it->tokvalue) if (!it->isIntValue())
continue; continue;
ValueFlow::Value v(*it); ValueFlow::Value v(*it);
v.intvalue = -v.intvalue; v.intvalue = -v.intvalue;
@ -530,10 +545,10 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
else if (parent->str() == "[" && parent->astOperand1() && parent->astOperand2()) { else if (parent->str() == "[" && parent->astOperand1() && parent->astOperand2()) {
std::list<ValueFlow::Value>::const_iterator value1, value2; std::list<ValueFlow::Value>::const_iterator value1, value2;
for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) { for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) {
if (!value1->tokvalue) if (!value1->isTokValue())
continue; continue;
for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) { for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) {
if (value2->tokvalue) if (!value2->isIntValue())
continue; continue;
if (value1->varId == 0U || value2->varId == 0U || if (value1->varId == 0U || value2->varId == 0U ||
(value1->varId == value2->varId && value1->varvalue == value2->varvalue)) { (value1->varId == value2->varId && value1->varvalue == value2->varvalue)) {
@ -659,6 +674,7 @@ static void valueFlowString(TokenList *tokenlist)
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
if (tok->tokType() == Token::eString) { if (tok->tokType() == Token::eString) {
ValueFlow::Value strvalue; ValueFlow::Value strvalue;
strvalue.valueType = ValueFlow::Value::TOK;
strvalue.tokvalue = tok; strvalue.tokvalue = tok;
strvalue.setKnown(); strvalue.setKnown();
setTokenValue(tok, strvalue, tokenlist->getSettings()); setTokenValue(tok, strvalue, tokenlist->getSettings());
@ -675,6 +691,7 @@ static void valueFlowArray(TokenList *tokenlist)
const std::map<unsigned int, const Token *>::const_iterator it = constantArrays.find(tok->varId()); const std::map<unsigned int, const Token *>::const_iterator it = constantArrays.find(tok->varId());
if (it != constantArrays.end()) { if (it != constantArrays.end()) {
ValueFlow::Value value; ValueFlow::Value value;
value.valueType = ValueFlow::Value::TOK;
value.tokvalue = it->second; value.tokvalue = it->second;
value.setKnown(); value.setKnown();
setTokenValue(tok, value, tokenlist->getSettings()); setTokenValue(tok, value, tokenlist->getSettings());
@ -689,6 +706,7 @@ static void valueFlowArray(TokenList *tokenlist)
tok->astParent()->astOperand1()->variable() && tok->astParent()->astOperand1()->variable() &&
tok->astParent()->astOperand1()->variable()->isPointer()) { tok->astParent()->astOperand1()->variable()->isPointer()) {
ValueFlow::Value value; ValueFlow::Value value;
value.valueType = ValueFlow::Value::TOK;
value.tokvalue = tok; value.tokvalue = tok;
value.setKnown(); value.setKnown();
setTokenValue(tok, value, tokenlist->getSettings()); setTokenValue(tok, value, tokenlist->getSettings());
@ -739,6 +757,7 @@ static void valueFlowPointerAlias(TokenList *tokenlist)
continue; continue;
ValueFlow::Value value; ValueFlow::Value value;
value.valueType = ValueFlow::Value::TOK;
value.tokvalue = tok; value.tokvalue = tok;
setTokenValue(tok, value, tokenlist->getSettings()); setTokenValue(tok, value, tokenlist->getSettings());
} }
@ -1463,7 +1482,7 @@ static bool valueFlowForward(Token * const startToken,
if (!condition || !op2) // Ticket #6713 if (!condition || !op2) // Ticket #6713
continue; continue;
if (condition->values.size() == 1U && condition->values.front().isKnown() && !condition->values.front().tokvalue) { if (condition->hasKnownIntValue()) {
const ValueFlow::Value &condValue = condition->values.front(); const ValueFlow::Value &condValue = condition->values.front();
const Token *expr = (condValue.intvalue != 0) ? op2->astOperand1() : op2->astOperand2(); const Token *expr = (condValue.intvalue != 0) ? op2->astOperand1() : op2->astOperand2();
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
@ -1561,7 +1580,7 @@ static bool valueFlowForward(Token * const startToken,
std::list<ValueFlow::Value>::iterator it; std::list<ValueFlow::Value>::iterator it;
// Erase values that are not int values.. // Erase values that are not int values..
for (it = values.begin(); it != values.end();) { for (it = values.begin(); it != values.end();) {
if (it->tokvalue) if (!it->isIntValue())
it = values.erase(it); it = values.erase(it);
else else
++it; ++it;
@ -1850,7 +1869,7 @@ static void execute(const Token *expr,
if (!expr) if (!expr)
*error = true; *error = true;
else if (expr->values.size() == 1U && expr->values.front().isKnown() && !expr->values.front().tokvalue) { else if (expr->hasKnownIntValue()) {
*result = expr->values.front().intvalue; *result = expr->values.front().intvalue;
} }
@ -2316,7 +2335,7 @@ static void setTokenValues(Token *tok, const std::list<ValueFlow::Value> &values
{ {
for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
const ValueFlow::Value &value = *it; const ValueFlow::Value &value = *it;
if (!value.tokvalue) if (value.isIntValue())
setTokenValue(tok, value, settings); setTokenValue(tok, value, settings);
} }
} }
@ -2337,9 +2356,10 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
if (Token::simpleMatch(tokenList.front(), "strlen ( arg1 )") && arg1) { if (Token::simpleMatch(tokenList.front(), "strlen ( arg1 )") && arg1) {
for (std::list<ValueFlow::Value>::const_iterator it = arg1->values.begin(); it != arg1->values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it = arg1->values.begin(); it != arg1->values.end(); ++it) {
const ValueFlow::Value &value = *it; const ValueFlow::Value &value = *it;
if (value.tokvalue && value.tokvalue->tokType() == Token::eString) { if (value.isTokValue() && value.tokvalue->tokType() == Token::eString) {
ValueFlow::Value retval(value); // copy all "inconclusive", "condition", etc attributes ValueFlow::Value retval(value); // copy all "inconclusive", "condition", etc attributes
// set return value.. // set return value..
retval.valueType = ValueFlow::Value::INT;
retval.tokvalue = nullptr; retval.tokvalue = nullptr;
retval.intvalue = Token::getStrLength(value.tokvalue); retval.intvalue = Token::getStrLength(value.tokvalue);
setTokenValue(tok, retval, settings); setTokenValue(tok, retval, settings);

View File

@ -33,13 +33,24 @@ class Settings;
namespace ValueFlow { namespace ValueFlow {
class CPPCHECKLIB Value { class CPPCHECKLIB Value {
public: public:
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) : valueType(INT), 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) : valueType(INT), 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 { bool operator==(const Value &rhs) const {
return intvalue == rhs.intvalue && if (valueType != rhs.valueType)
tokvalue == rhs.tokvalue && return false;
varvalue == rhs.varvalue && switch (valueType) {
case INT:
if (intvalue != rhs.intvalue)
return false;
break;
case TOK:
if (tokvalue != rhs.tokvalue)
return false;
break;
};
return varvalue == rhs.varvalue &&
condition == rhs.condition && condition == rhs.condition &&
varId == rhs.varId && varId == rhs.varId &&
conditional == rhs.conditional && conditional == rhs.conditional &&
@ -48,6 +59,14 @@ namespace ValueFlow {
valueKind == rhs.valueKind; valueKind == rhs.valueKind;
} }
enum ValueType { INT, TOK } valueType;
bool isIntValue() const {
return valueType == INT;
}
bool isTokValue() const {
return valueType == TOK;
}
/** int value */ /** int value */
long long intvalue; long long intvalue;