From 3c8f5b85ae199edef483bea71c54194a928d02bf Mon Sep 17 00:00:00 2001 From: PKEuS Date: Mon, 27 Mar 2017 18:48:34 +0200 Subject: [PATCH] Refactorization: Allocate Token::_values (ValueFlow information) dynamically, reducing size of each token by around 10% --- lib/astutils.cpp | 2 +- lib/checkautovariables.cpp | 2 +- lib/checkbufferoverrun.cpp | 2 +- lib/checkcondition.cpp | 6 +- lib/checkio.cpp | 4 +- lib/checkleakautovar.cpp | 2 +- lib/checkmemoryleak.cpp | 12 ++-- lib/checkother.cpp | 2 +- lib/checktype.cpp | 2 +- lib/checkuninitvar.cpp | 4 +- lib/checkunusedvar.cpp | 2 +- lib/symboldatabase.cpp | 8 +-- lib/token.cpp | 109 +++++++++++++++++++++++++----- lib/token.h | 36 +++++++--- lib/tokenize.cpp | 6 +- lib/valueflow.cpp | 133 ++++++++++++------------------------- test/testvalueflow.cpp | 10 +-- 17 files changed, 190 insertions(+), 152 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index ca5de9d55..a5f31d4d9 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -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; } diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 92fbec870..d2c5c6d97 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -119,7 +119,7 @@ bool CheckAutoVariables::isAutoVarArray(const Token *tok) // ValueFlow if (var->isPointer() && !var->isArgument()) { - for (std::list::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) { + for (std::list::const_iterator it = tok->values().begin(); it != tok->values().end(); ++it) { const ValueFlow::Value &val = *it; if (val.isTokValue() && isAutoVarArray(val.tokvalue)) return true; diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index be3b00264..e2ea978ae 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1132,7 +1132,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() if (!value) continue; - for (std::list::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) { + for (std::list::const_iterator it = tok->values().begin(); it != tok->values().end(); ++it) { if (!it->isTokValue() || !it->tokvalue) continue; const Variable *var = it->tokvalue->variable(); diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 539a9fa0f..a9edd50c7 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -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); } } } diff --git a/lib/checkio.cpp b/lib/checkio.cpp index fce1566d7..cf0fdff5c 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -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; diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 54236179f..a9e359c12 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -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)) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 035c0f81a..891654c30 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -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) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index c7a9fe264..0b4d246fc 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -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? diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 0cc9903e0..ac939ea86 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -337,7 +337,7 @@ void CheckType::checkFloatToIntegerOverflow() continue; const Token *op1 = tok->astOperand1(); - for (std::list::const_iterator it = op1->values.begin(); it != op1->values.end(); ++it) { + for (std::list::const_iterator it = op1->values().begin(); it != op1->values().end(); ++it) { if (it->valueType != ValueFlow::Value::FLOAT) continue; if (it->inconclusive && !_settings->inconclusive) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index ca0e07a66..64ce31460 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -219,8 +219,8 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::mapisComparisonOp()) { - 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; diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 8528a24d7..5ea79dec5 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -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); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 652c062e7..39ecdc360 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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; } } diff --git a/lib/token.cpp b/lib/token.cpp index b816b0d68..af18a5509 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -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 << "\">" << std::endl; + out << " _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::const_iterator it=tok->values.begin(); it!=tok->values.end(); ++it) { + for (std::list::const_iterator it=tok->_values->begin(); it!=tok->_values->end(); ++it) { if (xml) { out << " 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 << " " << 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::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::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::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::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::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::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(1, v); + } + + return true; +} + void Token::assignProgressValues(Token *tok) { unsigned int total_count = 0; diff --git a/lib/token.h b/lib/token.h index a00940c77..eb79f9113 100644 --- a/lib/token.h +++ b/lib/token.h @@ -736,6 +736,11 @@ public: return _originalName ? *_originalName : emptyString; } + const std::list& values() const { + static const std::list emptyList; + return _values ? *_values : emptyList; + } + /** * Sets the original name. */ @@ -747,16 +752,14 @@ public: *_originalName = name; } - /** Values of token */ - std::list 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::const_iterator it; - for (it = values.begin(); it != values.end(); ++it) { + if (!_values) + return nullptr; + for (std::list::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::const_iterator it; - for (it = values.begin(); it != values.end(); ++it) { + for (std::list::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::const_iterator it; - for (it = values.begin(); it != values.end(); ++it) { + if (!_values) + return nullptr; + for (std::list::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* _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) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 62bd6781c..71cc788c6 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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()) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 70f2546ca..6a6698dab 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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::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(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 &values = op->values; + const std::list &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::const_iterator value1, value2; - for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) { + for (std::list::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::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::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::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::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::const_iterator value1, value2; - for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) { + for (std::list::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::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::const_iterator it = tok->astOperand1()->values.begin(); it != tok->astOperand1()->values.end(); ++it) { + for (std::list::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 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::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 values = tok->astOperand2()->values; + std::list 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 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(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::const_iterator it = arg1->values.begin(); it != arg1->values.end(); ++it) { + for (std::list::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 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 &values = var->nameToken()->tokAt(2)->values; + const std::list &values = var->nameToken()->tokAt(2)->values(); std::list argvalues; for (std::list::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); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 6312f490e..4388e7c40 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -95,7 +95,7 @@ private: for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { if (tok->str() == "x" && tok->linenr() == linenr) { std::list::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::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::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::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(); + return tok ? tok->values() : std::list(); } ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {