Refactorization: Allocate Token::_values (ValueFlow information) dynamically, reducing size of each token by around 10%

This commit is contained in:
PKEuS 2017-03-27 18:48:34 +02:00
parent 2938278f00
commit 3c8f5b85ae
17 changed files with 190 additions and 152 deletions

View File

@ -87,7 +87,7 @@ static bool match(const Token *tok, const std::string &rhs)
{
if (tok->str() == rhs)
return true;
if (tok->isName() && !tok->varId() && tok->values.size() == 1U && tok->values.front().isKnown() && MathLib::toString(tok->values.front().intvalue) == rhs)
if (tok->isName() && !tok->varId() && tok->values().size() == 1U && tok->values().front().isKnown() && MathLib::toString(tok->values().front().intvalue) == rhs)
return true;
return false;
}

View File

@ -119,7 +119,7 @@ bool CheckAutoVariables::isAutoVarArray(const Token *tok)
// ValueFlow
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;
if (val.isTokValue() && isAutoVarArray(val.tokvalue))
return true;

View File

@ -1132,7 +1132,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
if (!value)
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->isTokValue() || !it->tokvalue)
continue;
const Variable *var = it->tokvalue->variable();

View File

@ -261,8 +261,8 @@ void CheckCondition::checkBadBitmaskCheck()
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while")) ||
(parent->str() == "return" && parent->astOperand1() == tok && inBooleanFunction(tok));
const bool isTrue = (tok->astOperand1()->values.size() == 1 && tok->astOperand1()->values.front().intvalue != 0 && tok->astOperand1()->values.front().isKnown()) ||
(tok->astOperand2()->values.size() == 1 && tok->astOperand2()->values.front().intvalue != 0 && tok->astOperand2()->values.front().isKnown());
const bool isTrue = (tok->astOperand1()->values().size() == 1 && tok->astOperand1()->values().front().intvalue != 0 && tok->astOperand1()->values().front().isKnown()) ||
(tok->astOperand2()->values().size() == 1 && tok->astOperand2()->values().front().intvalue != 0 && tok->astOperand2()->values().front().isKnown());
if (isBoolean && isTrue)
badBitmaskCheckError(tok);
@ -1049,7 +1049,7 @@ void CheckCondition::alwaysTrueFalse()
if (isExpandedMacro)
continue;
alwaysTrueFalseError(tok, tok->values.front().intvalue != 0);
alwaysTrueFalseError(tok, tok->values().front().intvalue != 0);
}
}
}

View File

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

View File

@ -547,7 +547,7 @@ void CheckLeakAutoVar::functionCall(const Token *tok, VarInfo *varInfo, const Va
if (arg->str() == "&")
arg = arg->next();
bool isnull = arg->hasKnownIntValue() && arg->values.front().intvalue == 0;
bool isnull = arg->hasKnownIntValue() && arg->values().front().intvalue == 0;
// Is variable allocated?
if (!isnull && (!af || af->arg == argNr))

View File

@ -481,18 +481,18 @@ static bool alwaysTrue(const Token *tok)
{
if (!tok)
return false;
if (tok->values.size() == 1U &&
tok->values.front().intvalue != 0 &&
tok->values.front().isKnown())
if (tok->values().size() == 1U &&
tok->values().front().intvalue != 0 &&
tok->values().front().isKnown())
return true;
if (tok->str() == "||")
return alwaysTrue(tok->astOperand1()) || alwaysTrue(tok->astOperand2());
if (tok->str() == "true")
return true;
return (tok->isComparisonOp() &&
tok->values.size() == 1U &&
tok->values.front().isKnown() &&
tok->values.front().intvalue != 0);
tok->values().size() == 1U &&
tok->values().front().isKnown() &&
tok->values().front().intvalue != 0);
}
bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, const Settings *settings, bool cpp)

View File

