@@ -407,6 +407,28 @@ namespace {
407407 return p;
408408 }
409409
410+ // Update the branch that the evaluated condition takes
411+ Progress updateTakenBranch (Branch& branch, const Token* skippedBlock, const Token* condTok, int depth)
412+ {
413+ // The condition is only "known" because of an earlier assumption, so the
414+ // skipped block could still modify the value -> lower to possible
415+ if (!condTok->hasKnownIntValue () && skippedBlock && analyzeScope (skippedBlock).isModified () &&
416+ !analyzer->lowerToPossible ())
417+ return Break (Analyzer::Terminate::Bail);
418+ if (!branch.endBlock )
419+ return Progress::Continue;
420+ updateScopeState (branch.endBlock );
421+ if (updateBranch (branch, depth - 1 ) == Progress::Break)
422+ return Progress::Break;
423+ // The branch was entered because of the tracked value; if it might not
424+ // return (it ends in a call to an unknown, possibly noreturn function)
425+ // then the value might not flow past the branch.
426+ if (!condTok->hasKnownIntValue () && !branch.escape && branch.escapeUnknown &&
427+ !analyzer->lowerToInconclusive ())
428+ return Break (Analyzer::Terminate::Bail);
429+ return Progress::Continue;
430+ }
431+
410432 bool reentersLoop (Token* endBlock, const Token* condTok, const Token* stepTok) const {
411433 if (!condTok)
412434 return true ;
@@ -558,16 +580,21 @@ namespace {
558580 return updateLoop (endToken, endBlock, condTok, initTok, stepTok, true );
559581 }
560582
561- Progress updateScope ( Token* endBlock, int depth = 20 )
583+ void updateScopeState ( const Token* endBlock)
562584 {
563- if (!endBlock)
564- return Break ();
565585 assert (endBlock->link ());
566- Token* ctx = endBlock->link ()->previous ();
586+ const Token* ctx = endBlock->link ()->previous ();
567587 if (Token::simpleMatch (ctx, " )" ))
568588 ctx = ctx->link ()->previous ();
569589 if (ctx)
570590 analyzer->updateState (ctx);
591+ }
592+
593+ Progress updateScope (Token* endBlock, int depth = 20 )
594+ {
595+ if (!endBlock)
596+ return Break ();
597+ updateScopeState (endBlock);
571598 return updateRange (endBlock->link (), endBlock, depth);
572599 }
573600
@@ -738,32 +765,12 @@ namespace {
738765 const bool hasElse = Token::simpleMatch (endBlock, " } else {" );
739766 tok = hasElse ? endBlock->linkAt (2 ) : endBlock;
740767 if (thenBranch.check ) {
741- // The condition is only "known" because of an earlier assumption, so the
742- // skipped else block could still modify the value -> lower to possible
743- if (!condTok->hasKnownIntValue () && hasElse &&
744- analyzeScope (elseBranch.endBlock ).isModified () && !analyzer->lowerToPossible ())
745- return Break (Analyzer::Terminate::Bail);
746- if (updateScope (thenBranch.endBlock , depth - 1 ) == Progress::Break)
768+ if (updateTakenBranch (thenBranch, hasElse ? elseBranch.endBlock : nullptr , condTok, depth) ==
769+ Progress::Break)
747770 return Break ();
748- // The branch was entered because of the tracked value; if it might not
749- // return (it ends in a call to an unknown, possibly noreturn function)
750- // then the value might not flow past the branch.
751- if (!condTok->hasKnownIntValue () &&
752- !isEscapeScope (thenBranch.endBlock , thenBranch.escapeUnknown ) &&
753- thenBranch.escapeUnknown && !analyzer->lowerToInconclusive ())
754- return Break (Analyzer::Terminate::Bail);
755771 } else if (elseBranch.check ) {
756- // Likewise the skipped then block could still modify the value
757- if (!condTok->hasKnownIntValue () && analyzeScope (thenBranch.endBlock ).isModified () &&
758- !analyzer->lowerToPossible ())
759- return Break (Analyzer::Terminate::Bail);
760- if (elseBranch.endBlock && updateScope (elseBranch.endBlock , depth - 1 ) == Progress::Break)
772+ if (updateTakenBranch (elseBranch, thenBranch.endBlock , condTok, depth) == Progress::Break)
761773 return Break ();
762- // Same as above: an else branch that might not return
763- if (elseBranch.endBlock && !condTok->hasKnownIntValue () &&
764- !isEscapeScope (elseBranch.endBlock , elseBranch.escapeUnknown ) &&
765- elseBranch.escapeUnknown && !analyzer->lowerToInconclusive ())
766- return Break (Analyzer::Terminate::Bail);
767774 } else {
768775 const bool conditional = stopOnCondition (condTok);
769776 // The value only flows into the then-branch when the condition can split
0 commit comments