@@ -386,6 +386,27 @@ abstract class StackVariableReachability extends string {
386
386
)
387
387
}
388
388
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
+
389
410
/**
390
411
* Holds if `pred`, `succ`, `predSkipsFirstLoopAlwaysTrueUponEntry` and
391
412
* `succSkipsFirstLoopAlwaysTrueUponEntry` satisfy the loop invariants specified in the QLDoc
@@ -396,36 +417,32 @@ abstract class StackVariableReachability extends string {
396
417
* 2. Refines the successor relation when the edge `pred -> succ` is a conditional edge whose truth
397
418
* value is known.
398
419
*/
420
+ pragma [ nomagic]
399
421
private predicate bbSuccessorEntryReachesLoopInvariant (
400
422
ControlFlowNode source , BasicBlock pred , SemanticStackVariable v , BasicBlock succ ,
401
423
boolean predSkipsFirstLoopAlwaysTrueUponEntry , boolean succSkipsFirstLoopAlwaysTrueUponEntry
402
424
) {
403
- not exists ( Condition cond |
425
+ bbSuccessorEntryReachesLoopInvariantCand ( source , pred , v , succ ,
426
+ predSkipsFirstLoopAlwaysTrueUponEntry , succSkipsFirstLoopAlwaysTrueUponEntry ) and
427
+ not exists ( Condition cond , Condition direct |
404
428
cond = getACondition ( source , v , pred ) and
405
- cond .refutesCondition ( getADirectCondition ( succ ) )
429
+ direct = pragma [ only_bind_out ] ( getADirectCondition ( succ ) ) and
430
+ cond .refutesCondition ( direct )
406
431
) 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
412
432
(
413
433
// If we picked the successor edge corresponding to a condition being true, there must not be
414
434
// another path condition that refutes that the condition is true.
415
- succ = pred .getATrueSuccessor ( ) and
416
435
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 ) ) )
418
438
)
419
439
or
420
440
// If we picked the successor edge corresponding to a condition being false, there must not be
421
441
// another path condition that refutes that the condition is false.
422
- succ = pred .getAFalseSuccessor ( ) and
423
442
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 ) ) )
425
445
)
426
- or
427
- // If it wasn't a conditional successor edge we require nothing.
428
- not succ = [ pred .getATrueSuccessor ( ) , pred .getAFalseSuccessor ( ) ]
429
446
)
430
447
}
431
448
0 commit comments