@@ -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
@@ -3756,7 +3725,19 @@ static const Token* findIncompleteVar(const Token* start, const Token* end)
37563725 return nullptr ;
37573726}
37583727
3759- static void valueFlowTerminatingCondition (TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
3728+ ValueFlow::Value makeConditionValue (long long val, const Token* condTok, bool assume)
3729+ {
3730+ ValueFlow::Value v (val);
3731+ v.setKnown ();
3732+ v.condition = condTok;
3733+ if (assume)
3734+ v.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is true" );
3735+ else
3736+ v.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is false" );
3737+ return v;
3738+ }
3739+ //
3740+ static void valueFlowConditionExpressions (TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
37603741{
37613742 for (const Scope * scope : symboldatabase->functionScopes ) {
37623743 if (const Token* incompleteTok = findIncompleteVar (scope->bodyStart , scope->bodyEnd )) {
@@ -3773,28 +3754,58 @@ static void valueFlowTerminatingCondition(TokenList *tokenlist, SymbolDatabase*
37733754 // Skip known values
37743755 if (tok->next ()->hasKnownValue ())
37753756 continue ;
3776- const Token * parenTok = tok->next ();
3757+ Token * parenTok = tok->next ();
37773758 if (!Token::simpleMatch (parenTok->link (), " ) {" ))
37783759 continue ;
3779- const Token * blockTok = parenTok->link ()->tokAt (1 );
3760+ Token * blockTok = parenTok->link ()->tokAt (1 );
3761+ const Token* condTok = parenTok->astOperand2 ();
3762+
3763+ Token* startTok = blockTok;
3764+ // Inner condition
3765+ {
3766+ std::vector<const Token*> conds = {condTok};
3767+ if (Token::simpleMatch (condTok, " &&" )) {
3768+ std::vector<const Token*> args = astFlatten (condTok, " &&" );
3769+ conds.insert (conds.end (), args.begin (), args.end ());
3770+ }
3771+ for (const Token* condTok2:conds) {
3772+ ExpressionAnalyzer a1 (condTok2, makeConditionValue (1 , condTok2, true ), tokenlist);
3773+ valueFlowGenericForward (startTok, startTok->link (), a1, settings);
3774+
3775+ OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (0 , condTok2, true ), tokenlist);
3776+ valueFlowGenericForward (startTok, startTok->link (), a2, settings);
3777+ }
3778+ }
3779+
3780+ std::vector<const Token*> conds = {condTok};
3781+ if (Token::simpleMatch (condTok, " ||" )) {
3782+ std::vector<const Token*> args = astFlatten (condTok, " ||" );
3783+ conds.insert (conds.end (), args.begin (), args.end ());
3784+ }
3785+
3786+ // Check else block
3787+ if (Token::simpleMatch (startTok->link (), " } else {" )) {
3788+ startTok = startTok->link ()->tokAt (2 );
3789+ for (const Token* condTok2:conds) {
3790+ ExpressionAnalyzer a1 (condTok2, makeConditionValue (0 , condTok2, false ), tokenlist);
3791+ valueFlowGenericForward (startTok, startTok->link (), a1, settings);
3792+
3793+ OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (1 , condTok2, false ), tokenlist);
3794+ valueFlowGenericForward (startTok, startTok->link (), a2, settings);
3795+ }
3796+ }
3797+
37803798 // Check if the block terminates early
3781- if (!isEscapeScope (blockTok, tokenlist))
3782- continue ;
3799+ if (isEscapeScope (blockTok, tokenlist)) {
3800+ for (const Token* condTok2:conds) {
3801+ ExpressionAnalyzer a1 (condTok2, makeConditionValue (0 , condTok2, false ), tokenlist);
3802+ valueFlowGenericForward (startTok->link ()->next (), scope->bodyEnd , a1, settings);
37833803
3784- const Token* condTok = parenTok->astOperand2 ();
3785- ValueFlow::Value v1 (0 );
3786- v1.setKnown ();
3787- v1.condition = condTok;
3788- v1.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is true" );
3789- ExpressionAnalyzer a1 (condTok, v1, tokenlist);
3790- valueFlowGenericForward (blockTok->link ()->next (), scope->bodyEnd , a1, settings);
3804+ OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (1 , condTok2, false ), tokenlist);
3805+ valueFlowGenericForward (startTok->link ()->next (), scope->bodyEnd , a2, settings);
3806+ }
3807+ }
37913808
3792- ValueFlow::Value v2 (1 );
3793- v2.setKnown ();
3794- v2.condition = condTok;
3795- v2.errorPath .emplace_back (condTok, " Assuming condition '" + condTok->expressionString () + " ' is false" );
3796- OppositeExpressionAnalyzer a2 (true , condTok, v2, tokenlist);
3797- valueFlowGenericForward (blockTok->link ()->next (), scope->bodyEnd , a2, settings);
37983809 }
37993810 }
38003811}
@@ -6624,6 +6635,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
66246635 valueFlowLifetime (tokenlist, symboldatabase, errorLogger, settings);
66256636 valueFlowBitAnd (tokenlist);
66266637 valueFlowSameExpressions (tokenlist);
6638+ valueFlowConditionExpressions (tokenlist, symboldatabase, errorLogger, settings);
66276639 valueFlowFwdAnalysis (tokenlist, settings);
66286640
66296641 std::size_t values = 0 ;
@@ -6633,8 +6645,6 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
66336645 valueFlowPointerAliasDeref (tokenlist);
66346646 valueFlowArrayBool (tokenlist);
66356647 valueFlowRightShift (tokenlist, settings);
6636- valueFlowOppositeCondition (symboldatabase, settings);
6637- valueFlowTerminatingCondition (tokenlist, symboldatabase, errorLogger, settings);
66386648 valueFlowAfterMove (tokenlist, symboldatabase, errorLogger, settings);
66396649 valueFlowCondition (SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
66406650 valueFlowInferCondition (tokenlist, settings);
0 commit comments