Refactor valueflow forward and reverse functions and unify them (#4127)
* Move functions around * Make it a template to handle both overloads * Simplify forward * Remove container forward * Remove unused settings params * Format * Remove valueFlowForwardExpression * Format * Remove init list * Make const ref * Remove braces * Remove braces
This commit is contained in:
parent
5999b35130
commit
7405ea039d
|
@ -1827,20 +1827,78 @@ 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 Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
|
const Token* endToken,
|
||||||
|
const Token* exprTok,
|
||||||
|
const ValueFlow::Value& value,
|
||||||
|
TokenList* const tokenlist)
|
||||||
|
{
|
||||||
|
return valueFlowGenericForward(startToken, endToken, makeAnalyzer(exprTok, value, tokenlist), tokenlist->getSettings());
|
||||||
|
}
|
||||||
|
|
||||||
static Analyzer::Result valueFlowForward(Token* startToken,
|
static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
const Token* endToken,
|
const Token* endToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* const tokenlist,
|
TokenList* const tokenlist)
|
||||||
const Settings* settings);
|
{
|
||||||
|
Analyzer::Result result{};
|
||||||
|
for (const ValueFlow::Value& v : values) {
|
||||||
|
result.update(valueFlowForward(startToken, endToken, exprTok, v, tokenlist));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueOrValues>
|
||||||
|
static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, const ValueOrValues& v, TokenList* tokenlist)
|
||||||
|
{
|
||||||
|
const Token* endToken = nullptr;
|
||||||
|
const Function* f = Scope::nestedInFunction(startToken->scope());
|
||||||
|
if (f && f->functionScope)
|
||||||
|
endToken = f->functionScope->bodyEnd;
|
||||||
|
return valueFlowForward(startToken, endToken, exprTok, v, tokenlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Analyzer::Result valueFlowForwardRecursive(Token* top,
|
||||||
|
const Token* exprTok,
|
||||||
|
const std::list<ValueFlow::Value>& values,
|
||||||
|
TokenList* const tokenlist)
|
||||||
|
{
|
||||||
|
Analyzer::Result result{};
|
||||||
|
for (const ValueFlow::Value& v : values) {
|
||||||
|
result.update(valueFlowGenericForward(top, makeAnalyzer(exprTok, v, tokenlist), tokenlist->getSettings()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void valueFlowReverse(Token* tok,
|
||||||
|
const Token* const endToken,
|
||||||
|
const Token* const varToken,
|
||||||
|
const std::list<ValueFlow::Value>& values,
|
||||||
|
TokenList* tokenlist)
|
||||||
|
{
|
||||||
|
for (const ValueFlow::Value& v : values) {
|
||||||
|
valueFlowGenericReverse(tok, endToken, makeReverseAnalyzer(varToken, v, tokenlist), tokenlist->getSettings());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
static void valueFlowReverse(TokenList* tokenlist,
|
static void valueFlowReverse(TokenList* tokenlist,
|
||||||
Token* tok,
|
Token* tok,
|
||||||
const Token* const varToken,
|
const Token* const varToken,
|
||||||
ValueFlow::Value val,
|
ValueFlow::Value val,
|
||||||
const ValueFlow::Value& val2,
|
const ValueFlow::Value& val2,
|
||||||
ErrorLogger* errorLogger,
|
ErrorLogger* /*errorLogger*/,
|
||||||
const Settings* settings);
|
const Settings* = nullptr)
|
||||||
|
{
|
||||||
|
std::list<ValueFlow::Value> values = {val};
|
||||||
|
if (val2.varId != 0)
|
||||||
|
values.push_back(val2);
|
||||||
|
valueFlowReverse(tok, nullptr, varToken, values, tokenlist);
|
||||||
|
}
|
||||||
|
|
||||||
static bool isConditionKnown(const Token* tok, bool then)
|
static bool isConditionKnown(const Token* tok, bool then)
|
||||||
{
|
{
|
||||||
|
@ -2647,8 +2705,6 @@ struct ValueFlowAnalyzer : Analyzer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList* tokenlist);
|
|
||||||
|
|
||||||
struct SingleValueFlowAnalyzer : ValueFlowAnalyzer {
|
struct SingleValueFlowAnalyzer : ValueFlowAnalyzer {
|
||||||
std::unordered_map<nonneg int, const Variable*> varids;
|
std::unordered_map<nonneg int, const Variable*> varids;
|
||||||
std::unordered_map<nonneg int, const Variable*> aliases;
|
std::unordered_map<nonneg int, const Variable*> aliases;
|
||||||
|
@ -2944,162 +3000,6 @@ struct MemberExpressionAnalyzer : SubExpressionAnalyzer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Analyzer::Result valueFlowForwardExpression(Token* startToken,
|
|
||||||
const Token* endToken,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
const TokenList* const tokenlist,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
|
||||||
Analyzer::Result result{};
|
|
||||||
for (const ValueFlow::Value& v : values) {
|
|
||||||
ExpressionAnalyzer a(exprTok, v, tokenlist);
|
|
||||||
result.update(valueFlowGenericForward(startToken, endToken, a, settings));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Token* parseBinaryIntOp(const Token* expr,
|
|
||||||
const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
|
|
||||||
MathLib::bigint& known)
|
|
||||||
{
|
|
||||||
if (!expr)
|
|
||||||
return nullptr;
|
|
||||||
if (!expr->astOperand1() || !expr->astOperand2())
|
|
||||||
return nullptr;
|
|
||||||
if (expr->astOperand1()->exprId() == 0 && expr->astOperand2()->exprId() == 0)
|
|
||||||
return nullptr;
|
|
||||||
std::vector<MathLib::bigint> x1 = eval(expr->astOperand1());
|
|
||||||
std::vector<MathLib::bigint> x2 = eval(expr->astOperand2());
|
|
||||||
if (expr->astOperand1()->exprId() == 0 && x1.empty())
|
|
||||||
return nullptr;
|
|
||||||
if (expr->astOperand2()->exprId() == 0 && x2.empty())
|
|
||||||
return nullptr;
|
|
||||||
const Token* varTok = nullptr;
|
|
||||||
if (!x1.empty() && x2.empty()) {
|
|
||||||
varTok = expr->astOperand2();
|
|
||||||
known = x1.front();
|
|
||||||
} else if (x1.empty() && !x2.empty()) {
|
|
||||||
varTok = expr->astOperand1();
|
|
||||||
known = x2.front();
|
|
||||||
}
|
|
||||||
return varTok;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token* 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;
|
|
||||||
if (value.isSymbolicValue() && !Token::Match(expr, "+|-"))
|
|
||||||
return expr;
|
|
||||||
MathLib::bigint intval;
|
|
||||||
const Token* binaryTok = parseBinaryIntOp(expr, eval, intval);
|
|
||||||
bool rhs = astIsRHS(binaryTok);
|
|
||||||
// If its on the rhs, then -1 multiplication is needed, which is not possible with simple delta analysis used currently for symbolic values
|
|
||||||
if (value.isSymbolicValue() && rhs && Token::simpleMatch(expr, "-"))
|
|
||||||
return expr;
|
|
||||||
if (binaryTok && expr->str().size() == 1) {
|
|
||||||
switch (expr->str()[0]) {
|
|
||||||
case '+': {
|
|
||||||
value.intvalue -= intval;
|
|
||||||
return solveExprValue(binaryTok, eval, value);
|
|
||||||
}
|
|
||||||
case '-': {
|
|
||||||
if (rhs)
|
|
||||||
value.intvalue = intval - value.intvalue;
|
|
||||||
else
|
|
||||||
value.intvalue += intval;
|
|
||||||
return solveExprValue(binaryTok, eval, value);
|
|
||||||
}
|
|
||||||
case '*': {
|
|
||||||
if (intval == 0)
|
|
||||||
break;
|
|
||||||
value.intvalue /= intval;
|
|
||||||
return solveExprValue(binaryTok, eval, value);
|
|
||||||
}
|
|
||||||
case '^': {
|
|
||||||
value.intvalue ^= intval;
|
|
||||||
return solveExprValue(binaryTok, eval, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Token* solveExprValue(const Token* expr, ValueFlow::Value& value)
|
|
||||||
{
|
|
||||||
return solveExprValue(
|
|
||||||
expr,
|
|
||||||
[](const Token* tok) -> std::vector<MathLib::bigint> {
|
|
||||||
if (tok->hasKnownIntValue())
|
|
||||||
return {tok->values().front().intvalue};
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList* tokenlist)
|
|
||||||
{
|
|
||||||
const Token* expr = solveExprValue(exprTok, value);
|
|
||||||
return ExpressionAnalyzer(expr, value, tokenlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Analyzer::Result valueFlowForward(Token* startToken,
|
|
||||||
const Token* endToken,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* const tokenlist,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
|
||||||
Analyzer::Result result{};
|
|
||||||
for (const ValueFlow::Value& v : values) {
|
|
||||||
result.update(valueFlowGenericForward(startToken, endToken, makeAnalyzer(exprTok, v, tokenlist), settings));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Analyzer::Result valueFlowForward(Token* top,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* const tokenlist,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
|
||||||
Analyzer::Result result{};
|
|
||||||
for (const ValueFlow::Value& v : values) {
|
|
||||||
result.update(valueFlowGenericForward(top, makeAnalyzer(exprTok, v, tokenlist), settings));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void valueFlowReverse(Token* tok,
|
|
||||||
const Token* const endToken,
|
|
||||||
const Token* const varToken,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
|
||||||
for (const ValueFlow::Value& v : values) {
|
|
||||||
ExpressionAnalyzer a(varToken, v, tokenlist);
|
|
||||||
valueFlowGenericReverse(tok, endToken, a, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void valueFlowReverse(TokenList* tokenlist,
|
|
||||||
Token* tok,
|
|
||||||
const Token* const varToken,
|
|
||||||
ValueFlow::Value val,
|
|
||||||
const ValueFlow::Value& val2,
|
|
||||||
ErrorLogger* /*errorLogger*/,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
|
||||||
std::list<ValueFlow::Value> values = {val};
|
|
||||||
if (val2.varId != 0)
|
|
||||||
values.push_back(val2);
|
|
||||||
valueFlowReverse(tok, nullptr, varToken, values, tokenlist, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class LifetimeCapture { Undefined, ByValue, ByReference };
|
enum class LifetimeCapture { Undefined, ByValue, ByReference };
|
||||||
|
|
||||||
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
|
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
|
||||||
|
@ -3591,7 +3491,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
|
||||||
if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) {
|
if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) {
|
||||||
std::list<ValueFlow::Value> values = tok->values();
|
std::list<ValueFlow::Value> values = tok->values();
|
||||||
values.remove_if(&isNotLifetimeValue);
|
values.remove_if(&isNotLifetimeValue);
|
||||||
valueFlowForward(nextAfterAstRightmostLeaf(tok), getEndOfExprScope(tok), tok->previous(), values, tokenlist, settings);
|
valueFlowForward(nextAfterAstRightmostLeaf(tok), getEndOfExprScope(tok), tok->previous(), values, tokenlist);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Token *parent = tok->astParent();
|
Token *parent = tok->astParent();
|
||||||
|
@ -3631,12 +3531,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
|
||||||
const Token *nextExpression = nextAfterAstRightmostLeaf(parent);
|
const Token *nextExpression = nextAfterAstRightmostLeaf(parent);
|
||||||
|
|
||||||
if (expr->exprId() > 0) {
|
if (expr->exprId() > 0) {
|
||||||
valueFlowForwardExpression(const_cast<Token*>(nextExpression),
|
valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope->next(), expr, values, tokenlist);
|
||||||
endOfVarScope->next(),
|
|
||||||
expr,
|
|
||||||
values,
|
|
||||||
tokenlist,
|
|
||||||
settings);
|
|
||||||
|
|
||||||
for (ValueFlow::Value& val : values) {
|
for (ValueFlow::Value& val : values) {
|
||||||
if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address)
|
if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address)
|
||||||
|
@ -3647,12 +3542,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
|
||||||
const Token* parentLifetime =
|
const Token* parentLifetime =
|
||||||
getParentLifetime(tokenlist->isCPP(), parent->astOperand1()->astOperand2(), &settings->library);
|
getParentLifetime(tokenlist->isCPP(), parent->astOperand1()->astOperand2(), &settings->library);
|
||||||
if (parentLifetime && parentLifetime->exprId() > 0) {
|
if (parentLifetime && parentLifetime->exprId() > 0) {
|
||||||
valueFlowForward(const_cast<Token*>(nextExpression),
|
valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, parentLifetime, values, tokenlist);
|
||||||
endOfVarScope,
|
|
||||||
parentLifetime,
|
|
||||||
values,
|
|
||||||
tokenlist,
|
|
||||||
settings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3673,7 +3563,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
|
||||||
const Token *nextExpression = nextAfterAstRightmostLeaf(parent);
|
const Token *nextExpression = nextAfterAstRightmostLeaf(parent);
|
||||||
// Only forward lifetime values
|
// Only forward lifetime values
|
||||||
values.remove_if(&isNotLifetimeValue);
|
values.remove_if(&isNotLifetimeValue);
|
||||||
valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, tok, values, tokenlist, settings);
|
valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, tok, values, tokenlist);
|
||||||
// Cast
|
// Cast
|
||||||
} else if (parent->isCast()) {
|
} else if (parent->isCast()) {
|
||||||
std::list<ValueFlow::Value> values = tok->values();
|
std::list<ValueFlow::Value> values = tok->values();
|
||||||
|
@ -4724,7 +4614,7 @@ static void valueFlowAfterMove(TokenList* tokenlist, SymbolDatabase* symboldatab
|
||||||
continue;
|
continue;
|
||||||
const Token * const endOfVarScope = var->scope()->bodyEnd;
|
const Token * const endOfVarScope = var->scope()->bodyEnd;
|
||||||
setTokenValue(varTok, value, settings);
|
setTokenValue(varTok, value, settings);
|
||||||
valueFlowForward(varTok->next(), endOfVarScope, varTok, values, tokenlist, settings);
|
valueFlowForward(varTok->next(), endOfVarScope, varTok, values, tokenlist);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ValueFlow::Value::MoveKind moveKind;
|
ValueFlow::Value::MoveKind moveKind;
|
||||||
|
@ -4760,8 +4650,7 @@ static void valueFlowAfterMove(TokenList* tokenlist, SymbolDatabase* symboldatab
|
||||||
const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok);
|
const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok);
|
||||||
const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
|
const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
|
||||||
if (endOfFunctionCall)
|
if (endOfFunctionCall)
|
||||||
valueFlowForward(
|
valueFlowForward(const_cast<Token*>(endOfFunctionCall), endOfVarScope, varTok, values, tokenlist);
|
||||||
const_cast<Token*>(endOfFunctionCall), endOfVarScope, varTok, values, tokenlist, settings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4981,13 +4870,13 @@ static void valueFlowSymbolic(TokenList* tokenlist, SymbolDatabase* symboldataba
|
||||||
rhs.errorPath.emplace_back(tok,
|
rhs.errorPath.emplace_back(tok,
|
||||||
tok->astOperand1()->expressionString() + " is assigned '" +
|
tok->astOperand1()->expressionString() + " is assigned '" +
|
||||||
tok->astOperand2()->expressionString() + "' here.");
|
tok->astOperand2()->expressionString() + "' here.");
|
||||||
valueFlowForward(start, end, tok->astOperand1(), {rhs}, tokenlist, tokenlist->getSettings());
|
valueFlowForward(start, end, tok->astOperand1(), rhs, tokenlist);
|
||||||
|
|
||||||
ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
|
ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
|
||||||
lhs.errorPath.emplace_back(tok,
|
lhs.errorPath.emplace_back(tok,
|
||||||
tok->astOperand1()->expressionString() + " is assigned '" +
|
tok->astOperand1()->expressionString() + " is assigned '" +
|
||||||
tok->astOperand2()->expressionString() + "' here.");
|
tok->astOperand2()->expressionString() + "' here.");
|
||||||
valueFlowForward(start, end, tok->astOperand2(), {lhs}, tokenlist, tokenlist->getSettings());
|
valueFlowForward(start, end, tok->astOperand2(), lhs, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5267,7 +5156,7 @@ static void valueFlowForwardAssign(Token* const tok,
|
||||||
constValues.splice(constValues.end(), values, it, values.end());
|
constValues.splice(constValues.end(), values, it, values.end());
|
||||||
valueFlowForwardConst(const_cast<Token*>(nextExpression), endOfVarScope, expr->variable(), constValues, settings);
|
valueFlowForwardConst(const_cast<Token*>(nextExpression), endOfVarScope, expr->variable(), constValues, settings);
|
||||||
}
|
}
|
||||||
valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, expr, values, tokenlist, settings);
|
valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, expr, values, tokenlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowForwardAssign(Token* const tok,
|
static void valueFlowForwardAssign(Token* const tok,
|
||||||
|
@ -5439,7 +5328,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
|
||||||
value.errorPath.emplace_back(tok,
|
value.errorPath.emplace_back(tok,
|
||||||
tok->astOperand1()->expressionString() + " is assigned '" +
|
tok->astOperand1()->expressionString() + " is assigned '" +
|
||||||
tok->astOperand2()->expressionString() + "' here.");
|
tok->astOperand2()->expressionString() + "' here.");
|
||||||
valueFlowForward(start, end, expr, {value}, tokenlist, settings);
|
valueFlowForward(start, end, expr, value, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5545,27 +5434,33 @@ struct ConditionHandler {
|
||||||
Condition() : vartok(nullptr), true_values(), false_values(), inverted(false), impossible(true) {}
|
Condition() : vartok(nullptr), true_values(), false_values(), inverted(false), impossible(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const = 0;
|
||||||
|
|
||||||
virtual Analyzer::Result forward(Token* start,
|
virtual Analyzer::Result forward(Token* start,
|
||||||
const Token* stop,
|
const Token* stop,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* tokenlist,
|
TokenList* tokenlist) const
|
||||||
const Settings* settings) const = 0;
|
{
|
||||||
|
return valueFlowForward(start->next(), stop, exprTok, values, tokenlist);
|
||||||
|
}
|
||||||
|
|
||||||
virtual Analyzer::Result forward(Token* top,
|
virtual Analyzer::Result forward(Token* top,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* tokenlist,
|
TokenList* tokenlist) const
|
||||||
const Settings* settings) const = 0;
|
{
|
||||||
|
return valueFlowForwardRecursive(top, exprTok, values, tokenlist);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void reverse(Token* start,
|
virtual void reverse(Token* start,
|
||||||
const Token* endToken,
|
const Token* endToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* tokenlist,
|
TokenList* tokenlist) const
|
||||||
const Settings* settings) const = 0;
|
{
|
||||||
|
return valueFlowReverse(start, endToken, exprTok, values, tokenlist);
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const = 0;
|
}
|
||||||
|
|
||||||
void traverseCondition(TokenList* tokenlist,
|
void traverseCondition(TokenList* tokenlist,
|
||||||
SymbolDatabase* symboldatabase,
|
SymbolDatabase* symboldatabase,
|
||||||
|
@ -5686,7 +5581,7 @@ struct ConditionHandler {
|
||||||
})) {
|
})) {
|
||||||
// Start at the end of the loop body
|
// Start at the end of the loop body
|
||||||
Token* bodyTok = top->link()->next();
|
Token* bodyTok = top->link()->next();
|
||||||
reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, settings);
|
reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist);
|
||||||
}
|
}
|
||||||
if (settings->debugwarnings)
|
if (settings->debugwarnings)
|
||||||
bailout(tokenlist,
|
bailout(tokenlist,
|
||||||
|
@ -5705,7 +5600,7 @@ struct ConditionHandler {
|
||||||
if (!startTok)
|
if (!startTok)
|
||||||
startTok = tok->previous();
|
startTok = tok->previous();
|
||||||
|
|
||||||
reverse(startTok, nullptr, cond.vartok, values, tokenlist, settings);
|
reverse(startTok, nullptr, cond.vartok, values, tokenlist);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5792,7 +5687,7 @@ struct ConditionHandler {
|
||||||
return v.isImpossible();
|
return v.isImpossible();
|
||||||
});
|
});
|
||||||
for (Token* start:nextExprs) {
|
for (Token* start:nextExprs) {
|
||||||
Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, settings);
|
Analyzer::Result r = forward(start, cond.vartok, values, tokenlist);
|
||||||
if (r.terminate != Analyzer::Terminate::None)
|
if (r.terminate != Analyzer::Terminate::None)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5852,8 +5747,8 @@ struct ConditionHandler {
|
||||||
|
|
||||||
if (Token::simpleMatch(condTop, "?")) {
|
if (Token::simpleMatch(condTop, "?")) {
|
||||||
Token* colon = condTop->astOperand2();
|
Token* colon = condTop->astOperand2();
|
||||||
forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist, settings);
|
forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist);
|
||||||
forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist, settings);
|
forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist);
|
||||||
// TODO: Handle after condition
|
// TODO: Handle after condition
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5937,8 +5832,7 @@ struct ConditionHandler {
|
||||||
std::list<ValueFlow::Value>& values = (i == 0 ? thenValues : elseValues);
|
std::list<ValueFlow::Value>& values = (i == 0 ? thenValues : elseValues);
|
||||||
valueFlowSetConditionToKnown(condTok, values, i == 0);
|
valueFlowSetConditionToKnown(condTok, values, i == 0);
|
||||||
|
|
||||||
Analyzer::Result r =
|
Analyzer::Result r = forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist);
|
||||||
forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist, settings);
|
|
||||||
deadBranch[i] = r.terminate == Analyzer::Terminate::Escape;
|
deadBranch[i] = r.terminate == Analyzer::Terminate::Escape;
|
||||||
if (r.action.isModified() && !deadBranch[i])
|
if (r.action.isModified() && !deadBranch[i])
|
||||||
changeBlock = i;
|
changeBlock = i;
|
||||||
|
@ -6040,7 +5934,7 @@ struct ConditionHandler {
|
||||||
}
|
}
|
||||||
if (values.empty())
|
if (values.empty())
|
||||||
return;
|
return;
|
||||||
forward(after, getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, settings);
|
forward(after, getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6058,32 +5952,6 @@ static void valueFlowCondition(const ValuePtr<ConditionHandler>& handler,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimpleConditionHandler : ConditionHandler {
|
struct SimpleConditionHandler : ConditionHandler {
|
||||||
virtual Analyzer::Result forward(Token* start,
|
|
||||||
const Token* stop,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings) const override {
|
|
||||||
return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Analyzer::Result forward(Token* top,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings) const override {
|
|
||||||
return valueFlowForward(top, exprTok, values, tokenlist, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void reverse(Token* start,
|
|
||||||
const Token* endToken,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings) const override {
|
|
||||||
return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const override {
|
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const override {
|
||||||
Condition cond;
|
Condition cond;
|
||||||
ValueFlow::Value true_value;
|
ValueFlow::Value true_value;
|
||||||
|
@ -6453,11 +6321,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowForLoopSimplifyAfter(Token* fortok,
|
static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, TokenList* tokenlist)
|
||||||
nonneg int varid,
|
|
||||||
const MathLib::bigint num,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
{
|
||||||
const Token *vartok = nullptr;
|
const Token *vartok = nullptr;
|
||||||
for (const Token *tok = fortok; tok; tok = tok->next()) {
|
for (const Token *tok = fortok; tok; tok = tok->next()) {
|
||||||
|
@ -6482,7 +6346,7 @@ static void valueFlowForLoopSimplifyAfter(Token* fortok,
|
||||||
values.back().errorPath.emplace_back(fortok,"After for loop, " + var->name() + " has value " + values.back().infoString());
|
values.back().errorPath.emplace_back(fortok,"After for loop, " + var->name() + " has value " + values.back().infoString());
|
||||||
|
|
||||||
if (blockTok != endToken) {
|
if (blockTok != endToken) {
|
||||||
valueFlowForward(blockTok->next(), endToken, vartok, values, tokenlist, settings);
|
valueFlowForward(blockTok->next(), endToken, vartok, values, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6510,8 +6374,7 @@ static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabas
|
||||||
std::list<ValueFlow::Value> initValues;
|
std::list<ValueFlow::Value> initValues;
|
||||||
initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower);
|
initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower);
|
||||||
initValues.push_back(asImpossible(initValues.back()));
|
initValues.push_back(asImpossible(initValues.back()));
|
||||||
Analyzer::Result result =
|
Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, initValues, tokenlist);
|
||||||
valueFlowForward(bodyStart, bodyStart->link(), vartok, initValues, tokenlist, settings);
|
|
||||||
|
|
||||||
if (!result.action.isModified()) {
|
if (!result.action.isModified()) {
|
||||||
std::list<ValueFlow::Value> lastValues;
|
std::list<ValueFlow::Value> lastValues;
|
||||||
|
@ -6520,11 +6383,11 @@ static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabas
|
||||||
lastValues.push_back(asImpossible(lastValues.back()));
|
lastValues.push_back(asImpossible(lastValues.back()));
|
||||||
if (stepValue != 1)
|
if (stepValue != 1)
|
||||||
lastValues.pop_front();
|
lastValues.pop_front();
|
||||||
valueFlowForward(bodyStart, bodyStart->link(), vartok, lastValues, tokenlist, settings);
|
valueFlowForward(bodyStart, bodyStart->link(), vartok, lastValues, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue;
|
const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue;
|
||||||
valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, settings);
|
valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist);
|
||||||
} else {
|
} else {
|
||||||
ProgramMemory mem1, mem2, memAfter;
|
ProgramMemory mem1, mem2, memAfter;
|
||||||
if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) {
|
if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) {
|
||||||
|
@ -6547,7 +6410,7 @@ static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabas
|
||||||
continue;
|
continue;
|
||||||
if (p.first.tok->varId() == 0)
|
if (p.first.tok->varId() == 0)
|
||||||
continue;
|
continue;
|
||||||
valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist, settings);
|
valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6804,7 +6667,6 @@ static void valueFlowInjectParameter(TokenList* tokenlist,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowInjectParameter(TokenList* tokenlist,
|
static void valueFlowInjectParameter(TokenList* tokenlist,
|
||||||
const Settings* settings,
|
|
||||||
const Variable* arg,
|
const Variable* arg,
|
||||||
const Scope* functionScope,
|
const Scope* functionScope,
|
||||||
const std::list<ValueFlow::Value>& argvalues)
|
const std::list<ValueFlow::Value>& argvalues)
|
||||||
|
@ -6822,8 +6684,7 @@ static void valueFlowInjectParameter(TokenList* tokenlist,
|
||||||
functionScope->bodyEnd,
|
functionScope->bodyEnd,
|
||||||
arg->nameToken(),
|
arg->nameToken(),
|
||||||
argvalues,
|
argvalues,
|
||||||
tokenlist,
|
tokenlist);
|
||||||
settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
|
@ -7046,7 +6907,7 @@ static void valueFlowSubFunction(TokenList* tokenlist, SymbolDatabase* symboldat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowFunctionDefaultParameter(TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings)
|
static void valueFlowFunctionDefaultParameter(TokenList* tokenlist, SymbolDatabase* symboldatabase)
|
||||||
{
|
{
|
||||||
if (!tokenlist->isCPP())
|
if (!tokenlist->isCPP())
|
||||||
return;
|
return;
|
||||||
|
@ -7068,7 +6929,7 @@ static void valueFlowFunctionDefaultParameter(TokenList* tokenlist, SymbolDataba
|
||||||
argvalues.push_back(v);
|
argvalues.push_back(v);
|
||||||
}
|
}
|
||||||
if (!argvalues.empty())
|
if (!argvalues.empty())
|
||||||
valueFlowInjectParameter(tokenlist, settings, var, scope, argvalues);
|
valueFlowInjectParameter(tokenlist, var, scope, argvalues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7264,7 +7125,7 @@ static void valueFlowUninit(TokenList* tokenlist, SymbolDatabase* /*symbolDataba
|
||||||
if (partial)
|
if (partial)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
valueFlowForward(tok->next(), tok->scope()->bodyEnd, var->nameToken(), {uninitValue}, tokenlist, settings);
|
valueFlowForward(tok->next(), tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7422,48 +7283,100 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
static const Token* parseBinaryIntOp(const Token* expr,
|
||||||
const Token* endToken,
|
const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
|
||||||
const Token* exprTok,
|
MathLib::bigint& known)
|
||||||
const ValueFlow::Value& value,
|
|
||||||
TokenList* tokenlist)
|
|
||||||
{
|
{
|
||||||
ContainerExpressionAnalyzer a(exprTok, value, tokenlist);
|
if (!expr)
|
||||||
return valueFlowGenericForward(startToken, endToken, a, tokenlist->getSettings());
|
return nullptr;
|
||||||
}
|
if (!expr->astOperand1() || !expr->astOperand2())
|
||||||
|
return nullptr;
|
||||||
static Analyzer::Result valueFlowContainerForwardRecursive(Token* top,
|
if (expr->astOperand1()->exprId() == 0 && expr->astOperand2()->exprId() == 0)
|
||||||
const Token* exprTok,
|
return nullptr;
|
||||||
const ValueFlow::Value& value,
|
std::vector<MathLib::bigint> x1 = eval(expr->astOperand1());
|
||||||
TokenList* tokenlist)
|
std::vector<MathLib::bigint> x2 = eval(expr->astOperand2());
|
||||||
{
|
if (expr->astOperand1()->exprId() == 0 && x1.empty())
|
||||||
ContainerExpressionAnalyzer a(exprTok, value, tokenlist);
|
return nullptr;
|
||||||
return valueFlowGenericForward(top, a, tokenlist->getSettings());
|
if (expr->astOperand2()->exprId() == 0 && x2.empty())
|
||||||
}
|
return nullptr;
|
||||||
|
const Token* varTok = nullptr;
|
||||||
static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
if (!x1.empty() && x2.empty()) {
|
||||||
const Token* exprTok,
|
varTok = expr->astOperand2();
|
||||||
const ValueFlow::Value& value,
|
known = x1.front();
|
||||||
TokenList* tokenlist)
|
} else if (x1.empty() && !x2.empty()) {
|
||||||
{
|
varTok = expr->astOperand1();
|
||||||
const Token* endToken = nullptr;
|
known = x2.front();
|
||||||
const Function* f = Scope::nestedInFunction(startToken->scope());
|
|
||||||
if (f && f->functionScope)
|
|
||||||
endToken = f->functionScope->bodyEnd;
|
|
||||||
return valueFlowContainerForward(startToken, endToken, exprTok, value, tokenlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void valueFlowContainerReverse(Token* tok,
|
|
||||||
const Token* const endToken,
|
|
||||||
const Token* const varToken,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings)
|
|
||||||
{
|
|
||||||
for (const ValueFlow::Value& value : values) {
|
|
||||||
ContainerExpressionAnalyzer a(varToken, value, tokenlist);
|
|
||||||
valueFlowGenericReverse(tok, endToken, a, settings);
|
|
||||||
}
|
}
|
||||||
|
return varTok;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Token* 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;
|
||||||
|
if (value.isSymbolicValue() && !Token::Match(expr, "+|-"))
|
||||||
|
return expr;
|
||||||
|
MathLib::bigint intval;
|
||||||
|
const Token* binaryTok = parseBinaryIntOp(expr, eval, intval);
|
||||||
|
bool rhs = astIsRHS(binaryTok);
|
||||||
|
// If its on the rhs, then -1 multiplication is needed, which is not possible with simple delta analysis used currently for symbolic values
|
||||||
|
if (value.isSymbolicValue() && rhs && Token::simpleMatch(expr, "-"))
|
||||||
|
return expr;
|
||||||
|
if (binaryTok && expr->str().size() == 1) {
|
||||||
|
switch (expr->str()[0]) {
|
||||||
|
case '+': {
|
||||||
|
value.intvalue -= intval;
|
||||||
|
return solveExprValue(binaryTok, eval, value);
|
||||||
|
}
|
||||||
|
case '-': {
|
||||||
|
if (rhs)
|
||||||
|
value.intvalue = intval - value.intvalue;
|
||||||
|
else
|
||||||
|
value.intvalue += intval;
|
||||||
|
return solveExprValue(binaryTok, eval, value);
|
||||||
|
}
|
||||||
|
case '*': {
|
||||||
|
if (intval == 0)
|
||||||
|
break;
|
||||||
|
value.intvalue /= intval;
|
||||||
|
return solveExprValue(binaryTok, eval, value);
|
||||||
|
}
|
||||||
|
case '^': {
|
||||||
|
value.intvalue ^= intval;
|
||||||
|
return solveExprValue(binaryTok, eval, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Token* solveExprValue(const Token* expr, ValueFlow::Value& value)
|
||||||
|
{
|
||||||
|
return solveExprValue(
|
||||||
|
expr,
|
||||||
|
[](const Token* tok) -> std::vector<MathLib::bigint> {
|
||||||
|
if (tok->hasKnownIntValue())
|
||||||
|
return {tok->values().front().intvalue};
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList* tokenlist)
|
||||||
|
{
|
||||||
|
if (value.isContainerSizeValue())
|
||||||
|
return ContainerExpressionAnalyzer(exprTok, value, tokenlist);
|
||||||
|
const Token* expr = solveExprValue(exprTok, value);
|
||||||
|
return ExpressionAnalyzer(expr, value, tokenlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist)
|
||||||
|
{
|
||||||
|
if (value.isContainerSizeValue())
|
||||||
|
return ContainerExpressionAnalyzer(exprTok, value, tokenlist);
|
||||||
|
return ExpressionAnalyzer(exprTok, value, tokenlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isContainerSizeChanged(const Token* tok, const Settings* settings, int depth)
|
bool isContainerSizeChanged(const Token* tok, const Settings* settings, int depth)
|
||||||
|
@ -7879,7 +7792,7 @@ static void valueFlowContainerSize(TokenList* tokenlist,
|
||||||
if (constSize)
|
if (constSize)
|
||||||
valueFlowForwardConst(var->nameToken()->next(), var->scope()->bodyEnd, var, values, settings);
|
valueFlowForwardConst(var->nameToken()->next(), var->scope()->bodyEnd, var, values, settings);
|
||||||
else
|
else
|
||||||
valueFlowContainerForward(var->nameToken()->next(), var->nameToken(), value, tokenlist);
|
valueFlowForward(var->nameToken()->next(), var->nameToken(), value, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7894,7 +7807,7 @@ static void valueFlowContainerSize(TokenList* tokenlist,
|
||||||
ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2)));
|
ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2)));
|
||||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
valueFlowContainerForward(containerTok->next(), containerTok, value, tokenlist);
|
valueFlowForward(containerTok->next(), containerTok, value, tokenlist);
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok, "%name%|;|{|}|> %var% = {") && Token::simpleMatch(tok->linkAt(3), "} ;")) {
|
} else if (Token::Match(tok, "%name%|;|{|}|> %var% = {") && Token::simpleMatch(tok->linkAt(3), "} ;")) {
|
||||||
const Token* containerTok = tok->next();
|
const Token* containerTok = tok->next();
|
||||||
|
@ -7904,7 +7817,7 @@ static void valueFlowContainerSize(TokenList* tokenlist,
|
||||||
std::vector<ValueFlow::Value> values =
|
std::vector<ValueFlow::Value> values =
|
||||||
getInitListSize(tok->tokAt(3), containerTok->valueType(), settings);
|
getInitListSize(tok->tokAt(3), containerTok->valueType(), settings);
|
||||||
for (const ValueFlow::Value& value : values)
|
for (const ValueFlow::Value& value : values)
|
||||||
valueFlowContainerForward(containerTok->next(), containerTok, value, tokenlist);
|
valueFlowForward(containerTok->next(), containerTok, value, tokenlist);
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok, ". %name% (") && tok->astOperand1() && tok->astOperand1()->valueType() &&
|
} else if (Token::Match(tok, ". %name% (") && tok->astOperand1() && tok->astOperand1()->valueType() &&
|
||||||
tok->astOperand1()->valueType()->container) {
|
tok->astOperand1()->valueType()->container) {
|
||||||
|
@ -7916,13 +7829,13 @@ static void valueFlowContainerSize(TokenList* tokenlist,
|
||||||
ValueFlow::Value value(0);
|
ValueFlow::Value value(0);
|
||||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
valueFlowContainerForward(tok->next(), containerTok, value, tokenlist);
|
valueFlowForward(tok->next(), containerTok, value, tokenlist);
|
||||||
} else if (action == Library::Container::Action::RESIZE && tok->tokAt(2)->astOperand2() &&
|
} else if (action == Library::Container::Action::RESIZE && tok->tokAt(2)->astOperand2() &&
|
||||||
tok->tokAt(2)->astOperand2()->hasKnownIntValue()) {
|
tok->tokAt(2)->astOperand2()->hasKnownIntValue()) {
|
||||||
ValueFlow::Value value(tok->tokAt(2)->astOperand2()->values().front());
|
ValueFlow::Value value(tok->tokAt(2)->astOperand2()->values().front());
|
||||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
valueFlowContainerForward(tok->next(), containerTok, value, tokenlist);
|
valueFlowForward(tok->next(), containerTok, value, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7930,38 +7843,6 @@ static void valueFlowContainerSize(TokenList* tokenlist,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContainerConditionHandler : ConditionHandler {
|
struct ContainerConditionHandler : ConditionHandler {
|
||||||
virtual Analyzer::Result forward(Token* start,
|
|
||||||
const Token* stop,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings*) const override {
|
|
||||||
Analyzer::Result result{};
|
|
||||||
for (const ValueFlow::Value& value : values)
|
|
||||||
result.update(valueFlowContainerForward(start->next(), stop, exprTok, value, tokenlist));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Analyzer::Result forward(Token* top,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings*) const override {
|
|
||||||
Analyzer::Result result{};
|
|
||||||
for (const ValueFlow::Value& value : values)
|
|
||||||
result.update(valueFlowContainerForwardRecursive(top, exprTok, value, tokenlist));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void reverse(Token* start,
|
|
||||||
const Token* endTok,
|
|
||||||
const Token* exprTok,
|
|
||||||
const std::list<ValueFlow::Value>& values,
|
|
||||||
TokenList* tokenlist,
|
|
||||||
const Settings* settings) const override {
|
|
||||||
return valueFlowContainerReverse(start, endTok, exprTok, values, tokenlist, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const override
|
virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const override
|
||||||
{
|
{
|
||||||
Condition cond;
|
Condition cond;
|
||||||
|
@ -8127,7 +8008,7 @@ static void valueFlowDynamicBufferSize(TokenList* tokenlist, SymbolDatabase* sym
|
||||||
value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
const std::list<ValueFlow::Value> values{value};
|
const std::list<ValueFlow::Value> values{value};
|
||||||
valueFlowForward(const_cast<Token*>(rhs), functionScope->bodyEnd, tok->next(), values, tokenlist, settings);
|
valueFlowForward(const_cast<Token*>(rhs), functionScope->bodyEnd, tok->next(), values, tokenlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8228,8 +8109,7 @@ static void valueFlowSafeFunctions(TokenList* tokenlist, SymbolDatabase* symbold
|
||||||
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000");
|
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000");
|
||||||
argValues.back().safe = true;
|
argValues.back().safe = true;
|
||||||
for (const ValueFlow::Value &value : argValues)
|
for (const ValueFlow::Value &value : argValues)
|
||||||
valueFlowContainerForward(
|
valueFlowForward(const_cast<Token*>(functionScope->bodyStart), arg.nameToken(), value, tokenlist);
|
||||||
const_cast<Token*>(functionScope->bodyStart), arg.nameToken(), value, tokenlist);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8267,8 +8147,7 @@ static void valueFlowSafeFunctions(TokenList* tokenlist, SymbolDatabase* symbold
|
||||||
functionScope->bodyEnd,
|
functionScope->bodyEnd,
|
||||||
arg.nameToken(),
|
arg.nameToken(),
|
||||||
argValues,
|
argValues,
|
||||||
tokenlist,
|
tokenlist);
|
||||||
settings);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8290,8 +8169,7 @@ static void valueFlowSafeFunctions(TokenList* tokenlist, SymbolDatabase* symbold
|
||||||
functionScope->bodyEnd,
|
functionScope->bodyEnd,
|
||||||
arg.nameToken(),
|
arg.nameToken(),
|
||||||
argValues,
|
argValues,
|
||||||
tokenlist,
|
tokenlist);
|
||||||
settings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8519,7 +8397,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
||||||
valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowFunctionReturn(tokenlist, errorLogger);
|
valueFlowFunctionReturn(tokenlist, errorLogger);
|
||||||
valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, settings);
|
valueFlowFunctionDefaultParameter(tokenlist, symboldatabase);
|
||||||
valueFlowUninit(tokenlist, symboldatabase, settings);
|
valueFlowUninit(tokenlist, symboldatabase, settings);
|
||||||
if (tokenlist->isCPP()) {
|
if (tokenlist->isCPP()) {
|
||||||
valueFlowAfterMove(tokenlist, symboldatabase, settings);
|
valueFlowAfterMove(tokenlist, symboldatabase, settings);
|
||||||
|
|
Loading…
Reference in New Issue