@@ -1427,37 +1427,6 @@ static void valueFlowRightShift(TokenList *tokenList, const Settings* settings)
14271427 }
14281428}
14291429
1430- static void valueFlowOppositeCondition (SymbolDatabase *symboldatabase, const Settings *settings)
1431- {
1432- for (const Scope &scope : symboldatabase->scopeList ) {
1433- if (scope.type != Scope::eIf)
1434- continue ;
1435- Token *tok = const_cast <Token *>(scope.classDef );
1436- if (!Token::simpleMatch (tok, " if (" ))
1437- continue ;
1438- const Token *cond1 = tok->next ()->astOperand2 ();
1439- if (!cond1 || !cond1->isComparisonOp ())
1440- continue ;
1441- const bool cpp = symboldatabase->isCPP ();
1442- Token *tok2 = tok->linkAt (1 );
1443- while (Token::simpleMatch (tok2, " ) {" )) {
1444- tok2 = tok2->linkAt (1 );
1445- if (!Token::simpleMatch (tok2, " } else { if (" ))
1446- break ;
1447- Token *ifOpenBraceTok = tok2->tokAt (4 );
1448- Token *cond2 = ifOpenBraceTok->astOperand2 ();
1449- if (!cond2 || !cond2->isComparisonOp ())
1450- continue ;
1451- if (isOppositeCond (true , cpp, cond1, cond2, settings->library , true , true )) {
1452- ValueFlow::Value value (1 );
1453- value.setKnown ();
1454- setTokenValue (cond2, value, settings);
1455- }
1456- tok2 = ifOpenBraceTok->link ();
1457- }
1458- }
1459- }
1460-
14611430static void valueFlowEnumValue (SymbolDatabase * symboldatabase, const Settings * settings)
14621431{
14631432
@@ -3755,7 +3724,19 @@ static const Token* findIncompleteVar(const Token* start, const Token* end)
37553724 return nullptr ;
37563725}
37573726
3758- static void valueFlowTerminatingCondition (TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
3727+ static ValueFlow::Value makeConditionValue (long long val, const Token* condTok, bool assume)
3728+ {
3729+ ValueFlow::Value v (val);
3730+ v.setKnown ();
3731+ v.condition = condTok;
3732+ if (assume)
3733+ v.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is true" );
3734+ else
3735+ v.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is false" );
3736+ return v;
3737+ }
3738+ //
3739+ static void valueFlowConditionExpressions (TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
37593740{
37603741 for (const Scope * scope : symboldatabase->functionScopes ) {
37613742 if (const Token* incompleteTok = findIncompleteVar (scope->bodyStart , scope->bodyEnd )) {
@@ -3772,28 +3753,60 @@ static void valueFlowTerminatingCondition(TokenList *tokenlist, SymbolDatabase*
37723753 // Skip known values
37733754 if (tok->next ()->hasKnownValue ())
37743755 continue ;
3775- const Token * parenTok = tok->next ();
3756+ Token * parenTok = tok->next ();
37763757 if (!Token::simpleMatch (parenTok->link (), " ) {" ))
37773758 continue ;
3778- const Token * blockTok = parenTok->link ()->tokAt (1 );
3779- // Check if the block terminates early
3780- if (! isEscapeScope (blockTok, tokenlist ))
3759+ Token * blockTok = parenTok->link ()->tokAt (1 );
3760+ const Token* condTok = parenTok-> astOperand2 ();
3761+ if (condTok-> hasKnownIntValue ( ))
37813762 continue ;
37823763
3783- const Token* condTok = parenTok->astOperand2 ();
3784- ValueFlow::Value v1 (0 );
3785- v1.setKnown ();
3786- v1.condition = condTok;
3787- v1.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is true" );
3788- ExpressionAnalyzer a1 (condTok, v1, tokenlist);
3789- valueFlowGenericForward (blockTok->link ()->next (), scope->bodyEnd , a1, settings);
3764+ Token* startTok = blockTok;
3765+ // Inner condition
3766+ {
3767+ std::vector<const Token*> conds = {condTok};
3768+ if (Token::simpleMatch (condTok, " &&" )) {
3769+ std::vector<const Token*> args = astFlatten (condTok, " &&" );
3770+ conds.insert (conds.end (), args.begin (), args.end ());
3771+ }
3772+ for (const Token* condTok2:conds) {
3773+ ExpressionAnalyzer a1 (condTok2, makeConditionValue (1 , condTok2, true ), tokenlist);
3774+ valueFlowGenericForward (startTok, startTok->link (), a1, settings);
3775+
3776+ OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (0 , condTok2, true ), tokenlist);
3777+ valueFlowGenericForward (startTok, startTok->link (), a2, settings);
3778+ }
3779+ }
3780+
3781+ std::vector<const Token*> conds = {condTok};
3782+ if (Token::simpleMatch (condTok, " ||" )) {
3783+ std::vector<const Token*> args = astFlatten (condTok, " ||" );
3784+ conds.insert (conds.end (), args.begin (), args.end ());
3785+ }
3786+
3787+ // Check else block
3788+ if (Token::simpleMatch (startTok->link (), " } else {" )) {
3789+ startTok = startTok->link ()->tokAt (2 );
3790+ for (const Token* condTok2:conds) {
3791+ ExpressionAnalyzer a1 (condTok2, makeConditionValue (0 , condTok2, false ), tokenlist);
3792+ valueFlowGenericForward (startTok, startTok->link (), a1, settings);
3793+
3794+ OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (1 , condTok2, false ), tokenlist);
3795+ valueFlowGenericForward (startTok, startTok->link (), a2, settings);
3796+ }
3797+ }
3798+
3799+ // Check if the block terminates early
3800+ if (isEscapeScope (blockTok, tokenlist)) {
3801+ for (const Token* condTok2:conds) {
3802+ ExpressionAnalyzer a1 (condTok2, makeConditionValue (0 , condTok2, false ), tokenlist);
3803+ valueFlowGenericForward (startTok->link ()->next (), scope->bodyEnd , a1, settings);
3804+
3805+ OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (1 , condTok2, false ), tokenlist);
3806+ valueFlowGenericForward (startTok->link ()->next (), scope->bodyEnd , a2, settings);
3807+ }
3808+ }
37903809
3791- ValueFlow::Value v2 (1 );
3792- v2.setKnown ();
3793- v2.condition = condTok;
3794- v2.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is false" );
3795- OppositeExpressionAnalyzer a2 (true , condTok, v2, tokenlist);
3796- valueFlowGenericForward (blockTok->link ()->next (), scope->bodyEnd , a2, settings);
37973810 }
37983811 }
37993812}
@@ -6623,6 +6636,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
66236636 valueFlowLifetime (tokenlist, symboldatabase, errorLogger, settings);
66246637 valueFlowBitAnd (tokenlist);
66256638 valueFlowSameExpressions (tokenlist);
6639+ valueFlowConditionExpressions (tokenlist, symboldatabase, errorLogger, settings);
66266640 valueFlowFwdAnalysis (tokenlist, settings);
66276641
66286642 std::size_t values = 0 ;
@@ -6632,8 +6646,6 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
66326646 valueFlowPointerAliasDeref (tokenlist);
66336647 valueFlowArrayBool (tokenlist);
66346648 valueFlowRightShift (tokenlist, settings);
6635- valueFlowOppositeCondition (symboldatabase, settings);
6636- valueFlowTerminatingCondition (tokenlist, symboldatabase, errorLogger, settings);
66376649 valueFlowAfterMove (tokenlist, symboldatabase, errorLogger, settings);
66386650 valueFlowCondition (SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
66396651 valueFlowInferCondition (tokenlist, settings);
0 commit comments