@@ -90,6 +90,9 @@ struct ForwardTraversal {
9090 bool isDead () const {
9191 return action.isModified () || action.isInconclusive () || isEscape ();
9292 }
93+ bool hasGoto () const {
94+ return endBlock ? ForwardTraversal::hasGoto (endBlock) : false ;
95+ }
9396 };
9497
9598 bool stopUpdates () {
@@ -389,6 +392,35 @@ struct ForwardTraversal {
389392 return bail;
390393 }
391394
395+ Progress updateBranch (Branch& branch, int depth)
396+ {
397+ // Save and reset actions
398+ Analyzer::Action prevActions = actions;
399+ actions = Analyzer::Action::None;
400+ Progress p = updateRange (branch.endBlock ->link (), branch.endBlock , depth);
401+ branch.action |= actions;
402+ // Restore actions
403+ actions |= prevActions;
404+
405+ if (terminate == Analyzer::Terminate::Escape) {
406+ branch.escape = true ;
407+ branch.escapeUnknown = false ;
408+ } else if (terminate != Analyzer::Terminate::None) {
409+ if (terminate != Analyzer::Terminate::Escape) {
410+ bool unknown = false ;
411+ if (isEscapeScope (branch.endBlock , unknown)) {
412+ branch.escape = true ;
413+ branch.escapeUnknown = unknown;
414+ }
415+ }
416+ if (terminate != Analyzer::Terminate::Modified) {
417+ branch.action |= analyzeScope (branch.endBlock );
418+ }
419+ }
420+
421+ return p;
422+ }
423+
392424 bool reentersLoop (Token* endBlock, const Token* condTok, const Token* stepTok) {
393425 if (!condTok)
394426 return true ;
@@ -697,71 +729,45 @@ struct ForwardTraversal {
697729 if (!thenBranch.check && !elseBranch.check && analyzer->stopOnCondition (condTok) && stopUpdates ())
698730 return Break (Analyzer::Terminate::Conditional);
699731 bool hasElse = Token::simpleMatch (endBlock, " } else {" );
700- bool bail = false ;
701-
702- // Traverse then block
703- thenBranch.escape = isEscapeScope (endBlock, thenBranch.escapeUnknown );
732+ tok = hasElse ? endBlock->linkAt (2 ) : endBlock;
704733 if (thenBranch.check ) {
705- thenBranch.active = true ;
706- if (updateRange (endCond->next (), endBlock, depth - 1 ) == Progress::Break)
734+ if (updateRange (thenBranch.endBlock ->link (), thenBranch.endBlock , depth - 1 ) == Progress::Break)
707735 return Break ();
708- } else if (! elseBranch.check ) {
709- thenBranch. active = true ;
710- if ( checkBranch (thenBranch))
711- bail = true ;
712- }
713- // Traverse else block
714- if (hasElse) {
715- elseBranch. escape = isEscapeScope (endBlock-> linkAt ( 2 ), elseBranch. escapeUnknown );
716- if (elseBranch. check ) {
717- elseBranch. active = true ;
718- Progress result = updateRange (endBlock-> tokAt ( 2 ), endBlock-> linkAt ( 2 ), depth - 1 );
719- if (result == Progress::Break)
736+ } else if (elseBranch.check ) {
737+ if (elseBranch. endBlock && updateRange (elseBranch. endBlock -> link (), elseBranch. endBlock , depth - 1 ) == Progress::Break)
738+ return Break ();
739+ } else {
740+ const bool conditional = analyzer-> isConditional ();
741+ ForwardTraversal ft = fork ();
742+ ft. analyzer -> assume (condTok, true );
743+ Progress p = ft. updateBranch (thenBranch, depth - 1 );
744+
745+ analyzer-> assume (condTok, false ) ;
746+ if (hasElse) {
747+ if (updateBranch (elseBranch, depth - 1 ) == Progress::Break)
720748 return Break ();
721- } else if (!thenBranch.check ) {
722- elseBranch.active = true ;
723- if (checkBranch (elseBranch))
724- bail = true ;
725749 }
726- tok = endBlock->linkAt (2 );
727- } else {
728- tok = endBlock;
729- }
730- if (thenBranch.active )
731- actions |= thenBranch.action ;
732- if (elseBranch.active )
733- actions |= elseBranch.action ;
734- if (bail)
735- return Break (Analyzer::Terminate::Bail);
736- if (thenBranch.isDead () && elseBranch.isDead ()) {
737- if (thenBranch.isModified () && elseBranch.isModified ())
738- return Break (Analyzer::Terminate::Modified);
739- if (thenBranch.isConclusiveEscape () && elseBranch.isConclusiveEscape ())
740- return Break (Analyzer::Terminate::Escape);
741- return Break (Analyzer::Terminate::Bail);
742- }
743- // Conditional return
744- if (thenBranch.active && thenBranch.isEscape () && !hasElse) {
745- if (!thenBranch.isConclusiveEscape ()) {
750+ if (thenBranch.isDead () || elseBranch.isDead ()) {
751+ if (conditional && stopUpdates ())
752+ return Break (Analyzer::Terminate::Conditional);
753+ }
754+ if (thenBranch.isModified () || elseBranch.isModified ()) {
755+ if (!analyzer->lowerToPossible ())
756+ return Break (Analyzer::Terminate::Bail);
757+ if (!ft.analyzer ->lowerToPossible ())
758+ p = Progress::Break;
759+ }
760+ if (thenBranch.isInconclusive () || elseBranch.isInconclusive ()) {
746761 if (!analyzer->lowerToInconclusive ())
747762 return Break (Analyzer::Terminate::Bail);
748- } else if (thenBranch.check ) {
749- return Break ();
750- } else {
751- if (analyzer->isConditional () && stopUpdates ())
752- return Break (Analyzer::Terminate::Conditional);
753- analyzer->assume (condTok, false );
763+ if (!ft.analyzer ->lowerToInconclusive ())
764+ p = Progress::Break;
754765 }
755- }
756- if (thenBranch.isInconclusive () || elseBranch.isInconclusive ()) {
757- if (!analyzer->lowerToInconclusive ())
766+ if (thenBranch.hasGoto () || elseBranch.hasGoto ()) {
758767 return Break (Analyzer::Terminate::Bail);
759- } else if (thenBranch.isModified () || elseBranch.isModified ()) {
760- if (!hasElse && analyzer->isConditional () && stopUpdates ())
761- return Break (Analyzer::Terminate::Conditional);
762- if (!analyzer->lowerToPossible ())
763- return Break (Analyzer::Terminate::Bail);
764- analyzer->assume (condTok, elseBranch.isModified ());
768+ }
769+ if (p != Progress::Break)
770+ ft.updateRange (thenBranch.endBlock , end, depth - 1 );
765771 }
766772 }
767773 } else if (Token::simpleMatch (tok, " try {" )) {
0 commit comments