@ -284,7 +284,7 @@ void CheckOther::warningOldStylePointerCast()
tok = tok->next();
const Token *p = tok->tokAt(4);
if (p->hasKnownIntValue() && p->values.front().intvalue==0) // Casting nullpointers is safe
if (p->hasKnownIntValue() && p->values().front().intvalue==0) // Casting nullpointers is safe
continue;
// Is "type" a class?

View File

@ -337,7 +337,7 @@ void CheckType::checkFloatToIntegerOverflow()
continue;
const Token *op1 = tok->astOperand1();
for (std::list<ValueFlow::Value>::const_iterator it = op1->values.begin(); it != op1->values.end(); ++it) {
for (std::list<ValueFlow::Value>::const_iterator it = op1->values().begin(); it != op1->values().end(); ++it) {
if (it->valueType != ValueFlow::Value::FLOAT)
continue;
if (it->inconclusive && !_settings->inconclusive)

View File

@ -219,8 +219,8 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::map<unsigned
}
else if (tok->isComparisonOp()) {
if (tok->values.size() == 1U && tok->values.front().isKnown()) {
if (tok->values.front().intvalue)
if (tok->values().size() == 1U && tok->values().front().isKnown()) {
if (tok->values().front().intvalue)
*alwaysTrue = true;
else
*alwaysFalse = true;

View File

@ -1016,7 +1016,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
Token::Match(tok, "%name% ;") &&
tok->varId() == 0 &&
tok->hasKnownIntValue() &&
tok->values.front().intvalue == 0) {
tok->values().front().intvalue == 0) {
variables.use(varid1, tok);
} else {
variables.write(varid1, tok);

View File

@ -1321,8 +1321,8 @@ void SymbolDatabase::createSymbolDatabaseEnums()
ValueFlow::valueFlowConstantFoldAST(rhs, _settings);
// get constant folded value:
if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) {
enumerator.value = rhs->values.front().intvalue;
if (rhs && rhs->values().size() == 1U && rhs->values().front().isKnown()) {
enumerator.value = rhs->values().front().intvalue;
enumerator.value_known = true;
value = enumerator.value + 1;
}
@ -1425,8 +1425,8 @@ void SymbolDatabase::createSymbolDatabaseUnknownArrayDimensions()
ValueFlow::valueFlowConstantFoldAST(rhs, _settings);
// get constant folded value:
if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) {
dimension.num = rhs->values.front().intvalue;
if (rhs && rhs->values().size() == 1U && rhs->values().front().isKnown()) {
dimension.num = rhs->values().front().intvalue;
dimension.known = true;
}
}

View File

@ -50,7 +50,8 @@ Token::Token(Token **t) :
_astOperand2(nullptr),
_astParent(nullptr),
_originalName(nullptr),
valuetype(nullptr)
valuetype(nullptr),
_values(nullptr)
{
}
@ -58,6 +59,7 @@ Token::~Token()
{
delete _originalName;
delete valuetype;
delete _values;
}
void Token::update_property_info()
@ -213,7 +215,7 @@ void Token::swapWithNext()
std::swap(_scope, _next->_scope);
std::swap(_function, _next->_function);
std::swap(_originalName, _next->_originalName);
std::swap(values, _next->values);
std::swap(_values, _next->_values);
std::swap(valuetype, _next->valuetype);
std::swap(_progressValue, _next->_progressValue);
}
@ -236,7 +238,11 @@ void Token::deleteThis()
_originalName = _next->_originalName;
_next->_originalName = nullptr;
}
values = _next->values;
if (_next->_values) {
delete _values;
_values = _next->_values;
_next->_values = nullptr;
}
if (_next->valuetype) {
delete valuetype;
valuetype = _next->valuetype;
@ -261,7 +267,11 @@ void Token::deleteThis()
_originalName = _previous->_originalName;
_previous->_originalName = nullptr;
}
values = _previous->values;
if (_previous->_values) {
delete _values;
_values = _previous->_values;
_previous->_values = nullptr;
}
if (_previous->valuetype) {
delete valuetype;
valuetype = _previous->valuetype;
@ -1233,8 +1243,8 @@ static void astStringXml(const Token *tok, std::size_t indent, std::ostream &out
out << " variable=\"" << tok->variable() << '\"';
if (tok->function())
out << " function=\"" << tok->function() << '\"';
if (!tok->values.empty())
out << " values=\"" << &tok->values << '\"';
if (!tok->values().empty())
out << " values=\"" << &tok->values() << '\"';
if (!tok->astOperand1() && !tok->astOperand2()) {
out << "/>" << std::endl;
@ -1318,19 +1328,19 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
else
out << "\n\n##Value flow" << std::endl;
for (const Token *tok = this; tok; tok = tok->next()) {
if (tok->values.empty())
if (!tok->_values)
continue;
if (xml)
out << " <values id=\"" << &tok->values << "\">" << std::endl;
out << " <values id=\"" << tok->_values << "\">" << std::endl;
else if (line != tok->linenr())
out << "Line " << tok->linenr() << std::endl;
line = tok->linenr();
if (!xml) {
out << " " << tok->str() << (tok->values.front().isKnown() ? " always " : " possible ");
if (tok->values.size() > 1U)
out << " " << tok->str() << (tok->_values->front().isKnown() ? " always " : " possible ");
if (tok->_values->size() > 1U)
out << '{';
}
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) {
out << " <value ";
switch (it->valueType) {
@ -1357,7 +1367,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
}
else {
if (it != tok->values.begin())
if (it != tok->_values->begin())
out << ",";
switch (it->valueType) {
case ValueFlow::Value::INT:
@ -1377,7 +1387,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
}
if (xml)
out << " </values>" << std::endl;
else if (tok->values.size() > 1U)
else if (tok->_values->size() > 1U)
out << '}' << std::endl;
else
out << std::endl;
@ -1388,9 +1398,11 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Settings *settings) const
{
if (!_values)
return nullptr;
const ValueFlow::Value *ret = nullptr;
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->isIntValue() && it->intvalue <= val) {
if (!ret || ret->inconclusive || (ret->condition && !it->inconclusive))
ret = &(*it);
@ -1409,9 +1421,11 @@ const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Sett
const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Settings *settings) const
{
if (!_values)
return nullptr;
const ValueFlow::Value *ret = nullptr;
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->isIntValue() && it->intvalue >= val) {
if (!ret || ret->inconclusive || (ret->condition && !it->inconclusive))
ret = &(*it);
@ -1430,10 +1444,12 @@ const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Sett
const Token *Token::getValueTokenMinStrSize() const
{
if (!_values)
return nullptr;
const Token *ret = nullptr;
std::size_t minsize = ~0U;
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->isTokValue() && it->tokvalue && it->tokvalue->tokType() == Token::eString) {
std::size_t size = getStrSize(it->tokvalue);
if (!ret || size < minsize) {
@ -1447,10 +1463,12 @@ const Token *Token::getValueTokenMinStrSize() const
const Token *Token::getValueTokenMaxStrLength() const
{
if (!_values)
return nullptr;
const Token *ret = nullptr;
std::size_t maxlength = 0U;
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->isTokValue() && it->tokvalue && it->tokvalue->tokType() == Token::eString) {
std::size_t length = getStrLength(it->tokvalue);
if (!ret || length > maxlength) {
@ -1474,7 +1492,7 @@ const Token *Token::getValueTokenDeadPointer() const
const Scope * const functionscope = getfunctionscope(this->scope());
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?
if (!it->isTokValue() || (it->tokvalue && it->tokvalue->str() != "&"))
continue;
@ -1502,6 +1520,61 @@ const Token *Token::getValueTokenDeadPointer() const
return nullptr;
}
bool Token::addValue(const ValueFlow::Value &value)
{
if (value.isKnown() && _values) {
// Clear all other values since value is known
_values->clear();
}
if (_values) {
// Don't handle more than 10 values for performance reasons
// TODO: add setting?
if (_values->size() >= 10U)
return false;
// if value already exists, don't add it again
std::list<ValueFlow::Value>::iterator it;
for (it = _values->begin(); it != _values->end(); ++it) {
// different intvalue => continue
if (it->intvalue != value.intvalue)
continue;
// different types => continue
if (it->valueType != value.valueType)
continue;
if (value.isTokValue() && (it->tokvalue != value.tokvalue) && (it->tokvalue->str() != value.tokvalue->str()))
continue;
// same value, but old value is inconclusive so replace it
if (it->inconclusive && !value.inconclusive) {
*it = value;
if (it->varId == 0)
it->varId = _varId;
break;
}
// Same value already exists, don't add new value
return false;
}
// Add value
if (it == values().end()) {
ValueFlow::Value v(value);
if (v.varId == 0)
v.varId = _varId;
_values->push_back(v);
}
} else {
ValueFlow::Value v(value);
if (v.varId == 0)
v.varId = _varId;
_values = new std::list<ValueFlow::Value>(1, v);
}
return true;
}
void Token::assignProgressValues(Token *tok)
{
unsigned int total_count = 0;

View File

@ -736,6 +736,11 @@ public:
return _originalName ? *_originalName : emptyString;
}
const std::list<ValueFlow::Value>& values() const {
static const std::list<ValueFlow::Value> emptyList;
return _values ? *_values : emptyList;
}
/**
* Sets the original name.
*/
@ -747,16 +752,14 @@ public:
*_originalName = name;
}
/** Values of token */
std::list<ValueFlow::Value> values;
bool hasKnownIntValue() const {
return values.size() == 1U && values.front().isKnown() && values.front().isIntValue();
return _values && _values->size() == 1U && _values->front().isKnown() && _values->front().isIntValue();
}
const ValueFlow::Value * getValue(const MathLib::bigint val) const {
std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) {
if (!_values)
return nullptr;
for (std::list<ValueFlow::Value>::const_iterator it = _values->begin(); it != _values->end(); ++it) {
if (it->isIntValue() && it->intvalue == val)
return &(*it);
}
@ -764,9 +767,10 @@ public:
}
const ValueFlow::Value * getMaxValue(bool condition) const {
if (!_values)
return nullptr;
const ValueFlow::Value *ret = nullptr;
std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) {
for (std::list<ValueFlow::Value>::const_iterator it = _values->begin(); it != _values->end(); ++it) {
if (!it->isIntValue())
continue;
if ((!ret || it->intvalue > ret->intvalue) &&
@ -777,8 +781,9 @@ public:
}
const ValueFlow::Value * getMovedValue() const {
std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) {
if (!_values)
return nullptr;
for (std::list<ValueFlow::Value>::const_iterator it = _values->begin(); it != _values->end(); ++it) {
if (it->isMovedValue() && it->moveKind != ValueFlow::Value::NonMovedVariable)
return &(*it);
}
@ -793,6 +798,9 @@ public:
const Token *getValueTokenDeadPointer() const;
/** Add token value. Return true if value is added. */
bool addValue(const ValueFlow::Value &value);
private:
void next(Token *nextToken) {
@ -903,6 +911,9 @@ private:
// ValueType
ValueType *valuetype;
// ValueFlow
std::list<ValueFlow::Value>* _values;
public:
void astOperand1(Token *tok);
void astOperand2(Token *tok);
@ -936,6 +947,11 @@ public:
_astOperand1 = _astOperand2 = _astParent = nullptr;
}
void clearValueFlow() {
delete _values;
_values = nullptr;
}
std::string astString(const char *sep = "") const {
std::string ret;
if (_astOperand1)

View File

@ -3666,7 +3666,7 @@ bool Tokenizer::simplifyTokenList2()
// Clear AST,ValueFlow. These will be created again at the end of this function.
for (Token *tok = list.front(); tok; tok = tok->next()) {
tok->clearAst();
tok->values.clear();
tok->clearValueFlow();
}
// f(x=g()) => x=g(); f(x)
@ -3904,8 +3904,8 @@ void Tokenizer::dump(std::ostream &out) const
out << " variable=\"" << tok->variable() << '\"';
if (tok->function())
out << " function=\"" << tok->function() << '\"';
if (!tok->values.empty())
out << " values=\"" << &tok->values << '\"';
if (!tok->values().empty())
out << " values=\"" << &tok->values() << '\"';
if (tok->type())
out << " type-scope=\"" << tok->type()->classScope << '\"';
if (tok->astParent())

View File

@ -235,55 +235,6 @@ static bool bailoutSelfAssignment(const Token * const tok)
return false;
}
/** Add token value. Return true if value is added. */
static bool addValue(Token *tok, const ValueFlow::Value &value)
{
if (value.isKnown()) {
// Clear all other values since value is known
tok->values.clear();
}
// Don't handle more than 10 values for performance reasons
// TODO: add setting?
if (tok->values.size() >= 10U)
return false;
// if value already exists, don't add it again
std::list<ValueFlow::Value>::iterator it;
for (it = tok->values.begin(); it != tok->values.end(); ++it) {
// different intvalue => continue
if (it->intvalue != value.intvalue)
continue;
// different types => continue
if (it->valueType != value.valueType)
continue;
if (value.isTokValue() && (it->tokvalue != value.tokvalue) && (it->tokvalue->str() != value.tokvalue->str()))
continue;
// same value, but old value is inconclusive so replace it
if (it->inconclusive && !value.inconclusive) {
*it = value;
if (it->varId == 0)
it->varId = tok->varId();
break;
}
// Same value already exists, don't add new value
return false;
}
// Add value
if (it == tok->values.end()) {
ValueFlow::Value v(value);
if (v.varId == 0)
v.varId = tok->varId();
tok->values.push_back(v);
}
return true;
}
static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign sign, unsigned int bit)
{
if (value.isFloatValue()) {
@ -302,7 +253,7 @@ static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign
/** set ValueFlow value and perform calculations if possible */
static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Settings *settings)
{
if (!addValue(tok,value))
if (!tok->addValue(value))
return;
Token *parent = const_cast<Token*>(tok->astParent());
@ -334,8 +285,8 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2() && parent->astOperand1()) {
// is condition always true/false?
if (parent->astOperand1()->values.size() == 1U && parent->astOperand1()->values.front().isKnown()) {
const ValueFlow::Value &condvalue = parent->astOperand1()->values.front();
if (parent->astOperand1()->values().size() == 1U && parent->astOperand1()->values().front().isKnown()) {
const ValueFlow::Value &condvalue = parent->astOperand1()->values().front();
const bool cond(condvalue.isTokValue() || (condvalue.isIntValue() && condvalue.intvalue != 0));
if (cond && !tok->astOperand1()) { // true condition, no second operator
setTokenValue(parent, condvalue, settings);
@ -343,7 +294,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
if (!op) // #7769 segmentation fault at setTokenValue()
return;
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())
setTokenValue(parent, value, settings);
}
@ -382,10 +333,10 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
else if ((parent->isArithmeticalOp() || parent->isComparisonOp() || (parent->tokType() == Token::eBitOp) || (parent->tokType() == Token::eLogicalOp)) &&
parent->astOperand1() &&
parent->astOperand2()) {
const bool known = ((parent->astOperand1()->values.size() == 1U &&
parent->astOperand1()->values.front().isKnown()) ||
(parent->astOperand2()->values.size() == 1U &&
parent->astOperand2()->values.front().isKnown()));
const bool known = ((parent->astOperand1()->values().size() == 1U &&
parent->astOperand1()->values().front().isKnown()) ||
(parent->astOperand2()->values().size() == 1U &&
parent->astOperand2()->values().front().isKnown()));
// known result when a operand is 0.
if (Token::Match(parent, "[&*]") && value.isKnown() && value.isIntValue() && value.intvalue==0) {
@ -393,13 +344,12 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
return;
}
std::list<ValueFlow::Value>::const_iterator value1, value2;
for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) {
for (std::list<ValueFlow::Value>::const_iterator value1 = parent->astOperand1()->values().begin(); value1 != parent->astOperand1()->values().end(); ++value1) {
if (!value1->isIntValue() && !value1->isFloatValue() && !value1->isTokValue())
continue;
if (value1->isTokValue() && (!parent->isComparisonOp() || value1->tokvalue->tokType() != Token::eString))
continue;
for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) {
for (std::list<ValueFlow::Value>::const_iterator value2 = parent->astOperand2()->values().begin(); value2 != parent->astOperand2()->values().end(); ++value2) {
if (!value2->isIntValue() && !value2->isFloatValue() && !value2->isTokValue())
continue;
if (value2->isTokValue() && (!parent->isComparisonOp() || value2->tokvalue->tokType() != Token::eString || value1->isTokValue()))
@ -558,7 +508,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
// !
else if (parent->str() == "!") {
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->isIntValue())
continue;
ValueFlow::Value v(*it);
@ -570,7 +520,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
// ~
else if (parent->str() == "~") {
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->isIntValue())
continue;
ValueFlow::Value v(*it);
@ -594,7 +544,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
// unary minus
else if (parent->str() == "-" && !parent->astOperand2()) {
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->isIntValue() && !it->isFloatValue())
continue;
ValueFlow::Value v(*it);
@ -608,11 +558,10 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
// Array element
else if (parent->str() == "[" && parent->astOperand1() && parent->astOperand2()) {
std::list<ValueFlow::Value>::const_iterator value1, value2;
for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) {
for (std::list<ValueFlow::Value>::const_iterator value1 = parent->astOperand1()->values().begin(); value1 != parent->astOperand1()->values().end(); ++value1) {
if (!value1->isTokValue())
continue;
for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) {
for (std::list<ValueFlow::Value>::const_iterator value2 = parent->astOperand2()->values().begin(); value2 != parent->astOperand2()->values().end(); ++value2) {
if (!value2->isIntValue())
continue;
if (value1->varId == 0U || value2->varId == 0U ||
@ -890,7 +839,7 @@ static void valueFlowBitAnd(TokenList *tokenlist)
if (tok->str() != "&")
continue;
if (tok->values.size() == 1U && tok->values.front().isKnown())
if (tok->values().size() == 1U && tok->values().front().isKnown())
continue;
if (!tok->astOperand1() || !tok->astOperand2())
@ -1104,10 +1053,10 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symbo
if (tok->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
if (tok->astOperand1()->isName() && tok->astOperand2()->hasKnownIntValue()) {
vartok = tok->astOperand1();
num = tok->astOperand2()->values.front().intvalue;
num = tok->astOperand2()->values().front().intvalue;
} else if (tok->astOperand1()->hasKnownIntValue() && tok->astOperand2()->isName()) {
vartok = tok->astOperand2();
num = tok->astOperand1()->values.front().intvalue;
num = tok->astOperand1()->values().front().intvalue;
} else {
continue;
}
@ -1230,7 +1179,7 @@ static void valueFlowAST(Token *tok, unsigned int varid, const ValueFlow::Value
return;
} else if (tok->str() == "||" && tok->astOperand1()) {
bool nonzero = false;
for (std::list<ValueFlow::Value>::const_iterator it = tok->astOperand1()->values.begin(); it != tok->astOperand1()->values.end(); ++it) {
for (std::list<ValueFlow::Value>::const_iterator it = tok->astOperand1()->values().begin(); it != tok->astOperand1()->values().end(); ++it) {
nonzero |= (it->intvalue != 0);
}
if (!nonzero)
@ -1391,7 +1340,7 @@ static bool valueFlowForward(Token * const startToken,
}
const Token * const condTok = tok2->next()->astOperand2();
const bool condAlwaysTrue = (condTok && condTok->values.size() == 1U && condTok->values.front().isKnown() && condTok->values.front().intvalue != 0);
const bool condAlwaysTrue = (condTok && condTok->values().size() == 1U && condTok->values().front().isKnown() && condTok->values().front().intvalue != 0);
// Should scope be skipped because variable value is checked?
std::list<ValueFlow::Value> truevalues;
@ -1627,7 +1576,7 @@ static bool valueFlowForward(Token * const startToken,
continue;
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();
std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it)
@ -1975,10 +1924,10 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
const Token * const endOfVarScope = var->typeStartToken()->scope()->classEnd;
// Rhs values..
if (!tok->astOperand2() || tok->astOperand2()->values.empty())
if (!tok->astOperand2() || tok->astOperand2()->values().empty())
continue;
std::list<ValueFlow::Value> values = tok->astOperand2()->values;
std::list<ValueFlow::Value> values = tok->astOperand2()->values();
const bool constValue = tok->astOperand2()->isNumber();
if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) {
@ -2052,7 +2001,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
if (!var || !(var->isLocal() || var->isGlobal() || var->isArgument()))
continue;
std::list<ValueFlow::Value> values;
values.push_back(ValueFlow::Value(tok, numtok ? numtok->values.front().intvalue : 0LL));
values.push_back(ValueFlow::Value(tok, numtok ? numtok->values().front().intvalue : 0LL));
if (Token::Match(tok->astParent(), "%oror%|&&")) {
Token *parent = const_cast<Token*>(tok->astParent());
@ -2186,7 +2135,7 @@ static void execute(const Token *expr,
*error = true;
else if (expr->hasKnownIntValue()) {
*result = expr->values.front().intvalue;
*result = expr->values().front().intvalue;
}
else if (expr->isNumber()) {
@ -2315,11 +2264,11 @@ static void execute(const Token *expr,
else if (expr->str() == "[" && expr->astOperand1() && expr->astOperand2()) {
const Token *tokvalue;
if (!programMemory->getTokValue(expr->astOperand1()->varId(), &tokvalue)) {
if (expr->astOperand1()->values.size() != 1U || !expr->astOperand1()->values.front().isTokValue()) {
if (expr->astOperand1()->values().size() != 1U || !expr->astOperand1()->values().front().isTokValue()) {
*error = true;
return;
}
tokvalue = expr->astOperand1()->values.front().tokvalue;
tokvalue = expr->astOperand1()->values().front().tokvalue;
}
if (!tokvalue || !tokvalue->isLiteral()) {
*error = true;
@ -2688,7 +2637,7 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
return;
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;
if (value.isTokValue() && value.tokvalue->tokType() == Token::eString) {
ValueFlow::Value retval(value); // copy all "inconclusive", "condition", etc attributes
@ -2715,14 +2664,14 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
valueFlowNumber(&tokenList);
for (Token *tok2 = tokenList.front(); tok2; tok2 = tok2->next()) {
if (tok2->str() == "arg1" && arg1) {
setTokenValues(tok2, arg1->values, settings);
setTokenValues(tok2, arg1->values(), settings);
}
}
// Find result..
for (const Token *tok2 = tokenList.front(); tok2; tok2 = tok2->next()) {
if (!tok2->astParent() && !tok2->values.empty()) {
setTokenValues(tok, tok2->values, settings);
if (!tok2->astParent() && !tok2->values().empty()) {
setTokenValues(tok, tok2->values(), settings);
return;
}
}
@ -2758,8 +2707,8 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
std::list<ValueFlow::Value> argvalues;
// passing value(s) to function
if (!argtok->values.empty() && Token::Match(argtok, "%name%|%num%|%str% [,)]"))
argvalues = argtok->values;
if (!argtok->values().empty() && Token::Match(argtok, "%name%|%num%|%str% [,)]"))
argvalues = argtok->values();
else {
// bool operator => values 1/0 are passed to function..
const Token *op = argtok;
@ -2769,8 +2718,8 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
argvalues.clear();
argvalues.push_back(ValueFlow::Value(0));
argvalues.push_back(ValueFlow::Value(1));
} else if (Token::Match(op, "%cop%") && !op->values.empty()) {
argvalues = op->values;
} else if (Token::Match(op, "%cop%") && !op->values().empty()) {
argvalues = op->values();
} else {
// possible values are unknown..
continue;
@ -2801,7 +2750,7 @@ static void valueFlowFunctionDefaultParameter(TokenList *tokenlist, SymbolDataba
for (std::size_t arg = function->minArgCount(); arg < function->argCount(); arg++) {
const Variable* var = function->getArgumentVar(arg);
if (var && var->hasDefault() && Token::Match(var->nameToken(), "%var% = %num%|%str% [,)]")) {
const std::list<ValueFlow::Value> &values = var->nameToken()->tokAt(2)->values;
const std::list<ValueFlow::Value> &values = var->nameToken()->tokAt(2)->values();
std::list<ValueFlow::Value> argvalues;
for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
ValueFlow::Value v(*it);
@ -2836,10 +2785,10 @@ static void valueFlowFunctionReturn(TokenList *tokenlist, ErrorLogger *errorLogg
partok = partok->astOperand1();
if (!isKnown(partok))
continue;
parvalues.push_back(partok->values.front().intvalue);
parvalues.push_back(partok->values().front().intvalue);
partok = partok->astParent();
while (partok && partok->str() == ",") {
parvalues.push_back(partok->astOperand2()->values.front().intvalue);
parvalues.push_back(partok->astOperand2()->values().front().intvalue);
partok = partok->astParent();
}
if (partok != tok)
@ -2889,19 +2838,19 @@ static void valueFlowFunctionReturn(TokenList *tokenlist, ErrorLogger *errorLogg
const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(const Token *expr, const Settings *settings)
{
if (expr && expr->values.empty()) {
if (expr && expr->values().empty()) {
valueFlowConstantFoldAST(expr->astOperand1(), settings);
valueFlowConstantFoldAST(expr->astOperand2(), settings);
valueFlowSetConstantValue(expr, settings, true /* TODO: this is a guess */);
}
return expr && expr->values.size() == 1U && expr->values.front().isKnown() ? &expr->values.front() : nullptr;
return expr && expr->values().size() == 1U && expr->values().front().isKnown() ? &expr->values().front() : nullptr;
}
void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
{
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
tok->values.clear();
tok->clearValueFlow();
valueFlowNumber(tokenlist);
valueFlowString(tokenlist);

View File

@ -95,7 +95,7 @@ private:
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
if (tok->str() == "x" && tok->linenr() == linenr) {
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->isIntValue() && it->intvalue == value)
return true;
}
@ -115,7 +115,7 @@ private:
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
if (tok->str() == "x" && tok->linenr() == linenr) {
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->isTokValue() && Token::simpleMatch(it->tokvalue, value))
return true;
}
@ -134,7 +134,7 @@ private:
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
if (tok->str() == "x" && tok->linenr() == linenr) {
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->isMovedValue() && it->moveKind == moveKind)
return true;
}
@ -153,7 +153,7 @@ private:
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
if (tok->str() == "x" && tok->linenr() == linenr) {
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->isIntValue() && it->intvalue == value && it->condition)
return true;
}
@ -181,7 +181,7 @@ private:
errout.str("");
tokenizer.tokenize(istr, "test.cpp");
const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr);
return tok ? tok->values : std::list<ValueFlow::Value>();
return tok ? tok->values() : std::list<ValueFlow::Value>();
}
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {