ValueFlow: some interface and namespace cleanups (#4746)

This commit is contained in:
Oliver Stöneberg 2023-01-28 10:20:47 +01:00 committed by GitHub
parent 464fbe8d53
commit afd13ea11d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 163 additions and 179 deletions

View File

@ -879,7 +879,7 @@ bool extractForLoopValues(const Token *forToken,
const Token *incExpr = forToken->next()->astOperand2()->astOperand2()->astOperand2();
if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%"))
return false;
std::vector<MathLib::bigint> minInitValue = getMinValue(makeIntegralInferModel(), initExpr->astOperand2()->values());
std::vector<MathLib::bigint> minInitValue = getMinValue(ValueFlow::makeIntegralInferModel(), initExpr->astOperand2()->values());
*varid = initExpr->astOperand1()->varId();
*knownInitValue = initExpr->astOperand2()->hasKnownIntValue();
*initValue = minInitValue.empty() ? 0 : minInitValue.front();
@ -1289,10 +1289,10 @@ const Token* followReferences(const Token* tok, ErrorPath* errors)
static bool isSameLifetime(const Token * const tok1, const Token * const tok2)
{
ValueFlow::Value v1 = getLifetimeObjValue(tok1);
ValueFlow::Value v1 = ValueFlow::getLifetimeObjValue(tok1);
if (!v1.isLifetimeValue())
return false;
ValueFlow::Value v2 = getLifetimeObjValue(tok2);
ValueFlow::Value v2 = ValueFlow::getLifetimeObjValue(tok2);
if (!v2.isLifetimeValue())
return false;
return v1.tokvalue == v2.tokvalue;

View File

@ -518,7 +518,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
for (const Token *tok = start; tok && tok != end; tok = tok->next()) {
// Return reference from function
if (returnRef && Token::simpleMatch(tok->astParent(), "return")) {
for (const LifetimeToken& lt : getLifetimeTokens(tok, true)) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok, true)) {
if (!printInconclusive && lt.inconclusive)
continue;
const Variable* var = lt.token->variable();
@ -537,14 +537,14 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
tok->variable()->declarationId() == tok->varId() && tok->variable()->isStatic() &&
!tok->variable()->isArgument()) {
ErrorPath errorPath;
const Variable *var = getLifetimeVariable(tok, errorPath);
const Variable *var = ValueFlow::getLifetimeVariable(tok, errorPath);
if (var && isInScope(var->nameToken(), tok->scope())) {
errorDanglingReference(tok, var, errorPath);
continue;
}
// Reference to temporary
} else if (tok->variable() && (tok->variable()->isReference() || tok->variable()->isRValueReference())) {
for (const LifetimeToken& lt : getLifetimeTokens(getParentLifetime(tok))) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(getParentLifetime(tok))) {
if (!printInconclusive && lt.inconclusive)
continue;
const Token * tokvalue = lt.token;
@ -565,13 +565,13 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
const Token* parent = getParentLifetime(mTokenizer->isCPP(), val.tokvalue, &mSettings->library);
if (!exprs.insert(parent).second)
continue;
for (const LifetimeToken& lt : getLifetimeTokens(parent, escape || isAssignedToNonLocal(tok))) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(parent, escape || isAssignedToNonLocal(tok))) {
const Token * tokvalue = lt.token;
if (val.isLocalLifetimeValue()) {
if (escape) {
if (getPointerDepth(tok) < getPointerDepth(tokvalue))
continue;
if (!isLifetimeBorrowed(tok, mSettings))
if (!ValueFlow::isLifetimeBorrowed(tok, mSettings))
continue;
if (tokvalue->exprId() == tok->exprId() && !(tok->variable() && tok->variable()->isArray()) &&
!astIsContainerView(tok->astParent()))
@ -604,7 +604,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
} else if (tok->variable() && tok->variable()->declarationId() == tok->varId()) {
var = tok->variable();
}
if (!isLifetimeBorrowed(tok, mSettings))
if (!ValueFlow::isLifetimeBorrowed(tok, mSettings))
continue;
const Token* nextTok = nextAfterAstRightmostLeaf(tok->astTop());
if (!nextTok)

View File

@ -1030,7 +1030,7 @@ void CheckBufferOverrun::objectIndex()
if (idx->hasKnownIntValue() && idx->getKnownIntValue() == 0)
continue;
std::vector<ValueFlow::Value> values = getLifetimeObjValues(obj, false, -1);
std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(obj, false, -1);
for (const ValueFlow::Value& v:values) {
if (v.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
continue;

View File

@ -1446,7 +1446,7 @@ void CheckOther::checkConstVariable()
retTok = retTok->astOperand2();
while (Token::simpleMatch(retTok, "."))
retTok = retTok->astOperand2();
return hasLifetimeToken(getParentLifetime(retTok), var->nameToken());
return ValueFlow::hasLifetimeToken(getParentLifetime(retTok), var->nameToken());
}))
continue;
}
@ -3671,8 +3671,8 @@ void CheckOther::checkComparePointers()
const Token *tok2 = tok->astOperand2();
if (!astIsPointer(tok1) || !astIsPointer(tok2))
continue;
ValueFlow::Value v1 = getLifetimeObjValue(tok1);
ValueFlow::Value v2 = getLifetimeObjValue(tok2);
ValueFlow::Value v1 = ValueFlow::getLifetimeObjValue(tok1);
ValueFlow::Value v2 = ValueFlow::getLifetimeObjValue(tok2);
if (!v1.isLocalLifetimeValue() || !v2.isLocalLifetimeValue())
continue;
const Variable *var1 = v1.tokvalue->variable();

View File

@ -727,7 +727,7 @@ static bool isSameIteratorContainerExpression(const Token* tok1,
static ValueFlow::Value getLifetimeIteratorValue(const Token* tok, MathLib::bigint path = 0)
{
std::vector<ValueFlow::Value> values = getLifetimeObjValues(tok, false, path);
std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, false, path);
auto it = std::find_if(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
return v.lifetimeKind == ValueFlow::Value::LifetimeKind::Iterator;
});
@ -1155,7 +1155,7 @@ void CheckStl::invalidContainer()
ErrorPath ep;
bool addressOf = false;
const Variable* var = getLifetimeVariable(info.tok, ep, &addressOf);
const Variable* var = ValueFlow::getLifetimeVariable(info.tok, ep, &addressOf);
// Check the reference is created before the change
if (var && var->declarationId() == r.tok->varId() && !addressOf) {
// An argument always reaches

View File

@ -1287,7 +1287,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
continue;
FwdAnalysis fwdAnalysis(mTokenizer->isCPP(), mSettings->library);
const Token* scopeEnd = getEndOfExprScope(expr, scope, /*smallest*/ false);
const Token* scopeEnd = ValueFlow::getEndOfExprScope(expr, scope, /*smallest*/ false);
if (fwdAnalysis.unusedValue(expr, start, scopeEnd)) {
if (!bailoutTypeName.empty()) {
if (bailoutTypeName != "auto")

View File

@ -1274,13 +1274,13 @@ static ValueFlow::Value executeImpl(const Token* expr, ProgramMemory& pm, const
if (expr->isComparisonOp()) {
if (rhs.isIntValue()) {
std::vector<ValueFlow::Value> result =
infer(makeIntegralInferModel(), expr->str(), expr->astOperand1()->values(), {rhs});
infer(ValueFlow::makeIntegralInferModel(), expr->str(), expr->astOperand1()->values(), {rhs});
if (result.empty() || !result.front().isKnown())
return unknown;
return result.front();
} else if (lhs.isIntValue()) {
std::vector<ValueFlow::Value> result =
infer(makeIntegralInferModel(), expr->str(), {lhs}, expr->astOperand2()->values());
infer(ValueFlow::makeIntegralInferModel(), expr->str(), {lhs}, expr->astOperand2()->values());
if (result.empty() || !result.front().isKnown())
return unknown;
return result.front();
@ -1353,7 +1353,7 @@ static ValueFlow::Value executeImpl(const Token* expr, ProgramMemory& pm, const
if (child->exprId() > 0 && pm.hasValue(child->exprId())) {
ValueFlow::Value& v = pm.at(child->exprId());
if (v.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) {
if (isContainerSizeChanged(child, v.indirect, settings))
if (ValueFlow::isContainerSizeChanged(child, v.indirect, settings))
v = unknown;
} else if (v.valueType != ValueFlow::Value::ValueType::UNINIT) {
if (isVariableChanged(child, v.indirect, settings, true))

View File

@ -343,10 +343,10 @@ static void parseCompareEachInt(
});
}
const Token* parseCompareInt(const Token* tok,
ValueFlow::Value& true_value,
ValueFlow::Value& false_value,
const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate)
const Token* ValueFlow::parseCompareInt(const Token* tok,
ValueFlow::Value& true_value,
ValueFlow::Value& false_value,
const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate)
{
const Token* result = nullptr;
parseCompareEachInt(
@ -370,7 +370,7 @@ const Token* parseCompareInt(const Token* tok,
return result;
}
const Token *parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value)
const Token *ValueFlow::parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value)
{
return parseCompareInt(tok, true_value, false_value, [](const Token* t) -> std::vector<MathLib::bigint> {
if (t->hasKnownIntValue())
@ -417,7 +417,7 @@ static bool isNumeric(const ValueFlow::Value& value) {
return value.isIntValue() || value.isFloatValue();
}
void combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value *result)
void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value *result)
{
if (value1.isKnown() && value2.isKnown())
result->setKnown();
@ -688,7 +688,7 @@ static void setTokenValue(Token* tok,
}
if (value.isLifetimeValue()) {
if (!isLifetimeBorrowed(parent, settings))
if (!ValueFlow::isLifetimeBorrowed(parent, settings))
return;
if (value.lifetimeKind == ValueFlow::Value::LifetimeKind::Iterator && astIsIterator(parent)) {
setTokenValue(parent,value,settings);
@ -1288,7 +1288,6 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
return tok->next();
}
static void valueFlowNumber(TokenList *tokenlist)
{
for (Token *tok = tokenlist->front(); tok;) {
@ -1973,8 +1972,8 @@ static void valueFlowGlobalStaticVar(TokenList *tokenList, const Settings *setti
}
}
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList* tokenlist);
ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist);
static ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList* tokenlist);
static ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist);
static Analyzer::Result valueFlowForward(Token* startToken,
const Token* endToken,
@ -3229,7 +3228,7 @@ struct MemberExpressionAnalyzer : SubExpressionAnalyzer {
enum class LifetimeCapture { Undefined, ByValue, ByReference };
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
static std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
{
std::string result;
if (!val)
@ -3253,7 +3252,7 @@ std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
return result;
}
std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ErrorPath &errorPath)
std::string ValueFlow::lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ErrorPath &errorPath)
{
const Token *tokvalue = val ? val->tokvalue : nullptr;
const Variable *tokvar = tokvalue ? tokvalue->variable() : nullptr;
@ -3291,7 +3290,7 @@ std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, Error
return msg;
}
std::vector<ValueFlow::Value> getLifetimeObjValues(const Token* tok, bool inconclusive, MathLib::bigint path)
std::vector<ValueFlow::Value> ValueFlow::getLifetimeObjValues(const Token* tok, bool inconclusive, MathLib::bigint path)
{
std::vector<ValueFlow::Value> result;
auto pred = [&](const ValueFlow::Value& v) {
@ -3338,9 +3337,9 @@ static bool derefShared(const Token* tok)
return !hasUniqueOwnership(ptrTok);
}
ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive)
ValueFlow::Value ValueFlow::getLifetimeObjValue(const Token *tok, bool inconclusive)
{
std::vector<ValueFlow::Value> values = getLifetimeObjValues(tok, inconclusive);
std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, inconclusive);
// There should only be one lifetime
if (values.size() != 1)
return ValueFlow::Value{};
@ -3348,16 +3347,16 @@ ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive)
}
template<class Predicate>
static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
bool escape,
ValueFlow::Value::ErrorPath errorPath,
Predicate pred,
int depth = 20)
static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
bool escape,
ValueFlow::Value::ErrorPath errorPath,
Predicate pred,
int depth = 20)
{
if (!tok)
return std::vector<LifetimeToken> {};
return std::vector<ValueFlow::LifetimeToken> {};
if (Token::simpleMatch(tok, "..."))
return std::vector<LifetimeToken>{};
return std::vector<ValueFlow::LifetimeToken>{};
const Variable *var = tok->variable();
if (pred(tok))
return {{tok, std::move(errorPath)}};
@ -3392,9 +3391,9 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
if (astIsContainer(contok))
return getLifetimeTokens(contok, escape, std::move(errorPath), pred, depth - 1);
else
return std::vector<LifetimeToken>{};
return std::vector<ValueFlow::LifetimeToken>{};
} else {
return std::vector<LifetimeToken> {};
return std::vector<ValueFlow::LifetimeToken> {};
}
}
} else if (Token::Match(tok->previous(), "%name% (")) {
@ -3402,12 +3401,12 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
if (f) {
if (!Function::returnsReference(f))
return {{tok, std::move(errorPath)}};
std::vector<LifetimeToken> result;
std::vector<ValueFlow::LifetimeToken> result;
std::vector<const Token*> returns = Function::findReturns(f);
for (const Token* returnTok : returns) {
if (returnTok == tok)
continue;
for (LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, depth - returns.size())) {
for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, depth - returns.size())) {
const Token* argvarTok = lt.token;
const Variable* argvar = argvarTok->variable();
if (!argvar)
@ -3416,11 +3415,11 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
const int n = getArgumentPos(argvar, f);
if (n < 0)
return std::vector<LifetimeToken> {};
return std::vector<ValueFlow::LifetimeToken> {};
std::vector<const Token*> args = getArguments(tok->previous());
// TODO: Track lifetimes of default parameters
if (n >= args.size())
return std::vector<LifetimeToken> {};
return std::vector<ValueFlow::LifetimeToken> {};
argTok = args[n];
lt.errorPath.emplace_back(returnTok, "Return reference.");
lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
@ -3432,7 +3431,7 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
"Calling member function on '" + argTok->expressionString() + "'.");
}
if (argTok) {
std::vector<LifetimeToken> arglts = LifetimeToken::setInconclusive(
std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()),
returns.size() > 1);
result.insert(result.end(), arglts.cbegin(), arglts.cend());
@ -3445,7 +3444,7 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
const Library::Container::Yield y = library->getYield(tok->previous()->str());
if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
errorPath.emplace_back(tok->previous(), "Accessing container.");
return LifetimeToken::setAddressOf(
return ValueFlow::LifetimeToken::setAddressOf(
getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1),
false);
}
@ -3474,8 +3473,8 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
return getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, depth - 1);
}
} else {
return LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1),
!(astIsContainer(vartok) && Token::simpleMatch(vartok->astParent(), "[")));
return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1),
!(astIsContainer(vartok) && Token::simpleMatch(vartok->astParent(), "[")));
}
} else if (Token::simpleMatch(tok, "{") && getArgumentStart(tok) &&
!Token::simpleMatch(getArgumentStart(tok), ",") && getArgumentStart(tok)->valueType()) {
@ -3490,14 +3489,14 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
return {{tok, std::move(errorPath)}};
}
std::vector<LifetimeToken> getLifetimeTokens(const Token* tok, bool escape, ValueFlow::Value::ErrorPath errorPath)
std::vector<ValueFlow::LifetimeToken> ValueFlow::getLifetimeTokens(const Token* tok, bool escape, ValueFlow::Value::ErrorPath errorPath)
{
return getLifetimeTokens(tok, escape, std::move(errorPath), [](const Token*) {
return false;
});
}
bool hasLifetimeToken(const Token* tok, const Token* lifetime)
bool ValueFlow::hasLifetimeToken(const Token* tok, const Token* lifetime)
{
bool result = false;
getLifetimeTokens(tok, false, ValueFlow::Value::ErrorPath{}, [&](const Token* tok2) {
@ -3509,7 +3508,7 @@ bool hasLifetimeToken(const Token* tok, const Token* lifetime)
static const Token* getLifetimeToken(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf = nullptr)
{
std::vector<LifetimeToken> lts = getLifetimeTokens(tok);
std::vector<ValueFlow::LifetimeToken> lts = ValueFlow::getLifetimeTokens(tok);
if (lts.size() != 1)
return nullptr;
if (lts.front().inconclusive)
@ -3520,7 +3519,7 @@ static const Token* getLifetimeToken(const Token* tok, ValueFlow::Value::ErrorPa
return lts.front().token;
}
const Variable* getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf)
const Variable* ValueFlow::getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf)
{
const Token* tok2 = getLifetimeToken(tok, errorPath, addressOf);
if (tok2 && tok2->variable())
@ -3528,7 +3527,7 @@ const Variable* getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPat
return nullptr;
}
const Variable* getLifetimeVariable(const Token* tok)
const Variable* ValueFlow::getLifetimeVariable(const Token* tok)
{
ValueFlow::Value::ErrorPath errorPath;
return getLifetimeVariable(tok, errorPath, nullptr);
@ -3662,7 +3661,7 @@ static bool isDifferentType(const Token* src, const Token* dst)
return false;
}
bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
bool ValueFlow::isLifetimeBorrowed(const Token *tok, const Settings *settings)
{
if (!tok)
return true;
@ -3729,7 +3728,7 @@ static const Token* getEndOfVarScope(const Variable* var)
return innerScope->bodyEnd;
}
const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope, bool smallest)
const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* defaultScope, bool smallest)
{
const Token* end = nullptr;
bool local = false;
@ -3767,7 +3766,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) {
std::list<ValueFlow::Value> values = tok->values();
values.remove_if(&isNotLifetimeValue);
valueFlowForward(nextAfterAstRightmostLeaf(tok), getEndOfExprScope(tok), tok->previous(), values, tokenlist);
valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), values, tokenlist);
return;
}
Token *parent = tok->astParent();
@ -3781,7 +3780,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
if (!parent->astOperand2() || parent->astOperand2()->values().empty())
return;
if (!isLifetimeBorrowed(parent->astOperand2(), settings))
if (!ValueFlow::isLifetimeBorrowed(parent->astOperand2(), settings))
return;
const Token* expr = getLHSVariableToken(parent);
@ -3791,7 +3790,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
if (expr->exprId() == 0)
return;
const Token* endOfVarScope = getEndOfExprScope(expr);
const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
// Only forward lifetime values
std::list<ValueFlow::Value> values = parent->astOperand2()->values();
@ -3938,7 +3937,7 @@ struct LifetimeStore {
if (!argtok)
return false;
bool update = false;
for (const LifetimeToken& lt : getLifetimeTokens(argtok)) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok)) {
if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
continue;
ErrorPath er = errorPath;
@ -4000,7 +3999,7 @@ struct LifetimeStore {
if (argtok->values().empty()) {
ErrorPath er;
er.emplace_back(argtok, message);
for (const LifetimeToken& lt : getLifetimeTokens(argtok)) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok)) {
if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
continue;
ValueFlow::Value value;
@ -4029,7 +4028,7 @@ struct LifetimeStore {
if (!v.isLifetimeValue())
continue;
const Token *tok3 = v.tokvalue;
for (const LifetimeToken& lt : getLifetimeTokens(tok3)) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok3)) {
if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
continue;
ErrorPath er = v.errorPath;
@ -4101,7 +4100,7 @@ struct LifetimeStore {
continue;
const Token *tok2 = v.tokvalue;
ErrorPath er = v.errorPath;
const Variable *var = getLifetimeVariable(tok2, er);
const Variable *var = ValueFlow::getLifetimeVariable(tok2, er);
// TODO: the inserted data is never used
er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
if (!var)
@ -4199,9 +4198,9 @@ static void valueFlowLifetimeUserConstructor(Token* tok,
const Token* expr = tok2->astOperand2();
if (!var)
continue;
if (!isLifetimeBorrowed(expr, settings))
if (!ValueFlow::isLifetimeBorrowed(expr, settings))
continue;
const Variable* argvar = getLifetimeVariable(expr);
const Variable* argvar = ValueFlow::getLifetimeVariable(expr);
if (var->isReference() || var->isRValueReference()) {
if (argvar && argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
paramCapture[argvar] = LifetimeCapture::ByReference;
@ -4312,7 +4311,7 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
LifetimeStore{
args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
.byDerefCopy(memtok, tokenlist, errorLogger, settings);
} else if (!args.empty() && isLifetimeBorrowed(args.back(), settings)) {
} else if (!args.empty() && ValueFlow::isLifetimeBorrowed(args.back(), settings)) {
LifetimeStore{
args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
.byVal(memtok, tokenlist, errorLogger, settings);
@ -4331,7 +4330,7 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
for (const Token* returnTok : returns) {
if (returnTok == tok)
continue;
const Variable *returnVar = getLifetimeVariable(returnTok);
const Variable *returnVar = ValueFlow::getLifetimeVariable(returnTok);
if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, settings, tokenlist->isCPP()))) {
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, errorLogger);
ls.inconclusive = inconclusive;
@ -4750,7 +4749,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, Erro
}
// address of
else if (tok->isUnaryOp("&")) {
for (const LifetimeToken& lt : getLifetimeTokens(tok->astOperand1())) {
for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1())) {
if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
continue;
ErrorPath errorPath = lt.errorPath;
@ -4869,7 +4868,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, Erro
// Check variables
else if (tok->variable()) {
ErrorPath errorPath;
const Variable * var = getLifetimeVariable(tok, errorPath);
const Variable * var = ValueFlow::getLifetimeVariable(tok, errorPath);
if (!var)
continue;
if (var->nameToken() == tok)
@ -5002,7 +5001,7 @@ static void valueFlowAfterMove(TokenList* tokenlist, SymbolDatabase* symboldatab
continue;
if (parent && parent->astOperand1() && parent->astOperand1()->varId() == varId)
continue;
const Token* const endOfVarScope = getEndOfExprScope(varTok);
const Token* const endOfVarScope = ValueFlow::getEndOfExprScope(varTok);
const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok);
const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
@ -5261,7 +5260,7 @@ static void valueFlowSymbolic(TokenList* tokenlist, SymbolDatabase* symboldataba
continue;
Token* start = nextAfterAstRightmostLeaf(tok);
const Token* end = getEndOfExprScope(tok->astOperand1(), scope);
const Token* end = ValueFlow::getEndOfExprScope(tok->astOperand1(), scope);
ValueFlow::Value rhs = makeSymbolic(tok->astOperand2());
rhs.errorPath.emplace_back(tok,
@ -5306,6 +5305,8 @@ static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth =
return nullptr;
}
static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val);
static void valueFlowSymbolicOperators(TokenList* tokenlist, SymbolDatabase* symboldatabase)
{
for (const Scope* scope : symboldatabase->functionScopes) {
@ -5530,7 +5531,7 @@ static void valueFlowForwardAssign(Token* const tok,
{
if (Token::simpleMatch(tok->astParent(), "return"))
return;
const Token* endOfVarScope = getEndOfExprScope(expr);
const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
if (std::any_of(values.cbegin(), values.cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
values.remove_if(std::mem_fn(&ValueFlow::Value::isLifetimeValue));
@ -5872,7 +5873,7 @@ static bool isBreakScope(const Token* const endToken)
return Token::findmatch(endToken->link(), "break|goto", endToken);
}
ValueFlow::Value asImpossible(ValueFlow::Value v)
ValueFlow::Value ValueFlow::asImpossible(ValueFlow::Value v)
{
v.invertRange();
v.setImpossible();
@ -5881,7 +5882,7 @@ ValueFlow::Value asImpossible(ValueFlow::Value v)
static void insertImpossible(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
{
std::transform(input.cbegin(), input.cend(), std::back_inserter(values), &asImpossible);
std::transform(input.cbegin(), input.cend(), std::back_inserter(values), &ValueFlow::asImpossible);
}
static void insertNegateKnown(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
@ -6476,7 +6477,7 @@ struct ConditionHandler {
changeKnownToPossible(values);
}
}
forward(after, getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist);
forward(after, ValueFlow::getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist);
}
});
}
@ -6548,7 +6549,7 @@ struct IntegralInferModel : InferModel {
}
};
ValuePtr<InferModel> makeIntegralInferModel() {
ValuePtr<InferModel> ValueFlow::makeIntegralInferModel() {
return IntegralInferModel{};
}
@ -6564,18 +6565,6 @@ ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, Math
return ValueFlow::Value{};
}
ValueFlow::Value inferCondition(const std::string &op, MathLib::bigint val, const Token* varTok)
{
if (!varTok)
return ValueFlow::Value{};
if (varTok->hasKnownIntValue())
return ValueFlow::Value{};
std::vector<ValueFlow::Value> r = infer(IntegralInferModel{}, op, val, varTok->values());
if (r.size() == 1 && r.front().isKnown())
return r.front();
return ValueFlow::Value{};
}
struct IteratorInferModel : InferModel {
virtual ValueFlow::Value::ValueType getType() const = 0;
bool match(const ValueFlow::Value& value) const override {
@ -6944,14 +6933,14 @@ static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabas
if (executeBody && vartok) {
std::list<ValueFlow::Value> initValues;
initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower);
initValues.push_back(asImpossible(initValues.back()));
initValues.push_back(ValueFlow::asImpossible(initValues.back()));
Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, initValues, tokenlist);
if (!result.action.isModified()) {
std::list<ValueFlow::Value> lastValues;
lastValues.emplace_back(lastValue, ValueFlow::Value::Bound::Upper);
lastValues.back().conditional = true;
lastValues.push_back(asImpossible(lastValues.back()));
lastValues.push_back(ValueFlow::asImpossible(lastValues.back()));
if (stepValue != 1)
lastValues.pop_front();
valueFlowForward(bodyStart, bodyStart->link(), vartok, lastValues, tokenlist);
@ -7838,7 +7827,7 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
return Action::Invalid;
if (isLikelyStreamRead(isCPP(), tok->astParent()))
return Action::Invalid;
if (astIsContainer(tok) && isContainerSizeChanged(tok, getIndirect(tok), getSettings()))
if (astIsContainer(tok) && ValueFlow::isContainerSizeChanged(tok, getIndirect(tok), getSettings()))
return read | Action::Invalid;
return read;
}
@ -7871,9 +7860,9 @@ static const Token* parseBinaryIntOp(const Token* expr,
return varTok;
}
const Token* solveExprValue(const Token* expr,
const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
ValueFlow::Value& value)
const Token* ValueFlow::solveExprValue(const Token* expr,
const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
ValueFlow::Value& value)
{
if (!value.isIntValue() && !value.isIteratorValue() && !value.isSymbolicValue())
return expr;
@ -7889,24 +7878,24 @@ const Token* solveExprValue(const Token* expr,
switch (expr->str()[0]) {
case '+': {
value.intvalue -= intval;
return solveExprValue(binaryTok, eval, value);
return ValueFlow::solveExprValue(binaryTok, eval, value);
}
case '-': {
if (rhs)
value.intvalue = intval - value.intvalue;
else
value.intvalue += intval;
return solveExprValue(binaryTok, eval, value);
return ValueFlow::solveExprValue(binaryTok, eval, value);
}
case '*': {
if (intval == 0)
break;
value.intvalue /= intval;
return solveExprValue(binaryTok, eval, value);
return ValueFlow::solveExprValue(binaryTok, eval, value);
}
case '^': {
value.intvalue ^= intval;
return solveExprValue(binaryTok, eval, value);
return ValueFlow::solveExprValue(binaryTok, eval, value);
}
}
}
@ -7915,7 +7904,7 @@ const Token* solveExprValue(const Token* expr,
static const Token* solveExprValue(const Token* expr, ValueFlow::Value& value)
{
return solveExprValue(
return ValueFlow::solveExprValue(
expr,
[](const Token* tok) -> std::vector<MathLib::bigint> {
if (tok->hasKnownIntValue())
@ -7940,7 +7929,7 @@ ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, const ValueFlow::Va
return ExpressionAnalyzer(exprTok, value, tokenlist);
}
bool isContainerSizeChanged(const Token* tok, int indirect, const Settings* settings, int depth)
bool ValueFlow::isContainerSizeChanged(const Token* tok, int indirect, const Settings* settings, int depth)
{
if (!tok)
return false;
@ -7991,7 +7980,7 @@ static bool isContainerSizeChanged(nonneg int varId,
for (const Token *tok = start; tok != end; tok = tok->next()) {
if (tok->varId() != varId)
continue;
if (isContainerSizeChanged(tok, indirect, settings, depth))
if (ValueFlow::isContainerSizeChanged(tok, indirect, settings, depth))
return true;
}
return false;

View File

@ -47,7 +47,7 @@ class ValuePtr;
namespace ValueFlow {
/// Constant folding of expression. This can be used before the full ValueFlow has been executed (ValueFlow::setValues).
const ValueFlow::Value * valueFlowConstantFoldAST(Token *expr, const Settings *settings);
const Value * valueFlowConstantFoldAST(Token *expr, const Settings *settings);
/// Perform valueflow analysis.
void setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings);
@ -56,82 +56,77 @@ namespace ValueFlow {
size_t getSizeOf(const ValueType &vt, const Settings *settings);
const ValueFlow::Value* findValue(const std::list<ValueFlow::Value>& values,
const Settings* settings,
const std::function<bool(const ValueFlow::Value&)> &pred);
const Value* findValue(const std::list<Value>& values,
const Settings* settings,
const std::function<bool(const Value&)> &pred);
std::vector<ValueFlow::Value> isOutOfBounds(const Value& size, const Token* indexTok, bool possible = true);
std::vector<Value> isOutOfBounds(const Value& size, const Token* indexTok, bool possible = true);
Value asImpossible(Value v);
bool isContainerSizeChanged(const Token* tok, int indirect, const Settings* settings = nullptr, int depth = 20);
struct LifetimeToken {
const Token* token;
Value::ErrorPath errorPath;
bool addressOf;
bool inconclusive;
LifetimeToken() : token(nullptr), errorPath(), addressOf(false), inconclusive(false) {}
LifetimeToken(const Token* token, Value::ErrorPath errorPath)
: token(token), errorPath(std::move(errorPath)), addressOf(false), inconclusive(false)
{}
LifetimeToken(const Token* token, bool addressOf, Value::ErrorPath errorPath)
: token(token), errorPath(std::move(errorPath)), addressOf(addressOf), inconclusive(false)
{}
static std::vector<LifetimeToken> setAddressOf(std::vector<LifetimeToken> v, bool b) {
for (LifetimeToken& x : v)
x.addressOf = b;
return v;
}
static std::vector<LifetimeToken> setInconclusive(std::vector<LifetimeToken> v, bool b) {
for (LifetimeToken& x : v)
x.inconclusive = b;
return v;
}
};
const Token *parseCompareInt(const Token *tok, Value &true_value, Value &false_value, const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate);
const Token *parseCompareInt(const Token *tok, Value &true_value, Value &false_value);
CPPCHECKLIB ValuePtr<InferModel> makeIntegralInferModel();
const Token* solveExprValue(const Token* expr,
const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
Value& value);
std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
bool escape = false,
Value::ErrorPath errorPath = Value::ErrorPath{});
bool hasLifetimeToken(const Token* tok, const Token* lifetime);
const Variable* getLifetimeVariable(const Token* tok, Value::ErrorPath& errorPath, bool* addressOf = nullptr);
const Variable* getLifetimeVariable(const Token* tok);
bool isLifetimeBorrowed(const Token *tok, const Settings *settings);
std::string lifetimeMessage(const Token *tok, const Value *val, Value::ErrorPath &errorPath);
CPPCHECKLIB Value getLifetimeObjValue(const Token *tok, bool inconclusive = false);
CPPCHECKLIB std::vector<Value> getLifetimeObjValues(const Token* tok,
bool inconclusive = false,
MathLib::bigint path = 0);
const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr, bool smallest = true);
void combineValueProperties(const Value& value1, const Value& value2, Value* result);
}
ValueFlow::Value asImpossible(ValueFlow::Value v);
bool isContainerSizeChanged(const Token* tok, int indirect, const Settings* settings = nullptr, int depth = 20);
struct LifetimeToken {
const Token* token;
ValueFlow::Value::ErrorPath errorPath;
bool addressOf;
bool inconclusive;
LifetimeToken() : token(nullptr), errorPath(), addressOf(false), inconclusive(false) {}
LifetimeToken(const Token* token, ValueFlow::Value::ErrorPath errorPath)
: token(token), errorPath(std::move(errorPath)), addressOf(false), inconclusive(false)
{}
LifetimeToken(const Token* token, bool addressOf, ValueFlow::Value::ErrorPath errorPath)
: token(token), errorPath(std::move(errorPath)), addressOf(addressOf), inconclusive(false)
{}
static std::vector<LifetimeToken> setAddressOf(std::vector<LifetimeToken> v, bool b) {
for (LifetimeToken& x : v)
x.addressOf = b;
return v;
}
static std::vector<LifetimeToken> setInconclusive(std::vector<LifetimeToken> v, bool b) {
for (LifetimeToken& x : v)
x.inconclusive = b;
return v;
}
};
const Token *parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value, const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate);
const Token *parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value);
ValueFlow::Value inferCondition(const std::string& op, MathLib::bigint val, const Token* varTok);
ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val);
CPPCHECKLIB ValuePtr<InferModel> makeIntegralInferModel();
const Token* solveExprValue(const Token* expr,
const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
ValueFlow::Value& value);
std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
bool escape = false,
ValueFlow::Value::ErrorPath errorPath = ValueFlow::Value::ErrorPath{});
bool hasLifetimeToken(const Token* tok, const Token* lifetime);
const Variable* getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf = nullptr);
const Variable* getLifetimeVariable(const Token* tok);
bool isLifetimeBorrowed(const Token *tok, const Settings *settings);
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val);
std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ValueFlow::Value::ErrorPath &errorPath);
CPPCHECKLIB ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive = false);
CPPCHECKLIB std::vector<ValueFlow::Value> getLifetimeObjValues(const Token* tok,
bool inconclusive = false,
MathLib::bigint path = 0);
const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr, bool smallest = true);
void combineValueProperties(const ValueFlow::Value& value1, const ValueFlow::Value& value2, ValueFlow::Value* result);
#endif // valueflowH