Refactor: Use valueFlowForward to forward values in condition expression (#3369)

This commit is contained in:
Paul Fultz II 2021-08-01 03:13:14 -05:00 committed by GitHub
parent 7d9fdf582b
commit 2f6a6e4b45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 64 additions and 28 deletions

View File

@ -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,