| 4623 | } |
| 4624 | |
| 4625 | void afterCondition(TokenList& tokenlist, |
| 4626 | const SymbolDatabase& symboldatabase, |
| 4627 | ErrorLogger& errorLogger, |
| 4628 | const Settings& settings, |
| 4629 | const std::set<const Scope*>& skippedFunctions) const { |
| 4630 | traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) { |
| 4631 | const MathLib::bigint path = cond.getPath(); |
| 4632 | const bool allowKnown = path == 0; |
| 4633 | |
| 4634 | std::list<ValueFlow::Value> thenValues; |
| 4635 | std::list<ValueFlow::Value> elseValues; |
| 4636 | |
| 4637 | Token* ctx = cond.getContextAndValues(condTok, thenValues, elseValues); |
| 4638 | |
| 4639 | if (Token::Match(ctx->astParent(), "%oror%|&&")) { |
| 4640 | Token* parent = ctx->astParent(); |
| 4641 | if (astIsRHS(ctx) && astIsLHS(parent) && parent->astParent() && |
| 4642 | parent->str() == parent->astParent()->str()) |
| 4643 | parent = parent->astParent(); |
| 4644 | else if (!astIsLHS(ctx)) { |
| 4645 | parent = nullptr; |
| 4646 | } |
| 4647 | if (parent) { |
| 4648 | std::vector<Token*> nextExprs = {parent->astOperand2()}; |
| 4649 | if (astIsLHS(parent) && parent->astParent() && parent->astParent()->str() == parent->str()) { |
| 4650 | nextExprs.push_back(parent->astParent()->astOperand2()); |
| 4651 | } |
| 4652 | std::list<ValueFlow::Value> andValues; |
| 4653 | std::list<ValueFlow::Value> orValues; |
| 4654 | cond.getContextAndValues(condTok, andValues, orValues, true); |
| 4655 | |
| 4656 | const std::string& op(parent->str()); |
| 4657 | std::list<ValueFlow::Value> values; |
| 4658 | if (op == "&&") |
| 4659 | values = std::move(andValues); |
| 4660 | else if (op == "||") |
| 4661 | values = std::move(orValues); |
| 4662 | if (allowKnown && (Token::Match(condTok, "==|!=") || cond.isBool())) |
| 4663 | changePossibleToKnown(values); |
| 4664 | if (astIsFloat(cond.vartok, false) || |
| 4665 | (!cond.vartok->valueType() && |
| 4666 | std::all_of(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) { |
| 4667 | return v.isIntValue() || v.isFloatValue(); |
| 4668 | }))) |
| 4669 | values.remove_if([&](const ValueFlow::Value& v) { |
| 4670 | return v.isImpossible(); |
| 4671 | }); |
| 4672 | for (Token* start:nextExprs) { |
| 4673 | Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, errorLogger, settings); |
| 4674 | if (r.terminate != Analyzer::Terminate::None || r.action.isModified()) |
| 4675 | return; |
| 4676 | } |
| 4677 | } |
| 4678 | } |
| 4679 | |
| 4680 | { |
| 4681 | const Token* tok2 = condTok; |
| 4682 | std::string op; |
no test coverage detected