@@ -114,6 +114,7 @@ public <T> void visitCtConstructor(CtConstructor<T> constructor) {
114114 }
115115 contextHistory .saveContext (constructor , context );
116116 context .exitContext ();
117+ vcChecker .clearPathVariables ();
117118 }
118119
119120 public <R > void visitCtMethod (CtMethod <R > method ) {
@@ -128,6 +129,7 @@ public <R> void visitCtMethod(CtMethod<R> method) {
128129 }
129130 contextHistory .saveContext (method , context );
130131 context .exitContext ();
132+ vcChecker .clearPathVariables ();
131133 }
132134
133135 @ Override
@@ -409,30 +411,38 @@ public void visitCtIf(CtIf ifElement) {
409411 // VISIT THEN
410412 context .enterContext ();
411413 visitCtBlock (ifElement .getThenStatement ());
412- if (canCompleteNormally (ifElement .getThenStatement ())) {
414+ boolean thenCompletes = canCompleteNormally (ifElement .getThenStatement ());
415+ if (thenCompletes ) {
413416 context .variablesSetThenIf ();
414417 }
415418 contextHistory .saveContext (ifElement .getThenStatement (), context );
416419 context .exitContext ();
417420
418421 // VISIT ELSE
422+ boolean elseCompletes = true ;
419423 if (ifElement .getElseStatement () != null ) {
420424 context .getVariableByName (pathVarName );
421425 context .newRefinementToVariableInContext (pathVarName , elseRefs );
422426
423427 context .enterContext ();
424428 visitCtBlock (ifElement .getElseStatement ());
425- if (canCompleteNormally (ifElement .getElseStatement ())) {
429+ elseCompletes = canCompleteNormally (ifElement .getElseStatement ());
430+ if (elseCompletes ) {
426431 context .variablesSetElseIf ();
427432 }
428433 contextHistory .saveContext (ifElement .getElseStatement (), context );
429434 context .exitContext ();
430435 }
431436 // end
432- // Reset the path variable's refinement to the original condition after the if,
433- // so branch-local truth assertions (and any typestate they imply) don't leak past the join.
434- context .newRefinementToVariableInContext (pathVarName , expRefs );
435- vcChecker .removePathVariable (freshRV );
437+ if (thenCompletes == elseCompletes ) {
438+ // Reset the path variable's refinement to the original condition after the if,
439+ // so branch-local truth assertions (and any typestate they imply) don't leak past the join.
440+ context .newRefinementToVariableInContext (pathVarName , expRefs );
441+ vcChecker .removePathVariable (freshRV );
442+ } else {
443+ // Keep the refinement of the only branch that reaches the code after the if.
444+ context .newRefinementToVariableInContext (pathVarName , thenCompletes ? thenRefs : elseRefs );
445+ }
436446 context .exitContext ();
437447 context .variablesCombineFromIf (expRefs );
438448 context .variablesFinishIfCombination ();
0 commit comments