@@ -623,13 +623,21 @@ module CFG {
623623 not cmpl .isNormal ( )
624624 }
625625
626- predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
626+ /**
627+ * Holds if `succ` is a successor of `pred`, ignoring the execution of any
628+ * deferred functions when a function ends.
629+ */
630+ pragma [ nomagic]
631+ predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
627632 exists ( int i |
628633 lastNode ( this .getChildTreeRanked ( i ) , pred , normalCompletion ( ) ) and
629634 firstNode ( this .getChildTreeRanked ( i + 1 ) , succ )
630635 )
631636 }
632637
638+ /** Holds if `succ` is a successor of `pred`. */
639+ predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) { this .succ0 ( pred , succ ) }
640+
633641 final ControlFlowTree getChildTreeRanked ( int i ) {
634642 exists ( int j |
635643 result = this .getChildTree ( j ) and
@@ -727,8 +735,9 @@ module CFG {
727735 last = this .getNode ( ) and cmpl = this .getCompletion ( )
728736 }
729737
730- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
731- super .succ ( pred , succ )
738+ pragma [ nomagic]
739+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
740+ super .succ0 ( pred , succ )
732741 or
733742 lastNode ( this .getLastChildTree ( ) , pred , normalCompletion ( ) ) and
734743 succ = this .getNode ( )
@@ -750,8 +759,9 @@ module CFG {
750759 cmpl = Done ( )
751760 }
752761
753- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
754- super .succ ( pred , succ )
762+ pragma [ nomagic]
763+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
764+ super .succ0 ( pred , succ )
755765 or
756766 pred = this .getNode ( ) and
757767 firstNode ( this .getFirstChildTree ( ) , succ )
@@ -853,8 +863,9 @@ module CFG {
853863 cmpl = Done ( )
854864 }
855865
856- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
857- ControlFlowTree .super .succ ( pred , succ )
866+ pragma [ nomagic]
867+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
868+ ControlFlowTree .super .succ0 ( pred , succ )
858869 or
859870 exists ( int i | lastNode ( this .getLhs ( i ) , pred , normalCompletion ( ) ) |
860871 firstNode ( this .getLhs ( i + 1 ) , succ )
@@ -978,7 +989,8 @@ module CFG {
978989 )
979990 }
980991
981- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
992+ pragma [ nomagic]
993+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
982994 exists ( Completion lcmpl |
983995 lastNode ( this .getLeftOperand ( ) , pred , lcmpl ) and
984996 succ = this .getGuard ( lcmpl .getOutcome ( ) )
@@ -1028,11 +1040,12 @@ module CFG {
10281040 not result instanceof TypeExpr
10291041 }
10301042
1031- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1043+ pragma [ nomagic]
1044+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
10321045 // interpose implicit argument destructuring nodes between last argument
10331046 // and call itself; this is for cases like `f(g())` where `g` has multiple
10341047 // results
1035- exists ( ControlFlow:: Node mid | PostOrderTree .super .succ ( pred , mid ) |
1048+ exists ( ControlFlow:: Node mid | PostOrderTree .super .succ0 ( pred , mid ) |
10361049 if mid = this .getNode ( ) then succ = this .getEpilogueNode ( 0 ) else succ = mid
10371050 )
10381051 or
@@ -1102,8 +1115,9 @@ module CFG {
11021115 lastNode ( this .getStmt ( this .getNumStmt ( ) - 1 ) , last , cmpl )
11031116 }
11041117
1105- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1106- ControlFlowTree .super .succ ( pred , succ )
1118+ pragma [ nomagic]
1119+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1120+ ControlFlowTree .super .succ0 ( pred , succ )
11071121 or
11081122 exists ( int i |
11091123 lastNode ( this .getExpr ( i ) , pred , normalCompletion ( ) ) and
@@ -1172,7 +1186,8 @@ module CFG {
11721186 cmpl = Done ( )
11731187 }
11741188
1175- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1189+ pragma [ nomagic]
1190+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
11761191 this .firstNode ( pred ) and
11771192 succ = this .getElementStart ( 0 )
11781193 or
@@ -1250,7 +1265,8 @@ module CFG {
12501265 cmpl = Done ( )
12511266 }
12521267
1253- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1268+ pragma [ nomagic]
1269+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
12541270 lastNode ( this .getInit ( ) , pred , normalCompletion ( ) ) and
12551271 firstNode ( this .getCond ( ) , succ )
12561272 or
@@ -1281,7 +1297,8 @@ module CFG {
12811297 ( cmpl = Done ( ) or cmpl = Panic ( ) )
12821298 }
12831299
1284- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1300+ pragma [ nomagic]
1301+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
12851302 lastNode ( this .getBase ( ) , pred , normalCompletion ( ) ) and
12861303 (
12871304 succ = MkImplicitDeref ( this .getBase ( ) )
@@ -1318,8 +1335,9 @@ module CFG {
13181335
13191336 override predicate lastNode ( ControlFlow:: Node last , Completion cmpl ) { none ( ) }
13201337
1321- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1322- ControlFlowTree .super .succ ( pred , succ )
1338+ pragma [ nomagic]
1339+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1340+ ControlFlowTree .super .succ0 ( pred , succ )
13231341 or
13241342 pred = MkEntryNode ( this ) and
13251343 firstNode ( this .getDecl ( 0 ) , succ )
@@ -1374,7 +1392,8 @@ module CFG {
13741392 i = 5 and result = this .getBody ( )
13751393 }
13761394
1377- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1395+ pragma [ nomagic]
1396+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
13781397 exists ( int i , ControlFlowTree predTree , Completion cmpl |
13791398 predTree = this .getChildTreeRanked ( i ) and
13801399 lastNode ( predTree , pred , cmpl ) and
@@ -1440,13 +1459,14 @@ module CFG {
14401459 // `defer` can be the first `defer` statement executed
14411460 // there is always a predecessor node because the `defer`'s call is always
14421461 // evaluated before the defer statement itself
1443- MkDeferNode ( defer ) = succ ( notDeferSucc * ( this .getEntry ( ) ) )
1462+ MkDeferNode ( defer ) = succ0 ( notDeferSucc0 * ( this .getEntry ( ) ) )
14441463 )
14451464 }
14461465
14471466 override predicate lastNode ( ControlFlow:: Node last , Completion cmpl ) { none ( ) }
14481467
1449- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1468+ pragma [ nomagic]
1469+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
14501470 exists ( int i |
14511471 pred = this .getPrologueNode ( i ) and
14521472 succ = this .getPrologueNode ( i + 1 )
@@ -1460,10 +1480,19 @@ module CFG {
14601480 firstNode ( ls , succ )
14611481 )
14621482 or
1483+ exists ( int i |
1484+ pred = this .getEpilogueNode ( i ) and
1485+ succ = this .getEpilogueNode ( i + 1 )
1486+ )
1487+ }
1488+
1489+ override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1490+ this .succ0 ( pred , succ )
1491+ or
14631492 exists ( Completion cmpl |
14641493 lastNode ( this .getBody ( ) , pred , cmpl ) and
14651494 // last node of function body can be reached without going through a `defer` statement
1466- pred = notDeferSucc * ( this .getEntry ( ) )
1495+ pred = notDeferSucc0 * ( this .getEntry ( ) )
14671496 |
14681497 // panic goes directly to exit, non-panic reads result variables first
14691498 if cmpl = Panic ( ) then succ = MkExitNode ( this ) else succ = this .getEpilogueNode ( 0 )
@@ -1473,7 +1502,7 @@ module CFG {
14731502 exists ( DeferStmt defer | defer = this .getADeferStmt ( ) |
14741503 succ = MkExprNode ( defer .getCall ( ) ) and
14751504 // the last `DeferStmt` executed before pred is this `defer`
1476- pred = notDeferSucc * ( MkDeferNode ( defer ) )
1505+ pred = notDeferSucc0 * ( MkDeferNode ( defer ) )
14771506 )
14781507 or
14791508 exists ( DeferStmt predDefer , DeferStmt succDefer |
@@ -1494,11 +1523,6 @@ module CFG {
14941523 or
14951524 succ = this .getEpilogueNode ( 0 )
14961525 )
1497- or
1498- exists ( int i |
1499- pred = this .getEpilogueNode ( i ) and
1500- succ = this .getEpilogueNode ( i + 1 )
1501- )
15021526 }
15031527 }
15041528
@@ -1516,7 +1540,8 @@ module CFG {
15161540 cmpl = Done ( )
15171541 }
15181542
1519- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1543+ pragma [ nomagic]
1544+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
15201545 lastNode ( this .getOperand ( ) , pred , normalCompletion ( ) ) and
15211546 succ = MkImplicitOne ( this )
15221547 or
@@ -1547,7 +1572,8 @@ module CFG {
15471572 not cmpl .isNormal ( )
15481573 }
15491574
1550- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1575+ pragma [ nomagic]
1576+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
15511577 lastNode ( this .getDomain ( ) , pred , normalCompletion ( ) ) and
15521578 succ = MkNextNode ( this )
15531579 or
@@ -1622,7 +1648,8 @@ module CFG {
16221648
16231649 override Completion getCompletion ( ) { result = Return ( ) }
16241650
1625- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1651+ pragma [ nomagic]
1652+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
16261653 exists ( int i |
16271654 lastNode ( this .getExpr ( i ) , pred , normalCompletion ( ) ) and
16281655 succ = this .complete ( i )
@@ -1678,8 +1705,9 @@ module CFG {
16781705 )
16791706 }
16801707
1681- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1682- ControlFlowTree .super .succ ( pred , succ )
1708+ pragma [ nomagic]
1709+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1710+ ControlFlowTree .super .succ0 ( pred , succ )
16831711 or
16841712 exists ( CommClause cc , int i , Stmt comm |
16851713 cc = this .getNonDefaultCommClause ( i ) and
@@ -1777,7 +1805,8 @@ module CFG {
17771805 cmpl = Done ( )
17781806 }
17791807
1780- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1808+ pragma [ nomagic]
1809+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
17811810 exists ( int i | pred = this .getStepWithRank ( i ) and succ = this .getStepWithRank ( i + 1 ) )
17821811 }
17831812
@@ -1814,8 +1843,9 @@ module CFG {
18141843 ( cmpl = Done ( ) or cmpl = Panic ( ) )
18151844 }
18161845
1817- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1818- ControlFlowTree .super .succ ( pred , succ )
1846+ pragma [ nomagic]
1847+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1848+ ControlFlowTree .super .succ0 ( pred , succ )
18191849 or
18201850 not this = any ( CommClause cc ) .getComm ( ) and
18211851 lastNode ( this .getValue ( ) , pred , normalCompletion ( ) ) and
@@ -1843,8 +1873,9 @@ module CFG {
18431873 ( cmpl = Done ( ) or cmpl = Panic ( ) )
18441874 }
18451875
1846- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1847- ControlFlowTree .super .succ ( pred , succ )
1876+ pragma [ nomagic]
1877+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1878+ ControlFlowTree .super .succ0 ( pred , succ )
18481879 or
18491880 lastNode ( this .getBase ( ) , pred , normalCompletion ( ) ) and
18501881 (
@@ -1930,8 +1961,9 @@ module CFG {
19301961 )
19311962 }
19321963
1933- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1934- ControlFlowTree .super .succ ( pred , succ )
1964+ pragma [ nomagic]
1965+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1966+ ControlFlowTree .super .succ0 ( pred , succ )
19351967 or
19361968 lastNode ( this .getInit ( ) , pred , normalCompletion ( ) ) and
19371969 (
@@ -2004,8 +2036,9 @@ module CFG {
20042036 )
20052037 }
20062038
2007- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
2008- ControlFlowTree .super .succ ( pred , succ )
2039+ pragma [ nomagic]
2040+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
2041+ ControlFlowTree .super .succ0 ( pred , succ )
20092042 or
20102043 not this = any ( RecvStmt recv ) .getExpr ( ) and
20112044 lastNode ( this .getOperand ( ) , pred , normalCompletion ( ) ) and
@@ -2033,19 +2066,19 @@ module CFG {
20332066 }
20342067
20352068 /** Gets a successor of `nd` that is not a `defer` node */
2036- private ControlFlow:: Node notDeferSucc ( ControlFlow:: Node nd ) {
2069+ private ControlFlow:: Node notDeferSucc0 ( ControlFlow:: Node nd ) {
20372070 not result = MkDeferNode ( _) and
2038- result = succ ( nd )
2071+ result = succ0 ( nd )
20392072 }
20402073
20412074 /** Gets `defer` statements that can be the first defer statement after `nd` in the CFG */
20422075 private ControlFlow:: Node nextDefer ( ControlFlow:: Node nd ) {
20432076 nd = MkDeferNode ( _) and
20442077 result = MkDeferNode ( _) and
20452078 (
2046- result = succ ( nd )
2079+ result = succ0 ( nd )
20472080 or
2048- result = succ ( notDeferSucc + ( nd ) )
2081+ result = succ0 ( notDeferSucc0 + ( nd ) )
20492082 )
20502083 }
20512084
@@ -2074,6 +2107,15 @@ module CFG {
20742107 )
20752108 }
20762109
2110+ /**
2111+ * Gets a successor of `nd`, that is, a node that is executed after `nd`,
2112+ * ignoring the execution of any deferred functions when a function ends.
2113+ */
2114+ pragma [ nomagic]
2115+ private ControlFlow:: Node succ0 ( ControlFlow:: Node nd ) {
2116+ any ( ControlFlowTree tree ) .succ0 ( nd , result )
2117+ }
2118+
20772119 /** Gets a successor of `nd`, that is, a node that is executed after `nd`. */
20782120 cached
20792121 ControlFlow:: Node succ ( ControlFlow:: Node nd ) { any ( ControlFlowTree tree ) .succ ( nd , result ) }
0 commit comments