diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index b0e9aad57..c54289cee 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2284,7 +2284,7 @@ struct ValueFlowAnalyzer : Analyzer { } }; -ValuePtr makeAnalyzer(Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist); +ValuePtr makeAnalyzer(const Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist); struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { std::unordered_map varids; @@ -2571,11 +2571,11 @@ static const Token* solveExprValues(const Token* expr, std::list makeAnalyzer(Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist) +ValuePtr makeAnalyzer(const Token* exprTok, const ValueFlow::Value& value, const TokenList* tokenlist) { std::list 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& 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& 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& 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& 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,