@@ -386,6 +386,27 @@ abstract class StackVariableReachability extends string {
386386 )
387387 }
388388
389+ pragma [ nomagic]
390+ private predicate bbSuccessorEntryReachesLoopInvariantSucc (
391+ ControlFlowNode source , BasicBlock pred , SemanticStackVariable v , BasicBlock succ ,
392+ boolean predSkipsFirstLoopAlwaysTrueUponEntry
393+ ) {
394+ revBbSuccessorEntryReaches0 ( source , pragma [ only_bind_into ] ( pred ) , v ,
395+ predSkipsFirstLoopAlwaysTrueUponEntry , this ) and
396+ pred .getASuccessor ( ) = succ
397+ }
398+
399+ pragma [ nomagic]
400+ private predicate bbSuccessorEntryReachesLoopInvariantCand (
401+ ControlFlowNode source , BasicBlock pred , SemanticStackVariable v , BasicBlock succ ,
402+ boolean predSkipsFirstLoopAlwaysTrueUponEntry , boolean succSkipsFirstLoopAlwaysTrueUponEntry
403+ ) {
404+ bbSuccessorEntryReachesLoopInvariantSucc ( source , pragma [ only_bind_into ] ( pred ) , v , succ ,
405+ predSkipsFirstLoopAlwaysTrueUponEntry ) and
406+ bbSuccessorEntryReachesLoopInvariant0 ( pred , succ , predSkipsFirstLoopAlwaysTrueUponEntry ,
407+ succSkipsFirstLoopAlwaysTrueUponEntry )
408+ }
409+
389410 /**
390411 * Holds if `pred`, `succ`, `predSkipsFirstLoopAlwaysTrueUponEntry` and
391412 * `succSkipsFirstLoopAlwaysTrueUponEntry` satisfy the loop invariants specified in the QLDoc
@@ -396,36 +417,32 @@ abstract class StackVariableReachability extends string {
396417 * 2. Refines the successor relation when the edge `pred -> succ` is a conditional edge whose truth
397418 * value is known.
398419 */
420+ pragma [ nomagic]
399421 private predicate bbSuccessorEntryReachesLoopInvariant (
400422 ControlFlowNode source , BasicBlock pred , SemanticStackVariable v , BasicBlock succ ,
401423 boolean predSkipsFirstLoopAlwaysTrueUponEntry , boolean succSkipsFirstLoopAlwaysTrueUponEntry
402424 ) {
403- not exists ( Condition cond |
425+ bbSuccessorEntryReachesLoopInvariantCand ( source , pred , v , succ ,
426+ predSkipsFirstLoopAlwaysTrueUponEntry , succSkipsFirstLoopAlwaysTrueUponEntry ) and
427+ not exists ( Condition cond , Condition direct |
404428 cond = getACondition ( source , v , pred ) and
405- cond .refutesCondition ( getADirectCondition ( succ ) )
429+ direct = pragma [ only_bind_out ] ( getADirectCondition ( succ ) ) and
430+ cond .refutesCondition ( direct )
406431 ) and
407- pred .getASuccessor ( ) = succ and
408- revBbSuccessorEntryReaches0 ( source , pragma [ only_bind_into ] ( pred ) , v ,
409- predSkipsFirstLoopAlwaysTrueUponEntry , this ) and
410- bbSuccessorEntryReachesLoopInvariant0 ( pred , succ , predSkipsFirstLoopAlwaysTrueUponEntry ,
411- succSkipsFirstLoopAlwaysTrueUponEntry ) and
412432 (
413433 // If we picked the successor edge corresponding to a condition being true, there must not be
414434 // another path condition that refutes that the condition is true.
415- succ = pred .getATrueSuccessor ( ) and
416435 not exists ( Condition cond | cond = getACondition ( source , v , pred ) |
417- cond .refutesCondition ( MkCondition ( pred .getEnd ( ) , true ) )
436+ succ = pred .getATrueSuccessor ( ) and
437+ cond .refutesCondition ( pragma [ only_bind_out ] ( MkCondition ( pred .getEnd ( ) , true ) ) )
418438 )
419439 or
420440 // If we picked the successor edge corresponding to a condition being false, there must not be
421441 // another path condition that refutes that the condition is false.
422- succ = pred .getAFalseSuccessor ( ) and
423442 not exists ( Condition cond | cond = getACondition ( source , v , pred ) |
424- cond .refutesCondition ( MkCondition ( pred .getEnd ( ) , false ) )
443+ succ = pred .getAFalseSuccessor ( ) and
444+ cond .refutesCondition ( pragma [ only_bind_out ] ( MkCondition ( pred .getEnd ( ) , false ) ) )
425445 )
426- or
427- // If it wasn't a conditional successor edge we require nothing.
428- not succ = [ pred .getATrueSuccessor ( ) , pred .getAFalseSuccessor ( ) ]
429446 )
430447 }
431448
0 commit comments