@@ -115,6 +115,7 @@ public <T> void visitCtConstructor(CtConstructor<T> constructor) {
115115 }
116116 contextHistory .saveContext (constructor , context );
117117 context .exitContext ();
118+ vcChecker .clearPathVariables ();
118119 }
119120
120121 public <R > void visitCtMethod (CtMethod <R > method ) {
@@ -130,6 +131,7 @@ public <R> void visitCtMethod(CtMethod<R> method) {
130131 }
131132 contextHistory .saveContext (method , context );
132133 context .exitContext ();
134+ vcChecker .clearPathVariables ();
133135 }
134136
135137 @ Override
@@ -411,30 +413,38 @@ public void visitCtIf(CtIf ifElement) {
411413 // VISIT THEN
412414 context .enterContext ();
413415 visitCtBlock (ifElement .getThenStatement ());
414- if (canCompleteNormally (ifElement .getThenStatement ())) {
416+ boolean thenCompletes = canCompleteNormally (ifElement .getThenStatement ());
417+ if (thenCompletes ) {
415418 context .variablesSetThenIf ();
416419 }
417420 contextHistory .saveContext (ifElement .getThenStatement (), context );
418421 context .exitContext ();
419422
420423 // VISIT ELSE
424+ boolean elseCompletes = true ;
421425 if (ifElement .getElseStatement () != null ) {
422426 context .getVariableByName (pathVarName );
423427 context .newRefinementToVariableInContext (pathVarName , elseRefs );
424428
425429 context .enterContext ();
426430 visitCtBlock (ifElement .getElseStatement ());
427- if (canCompleteNormally (ifElement .getElseStatement ())) {
431+ elseCompletes = canCompleteNormally (ifElement .getElseStatement ());
432+ if (elseCompletes ) {
428433 context .variablesSetElseIf ();
429434 }
430435 contextHistory .saveContext (ifElement .getElseStatement (), context );
431436 context .exitContext ();
432437 }
433438 // end
434- // Reset the path variable's refinement to the original condition after the if,
435- // so branch-local truth assertions (and any typestate they imply) don't leak past the join.
436- context .newRefinementToVariableInContext (pathVarName , expRefs );
437- vcChecker .removePathVariable (freshRV );
439+ if (thenCompletes == elseCompletes ) {
440+ // Reset the path variable's refinement to the original condition after the if,
441+ // so branch-local truth assertions (and any typestate they imply) don't leak past the join.
442+ context .newRefinementToVariableInContext (pathVarName , expRefs );
443+ vcChecker .removePathVariable (freshRV );
444+ } else {
445+ // Keep the refinement of the only branch that reaches the code after the if.
446+ context .newRefinementToVariableInContext (pathVarName , thenCompletes ? thenRefs : elseRefs );
447+ }
438448 context .exitContext ();
439449 context .variablesCombineFromIf (expRefs );
440450 context .variablesFinishIfCombination ();
0 commit comments