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