@@ -1427,6 +1427,37 @@ 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+
14301461static void valueFlowEnumValue (SymbolDatabase * symboldatabase, const Settings * settings)
14311462{
14321463
@@ -3725,19 +3756,7 @@ static const Token* findIncompleteVar(const Token* start, const Token* end)
37253756 return nullptr ;
37263757}
37273758
3728- static 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)
3759+ static void valueFlowTerminatingCondition (TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
37413760{
37423761 for (const Scope * scope : symboldatabase->functionScopes ) {
37433762 if (const Token* incompleteTok = findIncompleteVar (scope->bodyStart , scope->bodyEnd )) {
@@ -3754,58 +3773,28 @@ static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase*
37543773 // Skip known values
37553774 if (tok->next ()->hasKnownValue ())
37563775 continue ;
3757- Token * parenTok = tok->next ();
3776+ const Token * parenTok = tok->next ();
37583777 if (!Token::simpleMatch (parenTok->link (), " ) {" ))
37593778 continue ;
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-
3779+ const Token * blockTok = parenTok->link ()->tokAt (1 );
37983780 // Check if the block terminates early
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);
3781+ if (!isEscapeScope (blockTok, tokenlist))
3782+ continue ;
38033783
3804- OppositeExpressionAnalyzer a2 (true , condTok2, makeConditionValue (1 , condTok2, false ), tokenlist);
3805- valueFlowGenericForward (startTok->link ()->next (), scope->bodyEnd , a2, settings);
3806- }
3807- }
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);
38083791
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);
38093798 }
38103799 }
38113800}
@@ -6635,7 +6624,6 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
66356624 valueFlowLifetime (tokenlist, symboldatabase, errorLogger, settings);
66366625 valueFlowBitAnd (tokenlist);
66376626 valueFlowSameExpressions (tokenlist);
6638- valueFlowConditionExpressions (tokenlist, symboldatabase, errorLogger, settings);
66396627 valueFlowFwdAnalysis (tokenlist, settings);
66406628
66416629 std::size_t values = 0 ;
@@ -6645,6 +6633,8 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
66456633 valueFlowPointerAliasDeref (tokenlist);
66466634 valueFlowArrayBool (tokenlist);
66476635 valueFlowRightShift (tokenlist, settings);
6636+ valueFlowOppositeCondition (symboldatabase, settings);
6637+ valueFlowTerminatingCondition (tokenlist, symboldatabase, errorLogger, settings);
66486638 valueFlowAfterMove (tokenlist, symboldatabase, errorLogger, settings);
66496639 valueFlowCondition (SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
66506640 valueFlowInferCondition (tokenlist, settings);
0 commit comments