Refactorization: Allocate Token::_values (ValueFlow information) dynamically, reducing size of each token by around 10%
This commit is contained in:
parent
2938278f00
commit
3c8f5b85ae
|
@ -87,7 +87,7 @@ static bool match(const Token *tok, const std::string &rhs)
|
||||||
{
|
{
|
||||||
if (tok->str() == rhs)
|
if (tok->str() == rhs)
|
||||||
return true;
|
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 true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ bool CheckAutoVariables::isAutoVarArray(const Token *tok)
|
||||||
|
|
||||||
// ValueFlow
|
// ValueFlow
|
||||||
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.isTokValue() && isAutoVarArray(val.tokvalue))
|
if (val.isTokValue() && isAutoVarArray(val.tokvalue))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1132,7 +1132,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
|
||||||
if (!value)
|
if (!value)
|
||||||
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->isTokValue() || !it->tokvalue)
|
if (!it->isTokValue() || !it->tokvalue)
|
||||||
continue;
|
continue;
|
||||||
const Variable *var = it->tokvalue->variable();
|
const Variable *var = it->tokvalue->variable();
|
||||||
|
|
|
@ -261,8 +261,8 @@ void CheckCondition::checkBadBitmaskCheck()
|
||||||
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while")) ||
|
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while")) ||
|
||||||
(parent->str() == "return" && parent->astOperand1() == tok && inBooleanFunction(tok));
|
(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()) ||
|
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());
|
(tok->astOperand2()->values().size() == 1 && tok->astOperand2()->values().front().intvalue != 0 && tok->astOperand2()->values().front().isKnown());
|
||||||
|
|
||||||
if (isBoolean && isTrue)
|
if (isBoolean && isTrue)
|
||||||
badBitmaskCheckError(tok);
|
badBitmaskCheckError(tok);
|
||||||
|
@ -1049,7 +1049,7 @@ void CheckCondition::alwaysTrueFalse()
|
||||||
if (isExpandedMacro)
|
if (isExpandedMacro)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
alwaysTrueFalseError(tok, tok->values.front().intvalue != 0);
|
alwaysTrueFalseError(tok, tok->values().front().intvalue != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -474,8 +474,8 @@ 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.empty() && argTok->values.front().isTokValue() && 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;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -547,7 +547,7 @@ void CheckLeakAutoVar::functionCall(const Token *tok, VarInfo *varInfo, const Va
|
||||||
if (arg->str() == "&")
|
if (arg->str() == "&")
|
||||||
arg = arg->next();
|
arg = arg->next();
|
||||||
|
|
||||||
bool isnull = arg->hasKnownIntValue() && arg->values.front().intvalue == 0;
|
bool isnull = arg->hasKnownIntValue() && arg->values().front().intvalue == 0;
|
||||||
|
|
||||||
// Is variable allocated?
|
// Is variable allocated?
|
||||||
if (!isnull && (!af || af->arg == argNr))
|
if (!isnull && (!af || af->arg == argNr))
|
||||||
|
|
|
@ -481,18 +481,18 @@ static bool alwaysTrue(const Token *tok)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return false;
|
return false;
|
||||||
if (tok->values.size() == 1U &&
|
if (tok->values().size() == 1U &&
|
||||||
tok->values.front().intvalue != 0 &&
|
tok->values().front().intvalue != 0 &&
|
||||||
tok->values.front().isKnown())
|
tok->values().front().isKnown())
|
||||||
return true;
|
return true;
|
||||||
if (tok->str() == "||")
|
if (tok->str() == "||")
|
||||||
return alwaysTrue(tok->astOperand1()) || alwaysTrue(tok->astOperand2());
|
return alwaysTrue(tok->astOperand1()) || alwaysTrue(tok->astOperand2());
|
||||||
if (tok->str() == "true")
|
if (tok->str() == "true")
|
||||||
return true;
|
return true;
|
||||||
return (tok->isComparisonOp() &&
|
return (tok->isComparisonOp() &&
|
||||||
tok->values.size() == 1U &&
|
tok->values().size() == 1U &&
|
||||||
tok->values.front().isKnown() &&
|
tok->values().front().isKnown() &&
|
||||||
tok->values.front().intvalue != 0);
|
tok->values().front().intvalue != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, const Settings *settings, bool cpp)
|
bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, const Settings *settings, bool cpp)
|
||||||
|
|
|
@ -284,7 +284,7 @@ void CheckOther::warningOldStylePointerCast()
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
const Token *p = tok->tokAt(4);
|
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;
|
continue;
|
||||||
|
|
||||||
// Is "type" a class?
|
// Is "type" a class?
|
||||||
|
|
|
@ -337,7 +337,7 @@ void CheckType::checkFloatToIntegerOverflow()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token *op1 = tok->astOperand1();
|
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)
|
if (it->valueType != ValueFlow::Value::FLOAT)
|
||||||
continue;
|
continue;
|
||||||
if (it->inconclusive && !_settings->inconclusive)
|
if (it->inconclusive && !_settings->inconclusive)
|
||||||
|
|
|
@ -219,8 +219,8 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::map<unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (tok->isComparisonOp()) {
|
else if (tok->isComparisonOp()) {
|
||||||
if (tok->values.size() == 1U && tok->values.front().isKnown()) {
|
if (tok->values().size() == 1U && tok->values().front().isKnown()) {
|
||||||
if (tok->values.front().intvalue)
|
if (tok->values().front().intvalue)
|
||||||
*alwaysTrue = true;
|
*alwaysTrue = true;
|
||||||
else
|
else
|
||||||
*alwaysFalse = true;
|
*alwaysFalse = true;
|
||||||
|
|
|
@ -1016,7 +1016,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
Token::Match(tok, "%name% ;") &&
|
Token::Match(tok, "%name% ;") &&
|
||||||
tok->varId() == 0 &&
|
tok->varId() == 0 &&
|
||||||
tok->hasKnownIntValue() &&
|
tok->hasKnownIntValue() &&
|
||||||
tok->values.front().intvalue == 0) {
|
tok->values().front().intvalue == 0) {
|
||||||
variables.use(varid1, tok);
|
variables.use(varid1, tok);
|
||||||
} else {
|
} else {
|
||||||
variables.write(varid1, tok);
|
variables.write(varid1, tok);
|
||||||
|
|
|
@ -1321,8 +1321,8 @@ void SymbolDatabase::createSymbolDatabaseEnums()
|
||||||
ValueFlow::valueFlowConstantFoldAST(rhs, _settings);
|
ValueFlow::valueFlowConstantFoldAST(rhs, _settings);
|
||||||
|
|
||||||
// get constant folded value:
|
// get constant folded value:
|
||||||
if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) {
|
if (rhs && rhs->values().size() == 1U && rhs->values().front().isKnown()) {
|
||||||
enumerator.value = rhs->values.front().intvalue;
|
enumerator.value = rhs->values().front().intvalue;
|
||||||
enumerator.value_known = true;
|
enumerator.value_known = true;
|
||||||
value = enumerator.value + 1;
|
value = enumerator.value + 1;
|
||||||
}
|
}
|
||||||
|
@ -1425,8 +1425,8 @@ void SymbolDatabase::createSymbolDatabaseUnknownArrayDimensions()
|
||||||
ValueFlow::valueFlowConstantFoldAST(rhs, _settings);
|
ValueFlow::valueFlowConstantFoldAST(rhs, _settings);
|
||||||
|
|
||||||
// get constant folded value:
|
// get constant folded value:
|
||||||
if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) {
|
if (rhs && rhs->values().size() == 1U && rhs->values().front().isKnown()) {
|
||||||
dimension.num = rhs->values.front().intvalue;
|
dimension.num = rhs->values().front().intvalue;
|
||||||
dimension.known = true;
|
dimension.known = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
109
lib/token.cpp
109
lib/token.cpp
|
@ -50,7 +50,8 @@ Token::Token(Token **t) :
|
||||||
_astOperand2(nullptr),
|
_astOperand2(nullptr),
|
||||||
_astParent(nullptr),
|
_astParent(nullptr),
|
||||||
_originalName(nullptr),
|
_originalName(nullptr),
|
||||||
valuetype(nullptr)
|
valuetype(nullptr),
|
||||||
|
_values(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ Token::~Token()
|
||||||
{
|
{
|
||||||
delete _originalName;
|
delete _originalName;
|
||||||
delete valuetype;
|
delete valuetype;
|
||||||
|
delete _values;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Token::update_property_info()
|
void Token::update_property_info()
|
||||||
|
@ -213,7 +215,7 @@ void Token::swapWithNext()
|
||||||
std::swap(_scope, _next->_scope);
|
std::swap(_scope, _next->_scope);
|
||||||
std::swap(_function, _next->_function);
|
std::swap(_function, _next->_function);
|
||||||
std::swap(_originalName, _next->_originalName);
|
std::swap(_originalName, _next->_originalName);
|
||||||
std::swap(values, _next->values);
|
std::swap(_values, _next->_values);
|
||||||
std::swap(valuetype, _next->valuetype);
|
std::swap(valuetype, _next->valuetype);
|
||||||
std::swap(_progressValue, _next->_progressValue);
|
std::swap(_progressValue, _next->_progressValue);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +238,11 @@ void Token::deleteThis()
|
||||||
_originalName = _next->_originalName;
|
_originalName = _next->_originalName;
|
||||||
_next->_originalName = nullptr;
|
_next->_originalName = nullptr;
|
||||||
}
|
}
|
||||||
values = _next->values;
|
if (_next->_values) {
|
||||||
|
delete _values;
|
||||||
|
_values = _next->_values;
|
||||||
|
_next->_values = nullptr;
|
||||||
|
}
|
||||||
if (_next->valuetype) {
|
if (_next->valuetype) {
|
||||||
delete valuetype;
|
delete valuetype;
|
||||||
valuetype = _next->valuetype;
|
valuetype = _next->valuetype;
|
||||||
|
@ -261,7 +267,11 @@ void Token::deleteThis()
|
||||||
_originalName = _previous->_originalName;
|
_originalName = _previous->_originalName;
|
||||||
_previous->_originalName = nullptr;
|
_previous->_originalName = nullptr;
|
||||||
}
|
}
|
||||||
values = _previous->values;
|
if (_previous->_values) {
|
||||||
|
delete _values;
|
||||||
|
_values = _previous->_values;
|
||||||
|
_previous->_values = nullptr;
|
||||||
|
}
|
||||||
if (_previous->valuetype) {
|
if (_previous->valuetype) {
|
||||||
delete valuetype;
|
delete valuetype;
|
||||||
valuetype = _previous->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() << '\"';
|
out << " variable=\"" << tok->variable() << '\"';
|
||||||
if (tok->function())
|
if (tok->function())
|
||||||
out << " function=\"" << tok->function() << '\"';
|
out << " function=\"" << tok->function() << '\"';
|
||||||
if (!tok->values.empty())
|
if (!tok->values().empty())
|
||||||
out << " values=\"" << &tok->values << '\"';
|
out << " values=\"" << &tok->values() << '\"';
|
||||||
|
|
||||||
if (!tok->astOperand1() && !tok->astOperand2()) {
|
if (!tok->astOperand1() && !tok->astOperand2()) {
|
||||||
out << "/>" << std::endl;
|
out << "/>" << std::endl;
|
||||||
|
@ -1318,19 +1328,19 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
|
||||||
else
|
else
|
||||||
out << "\n\n##Value flow" << std::endl;
|
out << "\n\n##Value flow" << std::endl;
|
||||||
for (const Token *tok = this; tok; tok = tok->next()) {
|
for (const Token *tok = this; tok; tok = tok->next()) {
|
||||||
if (tok->values.empty())
|
if (!tok->_values)
|
||||||
continue;
|
continue;
|
||||||
if (xml)
|
if (xml)
|
||||||
out << " <values id=\"" << &tok->values << "\">" << std::endl;
|
out << " <values id=\"" << tok->_values << "\">" << std::endl;
|
||||||
else if (line != tok->linenr())
|
else if (line != tok->linenr())
|
||||||
out << "Line " << tok->linenr() << std::endl;
|
out << "Line " << tok->linenr() << std::endl;
|
||||||
line = tok->linenr();
|
line = tok->linenr();
|
||||||
if (!xml) {
|
if (!xml) {
|
||||||
out << " " << tok->str() << (tok->values.front().isKnown() ? " always " : " possible ");
|
out << " " << tok->str() << (tok->_values->front().isKnown() ? " always " : " possible ");
|
||||||
if (tok->values.size() > 1U)
|
if (tok->_values->size() > 1U)
|
||||||
out << '{';
|
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) {
|
if (xml) {
|
||||||
out << " <value ";
|
out << " <value ";
|
||||||
switch (it->valueType) {
|
switch (it->valueType) {
|
||||||
|
@ -1357,7 +1367,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
if (it != tok->values.begin())
|
if (it != tok->_values->begin())
|
||||||
out << ",";
|
out << ",";
|
||||||
switch (it->valueType) {
|
switch (it->valueType) {
|
||||||
case ValueFlow::Value::INT:
|
case ValueFlow::Value::INT:
|
||||||
|
@ -1377,7 +1387,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
|
||||||
}
|
}
|
||||||
if (xml)
|
if (xml)
|
||||||
out << " </values>" << std::endl;
|
out << " </values>" << std::endl;
|
||||||
else if (tok->values.size() > 1U)
|
else if (tok->_values->size() > 1U)
|
||||||
out << '}' << std::endl;
|
out << '}' << std::endl;
|
||||||
else
|
else
|
||||||
out << std::endl;
|
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
|
const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Settings *settings) const
|
||||||
{
|
{
|
||||||
|
if (!_values)
|
||||||
|
return nullptr;
|
||||||
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->isIntValue() && it->intvalue <= val) {
|
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);
|
||||||
|
@ -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
|
const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Settings *settings) const
|
||||||
{
|
{
|
||||||
|
if (!_values)
|
||||||
|
return nullptr;
|
||||||
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->isIntValue() && it->intvalue >= val) {
|
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);
|
||||||
|
@ -1430,10 +1444,12 @@ const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Sett
|
||||||
|
|
||||||
const Token *Token::getValueTokenMinStrSize() const
|
const Token *Token::getValueTokenMinStrSize() const
|
||||||
{
|
{
|
||||||
|
if (!_values)
|
||||||
|
return nullptr;
|
||||||
const Token *ret = nullptr;
|
const Token *ret = nullptr;
|
||||||
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->isTokValue() && 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) {
|
||||||
|
@ -1447,10 +1463,12 @@ const Token *Token::getValueTokenMinStrSize() const
|
||||||
|
|
||||||
const Token *Token::getValueTokenMaxStrLength() const
|
const Token *Token::getValueTokenMaxStrLength() const
|
||||||
{
|
{
|
||||||
|
if (!_values)
|
||||||
|
return nullptr;
|
||||||
const Token *ret = nullptr;
|
const Token *ret = nullptr;
|
||||||
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->isTokValue() && 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) {
|
||||||
|
@ -1474,7 +1492,7 @@ const Token *Token::getValueTokenDeadPointer() const
|
||||||
const Scope * const functionscope = getfunctionscope(this->scope());
|
const Scope * const functionscope = getfunctionscope(this->scope());
|
||||||
|
|
||||||
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->isTokValue() || (it->tokvalue && it->tokvalue->str() != "&"))
|
if (!it->isTokValue() || (it->tokvalue && it->tokvalue->str() != "&"))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1502,6 +1520,61 @@ const Token *Token::getValueTokenDeadPointer() const
|
||||||
return nullptr;
|
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)
|
void Token::assignProgressValues(Token *tok)
|
||||||
{
|
{
|
||||||
unsigned int total_count = 0;
|
unsigned int total_count = 0;
|
||||||
|
|
36
lib/token.h
36
lib/token.h
|
@ -736,6 +736,11 @@ public:
|
||||||
return _originalName ? *_originalName : emptyString;
|
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.
|
* Sets the original name.
|
||||||
*/
|
*/
|
||||||
|
@ -747,16 +752,14 @@ public:
|
||||||
*_originalName = name;
|
*_originalName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Values of token */
|
|
||||||
std::list<ValueFlow::Value> values;
|
|
||||||
|
|
||||||
bool hasKnownIntValue() const {
|
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 {
|
const ValueFlow::Value * getValue(const MathLib::bigint val) const {
|
||||||
std::list<ValueFlow::Value>::const_iterator it;
|
if (!_values)
|
||||||
for (it = values.begin(); it != values.end(); ++it) {
|
return nullptr;
|
||||||
|
for (std::list<ValueFlow::Value>::const_iterator it = _values->begin(); it != _values->end(); ++it) {
|
||||||
if (it->isIntValue() && it->intvalue == val)
|
if (it->isIntValue() && it->intvalue == val)
|
||||||
return &(*it);
|
return &(*it);
|
||||||
}
|
}
|
||||||
|
@ -764,9 +767,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const ValueFlow::Value * getMaxValue(bool condition) const {
|
const ValueFlow::Value * getMaxValue(bool condition) const {
|
||||||
|
if (!_values)
|
||||||
|
return nullptr;
|
||||||
const ValueFlow::Value *ret = nullptr;
|
const ValueFlow::Value *ret = nullptr;
|
||||||
std::list<ValueFlow::Value>::const_iterator it;
|
for (std::list<ValueFlow::Value>::const_iterator it = _values->begin(); it != _values->end(); ++it) {
|
||||||
for (it = values.begin(); it != values.end(); ++it) {
|
|
||||||
if (!it->isIntValue())
|
if (!it->isIntValue())
|
||||||
continue;
|
continue;
|
||||||
if ((!ret || it->intvalue > ret->intvalue) &&
|
if ((!ret || it->intvalue > ret->intvalue) &&
|
||||||
|
@ -777,8 +781,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const ValueFlow::Value * getMovedValue() const {
|
const ValueFlow::Value * getMovedValue() const {
|
||||||
std::list<ValueFlow::Value>::const_iterator it;
|
if (!_values)
|
||||||
for (it = values.begin(); it != values.end(); ++it) {
|
return nullptr;
|
||||||
|
for (std::list<ValueFlow::Value>::const_iterator it = _values->begin(); it != _values->end(); ++it) {
|
||||||
if (it->isMovedValue() && it->moveKind != ValueFlow::Value::NonMovedVariable)
|
if (it->isMovedValue() && it->moveKind != ValueFlow::Value::NonMovedVariable)
|
||||||
return &(*it);
|
return &(*it);
|
||||||
}
|
}
|
||||||
|
@ -793,6 +798,9 @@ public:
|
||||||
|
|
||||||
const Token *getValueTokenDeadPointer() const;
|
const Token *getValueTokenDeadPointer() const;
|
||||||
|
|
||||||
|
/** Add token value. Return true if value is added. */
|
||||||
|
bool addValue(const ValueFlow::Value &value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void next(Token *nextToken) {
|
void next(Token *nextToken) {
|
||||||
|
@ -903,6 +911,9 @@ private:
|
||||||
// ValueType
|
// ValueType
|
||||||
ValueType *valuetype;
|
ValueType *valuetype;
|
||||||
|
|
||||||
|
// ValueFlow
|
||||||
|
std::list<ValueFlow::Value>* _values;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void astOperand1(Token *tok);
|
void astOperand1(Token *tok);
|
||||||
void astOperand2(Token *tok);
|
void astOperand2(Token *tok);
|
||||||
|
@ -936,6 +947,11 @@ public:
|
||||||
_astOperand1 = _astOperand2 = _astParent = nullptr;
|
_astOperand1 = _astOperand2 = _astParent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearValueFlow() {
|
||||||
|
delete _values;
|
||||||
|
_values = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::string astString(const char *sep = "") const {
|
std::string astString(const char *sep = "") const {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
if (_astOperand1)
|
if (_astOperand1)
|
||||||
|
|
|
@ -3666,7 +3666,7 @@ bool Tokenizer::simplifyTokenList2()
|
||||||
// Clear AST,ValueFlow. These will be created again at the end of this function.
|
// Clear AST,ValueFlow. These will be created again at the end of this function.
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
tok->clearAst();
|
tok->clearAst();
|
||||||
tok->values.clear();
|
tok->clearValueFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// f(x=g()) => x=g(); f(x)
|
// f(x=g()) => x=g(); f(x)
|
||||||
|
@ -3904,8 +3904,8 @@ void Tokenizer::dump(std::ostream &out) const
|
||||||
out << " variable=\"" << tok->variable() << '\"';
|
out << " variable=\"" << tok->variable() << '\"';
|
||||||
if (tok->function())
|
if (tok->function())
|
||||||
out << " function=\"" << tok->function() << '\"';
|
out << " function=\"" << tok->function() << '\"';
|
||||||
if (!tok->values.empty())
|
if (!tok->values().empty())
|
||||||
out << " values=\"" << &tok->values << '\"';
|
out << " values=\"" << &tok->values() << '\"';
|
||||||
if (tok->type())
|
if (tok->type())
|
||||||
out << " type-scope=\"" << tok->type()->classScope << '\"';
|
out << " type-scope=\"" << tok->type()->classScope << '\"';
|
||||||
if (tok->astParent())
|
if (tok->astParent())
|
||||||
|
|
|
@ -235,55 +235,6 @@ static bool bailoutSelfAssignment(const Token * const tok)
|
||||||
return false;
|
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)
|
static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign sign, unsigned int bit)
|
||||||
{
|
{
|
||||||
if (value.isFloatValue()) {
|
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 */
|
/** set ValueFlow value and perform calculations if possible */
|
||||||
static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Settings *settings)
|
static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Settings *settings)
|
||||||
{
|
{
|
||||||
if (!addValue(tok,value))
|
if (!tok->addValue(value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Token *parent = const_cast<Token*>(tok->astParent());
|
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()) {
|
else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2() && parent->astOperand1()) {
|
||||||
// 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.isTokValue() || (condvalue.isIntValue() && 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);
|
||||||
|
@ -343,7 +294,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
|
||||||
const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
|
const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
|
||||||
if (!op) // #7769 segmentation fault at setTokenValue()
|
if (!op) // #7769 segmentation fault at setTokenValue()
|
||||||
return;
|
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())
|
if (std::find(values.begin(), values.end(), value) != values.end())
|
||||||
setTokenValue(parent, value, settings);
|
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)) &&
|
else if ((parent->isArithmeticalOp() || parent->isComparisonOp() || (parent->tokType() == Token::eBitOp) || (parent->tokType() == Token::eLogicalOp)) &&
|
||||||
parent->astOperand1() &&
|
parent->astOperand1() &&
|
||||||
parent->astOperand2()) {
|
parent->astOperand2()) {
|
||||||
const bool known = ((parent->astOperand1()->values.size() == 1U &&
|
const bool known = ((parent->astOperand1()->values().size() == 1U &&
|
||||||
parent->astOperand1()->values.front().isKnown()) ||
|
parent->astOperand1()->values().front().isKnown()) ||
|
||||||
(parent->astOperand2()->values.size() == 1U &&
|
(parent->astOperand2()->values().size() == 1U &&
|
||||||
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.isIntValue() && value.intvalue==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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<ValueFlow::Value>::const_iterator value1, value2;
|
for (std::list<ValueFlow::Value>::const_iterator 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->isIntValue() && !value1->isFloatValue() && !value1->isTokValue())
|
if (!value1->isIntValue() && !value1->isFloatValue() && !value1->isTokValue())
|
||||||
continue;
|
continue;
|
||||||
if (value1->isTokValue() && (!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 (std::list<ValueFlow::Value>::const_iterator value2 = parent->astOperand2()->values().begin(); value2 != parent->astOperand2()->values().end(); ++value2) {
|
||||||
if (!value2->isIntValue() && !value2->isFloatValue() && !value2->isTokValue())
|
if (!value2->isIntValue() && !value2->isFloatValue() && !value2->isTokValue())
|
||||||
continue;
|
continue;
|
||||||
if (value2->isTokValue() && (!parent->isComparisonOp() || value2->tokvalue->tokType() != Token::eString || value1->isTokValue()))
|
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() == "!") {
|
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->isIntValue())
|
if (!it->isIntValue())
|
||||||
continue;
|
continue;
|
||||||
ValueFlow::Value v(*it);
|
ValueFlow::Value v(*it);
|
||||||
|
@ -570,7 +520,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->isIntValue())
|
if (!it->isIntValue())
|
||||||
continue;
|
continue;
|
||||||
ValueFlow::Value v(*it);
|
ValueFlow::Value v(*it);
|
||||||
|
@ -594,7 +544,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
|
||||||
// unary minus
|
// unary minus
|
||||||
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->isIntValue() && !it->isFloatValue())
|
if (!it->isIntValue() && !it->isFloatValue())
|
||||||
continue;
|
continue;
|
||||||
ValueFlow::Value v(*it);
|
ValueFlow::Value v(*it);
|
||||||
|
@ -608,11 +558,10 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
|
||||||
|
|
||||||
// Array element
|
// Array element
|
||||||
else if (parent->str() == "[" && parent->astOperand1() && parent->astOperand2()) {
|
else if (parent->str() == "[" && parent->astOperand1() && parent->astOperand2()) {
|
||||||
std::list<ValueFlow::Value>::const_iterator value1, value2;
|
for (std::list<ValueFlow::Value>::const_iterator 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->isTokValue())
|
if (!value1->isTokValue())
|
||||||
continue;
|
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())
|
if (!value2->isIntValue())
|
||||||
continue;
|
continue;
|
||||||
if (value1->varId == 0U || value2->varId == 0U ||
|
if (value1->varId == 0U || value2->varId == 0U ||
|
||||||
|
@ -890,7 +839,7 @@ static void valueFlowBitAnd(TokenList *tokenlist)
|
||||||
if (tok->str() != "&")
|
if (tok->str() != "&")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tok->values.size() == 1U && tok->values.front().isKnown())
|
if (tok->values().size() == 1U && tok->values().front().isKnown())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!tok->astOperand1() || !tok->astOperand2())
|
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->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
|
||||||
if (tok->astOperand1()->isName() && tok->astOperand2()->hasKnownIntValue()) {
|
if (tok->astOperand1()->isName() && tok->astOperand2()->hasKnownIntValue()) {
|
||||||
vartok = tok->astOperand1();
|
vartok = tok->astOperand1();
|
||||||
num = tok->astOperand2()->values.front().intvalue;
|
num = tok->astOperand2()->values().front().intvalue;
|
||||||
} else if (tok->astOperand1()->hasKnownIntValue() && tok->astOperand2()->isName()) {
|
} else if (tok->astOperand1()->hasKnownIntValue() && tok->astOperand2()->isName()) {
|
||||||
vartok = tok->astOperand2();
|
vartok = tok->astOperand2();
|
||||||
num = tok->astOperand1()->values.front().intvalue;
|
num = tok->astOperand1()->values().front().intvalue;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1230,7 +1179,7 @@ static void valueFlowAST(Token *tok, unsigned int varid, const ValueFlow::Value
|
||||||
return;
|
return;
|
||||||
} else if (tok->str() == "||" && tok->astOperand1()) {
|
} else if (tok->str() == "||" && tok->astOperand1()) {
|
||||||
bool nonzero = false;
|
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);
|
nonzero |= (it->intvalue != 0);
|
||||||
}
|
}
|
||||||
if (!nonzero)
|
if (!nonzero)
|
||||||
|
@ -1391,7 +1340,7 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token * const condTok = tok2->next()->astOperand2();
|
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?
|
// Should scope be skipped because variable value is checked?
|
||||||
std::list<ValueFlow::Value> truevalues;
|
std::list<ValueFlow::Value> truevalues;
|
||||||
|
@ -1627,7 +1576,7 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (condition->hasKnownIntValue()) {
|
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;
|
||||||
for (it = values.begin(); it != values.end(); ++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;
|
const Token * const endOfVarScope = var->typeStartToken()->scope()->classEnd;
|
||||||
|
|
||||||
// Rhs values..
|
// Rhs values..
|
||||||
if (!tok->astOperand2() || tok->astOperand2()->values.empty())
|
if (!tok->astOperand2() || tok->astOperand2()->values().empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::list<ValueFlow::Value> values = tok->astOperand2()->values;
|
std::list<ValueFlow::Value> values = tok->astOperand2()->values();
|
||||||
const bool constValue = tok->astOperand2()->isNumber();
|
const bool constValue = tok->astOperand2()->isNumber();
|
||||||
|
|
||||||
if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) {
|
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()))
|
if (!var || !(var->isLocal() || var->isGlobal() || var->isArgument()))
|
||||||
continue;
|
continue;
|
||||||
std::list<ValueFlow::Value> values;
|
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%|&&")) {
|
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
||||||
Token *parent = const_cast<Token*>(tok->astParent());
|
Token *parent = const_cast<Token*>(tok->astParent());
|
||||||
|
@ -2186,7 +2135,7 @@ static void execute(const Token *expr,
|
||||||
*error = true;
|
*error = true;
|
||||||
|
|
||||||
else if (expr->hasKnownIntValue()) {
|
else if (expr->hasKnownIntValue()) {
|
||||||
*result = expr->values.front().intvalue;
|
*result = expr->values().front().intvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (expr->isNumber()) {
|
else if (expr->isNumber()) {
|
||||||
|
@ -2315,11 +2264,11 @@ static void execute(const Token *expr,
|
||||||
else if (expr->str() == "[" && expr->astOperand1() && expr->astOperand2()) {
|
else if (expr->str() == "[" && expr->astOperand1() && expr->astOperand2()) {
|
||||||
const Token *tokvalue;
|
const Token *tokvalue;
|
||||||
if (!programMemory->getTokValue(expr->astOperand1()->varId(), &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;
|
*error = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tokvalue = expr->astOperand1()->values.front().tokvalue;
|
tokvalue = expr->astOperand1()->values().front().tokvalue;
|
||||||
}
|
}
|
||||||
if (!tokvalue || !tokvalue->isLiteral()) {
|
if (!tokvalue || !tokvalue->isLiteral()) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -2688,7 +2637,7 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
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.isTokValue() && 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
|
||||||
|
@ -2715,14 +2664,14 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
|
||||||
valueFlowNumber(&tokenList);
|
valueFlowNumber(&tokenList);
|
||||||
for (Token *tok2 = tokenList.front(); tok2; tok2 = tok2->next()) {
|
for (Token *tok2 = tokenList.front(); tok2; tok2 = tok2->next()) {
|
||||||
if (tok2->str() == "arg1" && arg1) {
|
if (tok2->str() == "arg1" && arg1) {
|
||||||
setTokenValues(tok2, arg1->values, settings);
|
setTokenValues(tok2, arg1->values(), settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find result..
|
// Find result..
|
||||||
for (const Token *tok2 = tokenList.front(); tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = tokenList.front(); tok2; tok2 = tok2->next()) {
|
||||||
if (!tok2->astParent() && !tok2->values.empty()) {
|
if (!tok2->astParent() && !tok2->values().empty()) {
|
||||||
setTokenValues(tok, tok2->values, settings);
|
setTokenValues(tok, tok2->values(), settings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2758,8 +2707,8 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
|
||||||
std::list<ValueFlow::Value> argvalues;
|
std::list<ValueFlow::Value> argvalues;
|
||||||
|
|
||||||
// passing value(s) to function
|
// passing value(s) to function
|
||||||
if (!argtok->values.empty() && Token::Match(argtok, "%name%|%num%|%str% [,)]"))
|
if (!argtok->values().empty() && Token::Match(argtok, "%name%|%num%|%str% [,)]"))
|
||||||
argvalues = argtok->values;
|
argvalues = argtok->values();
|
||||||
else {
|
else {
|
||||||
// bool operator => values 1/0 are passed to function..
|
// bool operator => values 1/0 are passed to function..
|
||||||
const Token *op = argtok;
|
const Token *op = argtok;
|
||||||
|
@ -2769,8 +2718,8 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
|
||||||
argvalues.clear();
|
argvalues.clear();
|
||||||
argvalues.push_back(ValueFlow::Value(0));
|
argvalues.push_back(ValueFlow::Value(0));
|
||||||
argvalues.push_back(ValueFlow::Value(1));
|
argvalues.push_back(ValueFlow::Value(1));
|
||||||
} else if (Token::Match(op, "%cop%") && !op->values.empty()) {
|
} else if (Token::Match(op, "%cop%") && !op->values().empty()) {
|
||||||
argvalues = op->values;
|
argvalues = op->values();
|
||||||
} else {
|
} else {
|
||||||
// possible values are unknown..
|
// possible values are unknown..
|
||||||
continue;
|
continue;
|
||||||
|
@ -2801,7 +2750,7 @@ static void valueFlowFunctionDefaultParameter(TokenList *tokenlist, SymbolDataba
|
||||||
for (std::size_t arg = function->minArgCount(); arg < function->argCount(); arg++) {
|
for (std::size_t arg = function->minArgCount(); arg < function->argCount(); arg++) {
|
||||||
const Variable* var = function->getArgumentVar(arg);
|
const Variable* var = function->getArgumentVar(arg);
|
||||||
if (var && var->hasDefault() && Token::Match(var->nameToken(), "%var% = %num%|%str% [,)]")) {
|
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;
|
std::list<ValueFlow::Value> argvalues;
|
||||||
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) {
|
||||||
ValueFlow::Value v(*it);
|
ValueFlow::Value v(*it);
|
||||||
|
@ -2836,10 +2785,10 @@ static void valueFlowFunctionReturn(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
partok = partok->astOperand1();
|
partok = partok->astOperand1();
|
||||||
if (!isKnown(partok))
|
if (!isKnown(partok))
|
||||||
continue;
|
continue;
|
||||||
parvalues.push_back(partok->values.front().intvalue);
|
parvalues.push_back(partok->values().front().intvalue);
|
||||||
partok = partok->astParent();
|
partok = partok->astParent();
|
||||||
while (partok && partok->str() == ",") {
|
while (partok && partok->str() == ",") {
|
||||||
parvalues.push_back(partok->astOperand2()->values.front().intvalue);
|
parvalues.push_back(partok->astOperand2()->values().front().intvalue);
|
||||||
partok = partok->astParent();
|
partok = partok->astParent();
|
||||||
}
|
}
|
||||||
if (partok != tok)
|
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)
|
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->astOperand1(), settings);
|
||||||
valueFlowConstantFoldAST(expr->astOperand2(), settings);
|
valueFlowConstantFoldAST(expr->astOperand2(), settings);
|
||||||
valueFlowSetConstantValue(expr, settings, true /* TODO: this is a guess */);
|
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)
|
void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
|
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
|
||||||
tok->values.clear();
|
tok->clearValueFlow();
|
||||||
|
|
||||||
valueFlowNumber(tokenlist);
|
valueFlowNumber(tokenlist);
|
||||||
valueFlowString(tokenlist);
|
valueFlowString(tokenlist);
|
||||||
|
|
|
@ -95,7 +95,7 @@ private:
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
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->isIntValue() && it->intvalue == value)
|
if (it->isIntValue() && it->intvalue == value)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ private:
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
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->isTokValue() && Token::simpleMatch(it->tokvalue, value))
|
if (it->isTokValue() && Token::simpleMatch(it->tokvalue, value))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ private:
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
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->isMovedValue() && it->moveKind == moveKind)
|
if (it->isMovedValue() && it->moveKind == moveKind)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ private:
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
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->isIntValue() && it->intvalue == value && it->condition)
|
if (it->isIntValue() && it->intvalue == value && it->condition)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ private:
|
||||||
errout.str("");
|
errout.str("");
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr);
|
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[]) {
|
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
|
||||||
|
|
Loading…
Reference in New Issue