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 {
|
||||
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;
|
||||
}
|
||||
|
||||
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};
|
||||
const Token* expr = solveExprValues(exprTok, values);
|
||||
return ExpressionAnalyzer(expr, value, tokenlist);
|
||||
return ExpressionAnalyzer(expr, values.front(), tokenlist);
|
||||
}
|
||||
|
||||
static Analyzer::Result valueFlowForward(Token* startToken,
|
||||
|
@ -2589,6 +2589,19 @@ static Analyzer::Result valueFlowForward(Token* startToken,
|
|||
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,
|
||||
const Token* const endToken,
|
||||
const Token* const varToken,
|
||||
|
@ -4359,6 +4372,12 @@ struct ConditionHandler {
|
|||
TokenList* tokenlist,
|
||||
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,
|
||||
const Token* endToken,
|
||||
const Token* exprTok,
|
||||
|
@ -4571,7 +4590,8 @@ struct ConditionHandler {
|
|||
|
||||
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
||||
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();
|
||||
else if (!astIsLHS(tok)) {
|
||||
parent = nullptr;
|
||||
|
@ -4583,31 +4603,17 @@ struct ConditionHandler {
|
|||
values = thenValues;
|
||||
else if (op == "||")
|
||||
values = elseValues;
|
||||
if (Token::Match(tok, "==|!="))
|
||||
if (Token::Match(tok, "==|!=") || (tok == cond.vartok && astIsBool(tok)))
|
||||
changePossibleToKnown(values);
|
||||
if (!values.empty()) {
|
||||
bool assign = false;
|
||||
visitAstNodes(parent->astOperand2(), [&](Token* tok2) {
|
||||
if (tok2 == tok)
|
||||
return ChildrenToVisit::done;
|
||||
if (isSameExpression(
|
||||
tokenlist->isCPP(), false, cond.vartok, tok2, settings->library, true, false))
|
||||
setTokenValue(tok2, values.front(), settings);
|
||||
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;
|
||||
}
|
||||
if (astIsFloat(cond.vartok, false) ||
|
||||
(!cond.vartok->valueType() &&
|
||||
std::all_of(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
||||
return v.isIntValue() || v.isFloatValue();
|
||||
})))
|
||||
values.remove_if([&](const ValueFlow::Value& v) { return v.isImpossible(); });
|
||||
Analyzer::Result r = forward(parent->astOperand2(), cond.vartok, values, tokenlist, settings);
|
||||
if (r.terminate != Analyzer::Terminate::None)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4797,6 +4803,15 @@ struct SimpleConditionHandler : ConditionHandler {
|
|||
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,
|
||||
|
@ -6156,6 +6171,15 @@ static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
|||
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,
|
||||
const Token* exprTok,
|
||||
const ValueFlow::Value& value,
|
||||
|
@ -6539,6 +6563,18 @@ struct ContainerConditionHandler : ConditionHandler {
|
|||
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,
|
||||
|
|
Loading…
Reference in New Issue