Refactor: Use valueFlowForward to forward values in condition expression (#3369)
This commit is contained in:
parent
7d9fdf582b
commit
2f6a6e4b45
|
@ -2284,7 +2284,7 @@ struct ValueFlowAnalyzer : Analyzer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ValuePtr<Analyzer> makeAnalyzer(Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist);
|
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, const 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;
|
||||||
|
@ -2571,11 +2571,11 @@ static const Token* solveExprValues(const Token* expr, std::list<ValueFlow::Valu
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValuePtr<Analyzer> makeAnalyzer(Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist)
|
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist)
|
||||||
{
|
{
|
||||||
std::list<ValueFlow::Value> values = {value};
|
std::list<ValueFlow::Value> values = {value};
|
||||||
const Token* expr = solveExprValues(exprTok, values);
|
const Token* expr = solveExprValues(exprTok, values);
|
||||||
return ExpressionAnalyzer(expr, value, tokenlist);
|
return ExpressionAnalyzer(expr, values.front(), tokenlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Analyzer::Result valueFlowForward(Token* startToken,
|
static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
|
@ -2589,6 +2589,19 @@ static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
return valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings);
|
return valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
static void valueFlowReverse(Token* tok,
|
||||||
const Token* const endToken,
|
const Token* const endToken,
|
||||||
const Token* const varToken,
|
const Token* const varToken,
|
||||||
|
@ -4359,6 +4372,12 @@ struct ConditionHandler {
|
||||||
TokenList* tokenlist,
|
TokenList* tokenlist,
|
||||||
const Settings* settings) const = 0;
|
const Settings* settings) const = 0;
|
||||||
|
|
||||||
|
virtual Analyzer::Result forward(Token* top,
|
||||||
|
const Token* exprTok,
|
||||||
|
const std::list<ValueFlow::Value>& values,
|
||||||
|
TokenList* tokenlist,
|
||||||
|
const Settings* settings) const = 0;
|
||||||
|
|
||||||
virtual void reverse(Token* start,
|
virtual void reverse(Token* start,
|
||||||
const Token* endToken,
|
const Token* endToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
|
@ -4571,7 +4590,8 @@ struct ConditionHandler {
|
||||||
|
|
||||||
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
||||||
Token* parent = tok->astParent();
|
Token* parent = tok->astParent();
|
||||||
if (astIsRHS(tok) && parent->astParent() && parent->str() == parent->astParent()->str())
|
if (astIsRHS(tok) && astIsLHS(parent) && parent->astParent() &&
|
||||||
|
parent->str() == parent->astParent()->str())
|
||||||
parent = parent->astParent();
|
parent = parent->astParent();
|
||||||
else if (!astIsLHS(tok)) {
|
else if (!astIsLHS(tok)) {
|
||||||
parent = nullptr;
|
parent = nullptr;
|
||||||
|
@ -4583,33 +4603,19 @@ struct ConditionHandler {
|
||||||
values = thenValues;
|
values = thenValues;
|
||||||
else if (op == "||")
|
else if (op == "||")
|
||||||
values = elseValues;
|
values = elseValues;
|
||||||
if (Token::Match(tok, "==|!="))
|
if (Token::Match(tok, "==|!=") || (tok == cond.vartok && astIsBool(tok)))
|
||||||
changePossibleToKnown(values);
|
changePossibleToKnown(values);
|
||||||
if (!values.empty()) {
|
if (astIsFloat(cond.vartok, false) ||
|
||||||
bool assign = false;
|
(!cond.vartok->valueType() &&
|
||||||
visitAstNodes(parent->astOperand2(), [&](Token* tok2) {
|
std::all_of(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
||||||
if (tok2 == tok)
|
return v.isIntValue() || v.isFloatValue();
|
||||||
return ChildrenToVisit::done;
|
})))
|
||||||
if (isSameExpression(
|
values.remove_if([&](const ValueFlow::Value& v) { return v.isImpossible(); });
|
||||||
tokenlist->isCPP(), false, cond.vartok, tok2, settings->library, true, false))
|
Analyzer::Result r = forward(parent->astOperand2(), cond.vartok, values, tokenlist, settings);
|
||||||
setTokenValue(tok2, values.front(), settings);
|
if (r.terminate != Analyzer::Terminate::None)
|
||||||
else if (Token::Match(tok2, "++|--|=") && isSameExpression(tokenlist->isCPP(),
|
|
||||||
false,
|
|
||||||
cond.vartok,
|
|
||||||
tok2->astOperand1(),
|
|
||||||
settings->library,
|
|
||||||
true,
|
|
||||||
false)) {
|
|
||||||
assign = true;
|
|
||||||
return ChildrenToVisit::done;
|
|
||||||
}
|
|
||||||
return ChildrenToVisit::op1_and_op2;
|
|
||||||
});
|
|
||||||
if (assign)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const Token* tok2 = tok;
|
const Token* tok2 = tok;
|
||||||
|
@ -4797,6 +4803,15 @@ struct SimpleConditionHandler : ConditionHandler {
|
||||||
return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, settings);
|
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,
|
virtual void reverse(Token* start,
|
||||||
const Token* endToken,
|
const Token* endToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
|
@ -6156,6 +6171,15 @@ static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
||||||
return valueFlowGenericForward(startToken, endToken, a, tokenlist->getSettings());
|
return valueFlowGenericForward(startToken, endToken, a, tokenlist->getSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Analyzer::Result valueFlowContainerForwardRecursive(Token* top,
|
||||||
|
const Token* exprTok,
|
||||||
|
const ValueFlow::Value& value,
|
||||||
|
TokenList* tokenlist)
|
||||||
|
{
|
||||||
|
ContainerExpressionAnalyzer a(exprTok, value, tokenlist);
|
||||||
|
return valueFlowGenericForward(top, a, tokenlist->getSettings());
|
||||||
|
}
|
||||||
|
|
||||||
static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const ValueFlow::Value& value,
|
const ValueFlow::Value& value,
|
||||||
|
@ -6539,6 +6563,18 @@ struct ContainerConditionHandler : ConditionHandler {
|
||||||
return result;
|
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,
|
virtual void reverse(Token* start,
|
||||||
const Token* endTok,
|
const Token* endTok,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
|
|
Loading…
Reference in New Issue