@@ -623,13 +623,21 @@ module CFG {
623
623
not cmpl .isNormal ( )
624
624
}
625
625
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 ) {
627
632
exists ( int i |
628
633
lastNode ( this .getChildTreeRanked ( i ) , pred , normalCompletion ( ) ) and
629
634
firstNode ( this .getChildTreeRanked ( i + 1 ) , succ )
630
635
)
631
636
}
632
637
638
+ /** Holds if `succ` is a successor of `pred`. */
639
+ predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) { this .succ0 ( pred , succ ) }
640
+
633
641
final ControlFlowTree getChildTreeRanked ( int i ) {
634
642
exists ( int j |
635
643
result = this .getChildTree ( j ) and
@@ -727,8 +735,9 @@ module CFG {
727
735
last = this .getNode ( ) and cmpl = this .getCompletion ( )
728
736
}
729
737
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 )
732
741
or
733
742
lastNode ( this .getLastChildTree ( ) , pred , normalCompletion ( ) ) and
734
743
succ = this .getNode ( )
@@ -750,8 +759,9 @@ module CFG {
750
759
cmpl = Done ( )
751
760
}
752
761
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 )
755
765
or
756
766
pred = this .getNode ( ) and
757
767
firstNode ( this .getFirstChildTree ( ) , succ )
@@ -853,8 +863,9 @@ module CFG {
853
863
cmpl = Done ( )
854
864
}
855
865
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 )
858
869
or
859
870
exists ( int i | lastNode ( this .getLhs ( i ) , pred , normalCompletion ( ) ) |
860
871
firstNode ( this .getLhs ( i + 1 ) , succ )
@@ -978,7 +989,8 @@ module CFG {
978
989
)
979
990
}
980
991
981
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
992
+ pragma [ nomagic]
993
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
982
994
exists ( Completion lcmpl |
983
995
lastNode ( this .getLeftOperand ( ) , pred , lcmpl ) and
984
996
succ = this .getGuard ( lcmpl .getOutcome ( ) )
@@ -1028,11 +1040,12 @@ module CFG {
1028
1040
not result instanceof TypeExpr
1029
1041
}
1030
1042
1031
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1043
+ pragma [ nomagic]
1044
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1032
1045
// interpose implicit argument destructuring nodes between last argument
1033
1046
// and call itself; this is for cases like `f(g())` where `g` has multiple
1034
1047
// results
1035
- exists ( ControlFlow:: Node mid | PostOrderTree .super .succ ( pred , mid ) |
1048
+ exists ( ControlFlow:: Node mid | PostOrderTree .super .succ0 ( pred , mid ) |
1036
1049
if mid = this .getNode ( ) then succ = this .getEpilogueNode ( 0 ) else succ = mid
1037
1050
)
1038
1051
or
@@ -1102,8 +1115,9 @@ module CFG {
1102
1115
lastNode ( this .getStmt ( this .getNumStmt ( ) - 1 ) , last , cmpl )
1103
1116
}
1104
1117
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 )
1107
1121
or
1108
1122
exists ( int i |
1109
1123
lastNode ( this .getExpr ( i ) , pred , normalCompletion ( ) ) and
@@ -1172,7 +1186,8 @@ module CFG {
1172
1186
cmpl = Done ( )
1173
1187
}
1174
1188
1175
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1189
+ pragma [ nomagic]
1190
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1176
1191
this .firstNode ( pred ) and
1177
1192
succ = this .getElementStart ( 0 )
1178
1193
or
@@ -1250,7 +1265,8 @@ module CFG {
1250
1265
cmpl = Done ( )
1251
1266
}
1252
1267
1253
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1268
+ pragma [ nomagic]
1269
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1254
1270
lastNode ( this .getInit ( ) , pred , normalCompletion ( ) ) and
1255
1271
firstNode ( this .getCond ( ) , succ )
1256
1272
or
@@ -1281,7 +1297,8 @@ module CFG {
1281
1297
( cmpl = Done ( ) or cmpl = Panic ( ) )
1282
1298
}
1283
1299
1284
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1300
+ pragma [ nomagic]
1301
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1285
1302
lastNode ( this .getBase ( ) , pred , normalCompletion ( ) ) and
1286
1303
(
1287
1304
succ = MkImplicitDeref ( this .getBase ( ) )
@@ -1318,8 +1335,9 @@ module CFG {
1318
1335
1319
1336
override predicate lastNode ( ControlFlow:: Node last , Completion cmpl ) { none ( ) }
1320
1337
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 )
1323
1341
or
1324
1342
pred = MkEntryNode ( this ) and
1325
1343
firstNode ( this .getDecl ( 0 ) , succ )
@@ -1374,7 +1392,8 @@ module CFG {
1374
1392
i = 5 and result = this .getBody ( )
1375
1393
}
1376
1394
1377
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1395
+ pragma [ nomagic]
1396
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1378
1397
exists ( int i , ControlFlowTree predTree , Completion cmpl |
1379
1398
predTree = this .getChildTreeRanked ( i ) and
1380
1399
lastNode ( predTree , pred , cmpl ) and
@@ -1440,13 +1459,14 @@ module CFG {
1440
1459
// `defer` can be the first `defer` statement executed
1441
1460
// there is always a predecessor node because the `defer`'s call is always
1442
1461
// evaluated before the defer statement itself
1443
- MkDeferNode ( defer ) = succ ( notDeferSucc * ( this .getEntry ( ) ) )
1462
+ MkDeferNode ( defer ) = succ0 ( notDeferSucc0 * ( this .getEntry ( ) ) )
1444
1463
)
1445
1464
}
1446
1465
1447
1466
override predicate lastNode ( ControlFlow:: Node last , Completion cmpl ) { none ( ) }
1448
1467
1449
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1468
+ pragma [ nomagic]
1469
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1450
1470
exists ( int i |
1451
1471
pred = this .getPrologueNode ( i ) and
1452
1472
succ = this .getPrologueNode ( i + 1 )
@@ -1460,10 +1480,19 @@ module CFG {
1460
1480
firstNode ( ls , succ )
1461
1481
)
1462
1482
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
1463
1492
exists ( Completion cmpl |
1464
1493
lastNode ( this .getBody ( ) , pred , cmpl ) and
1465
1494
// last node of function body can be reached without going through a `defer` statement
1466
- pred = notDeferSucc * ( this .getEntry ( ) )
1495
+ pred = notDeferSucc0 * ( this .getEntry ( ) )
1467
1496
|
1468
1497
// panic goes directly to exit, non-panic reads result variables first
1469
1498
if cmpl = Panic ( ) then succ = MkExitNode ( this ) else succ = this .getEpilogueNode ( 0 )
@@ -1473,7 +1502,7 @@ module CFG {
1473
1502
exists ( DeferStmt defer | defer = this .getADeferStmt ( ) |
1474
1503
succ = MkExprNode ( defer .getCall ( ) ) and
1475
1504
// the last `DeferStmt` executed before pred is this `defer`
1476
- pred = notDeferSucc * ( MkDeferNode ( defer ) )
1505
+ pred = notDeferSucc0 * ( MkDeferNode ( defer ) )
1477
1506
)
1478
1507
or
1479
1508
exists ( DeferStmt predDefer , DeferStmt succDefer |
@@ -1494,11 +1523,6 @@ module CFG {
1494
1523
or
1495
1524
succ = this .getEpilogueNode ( 0 )
1496
1525
)
1497
- or
1498
- exists ( int i |
1499
- pred = this .getEpilogueNode ( i ) and
1500
- succ = this .getEpilogueNode ( i + 1 )
1501
- )
1502
1526
}
1503
1527
}
1504
1528
@@ -1516,7 +1540,8 @@ module CFG {
1516
1540
cmpl = Done ( )
1517
1541
}
1518
1542
1519
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1543
+ pragma [ nomagic]
1544
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1520
1545
lastNode ( this .getOperand ( ) , pred , normalCompletion ( ) ) and
1521
1546
succ = MkImplicitOne ( this )
1522
1547
or
@@ -1547,7 +1572,8 @@ module CFG {
1547
1572
not cmpl .isNormal ( )
1548
1573
}
1549
1574
1550
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1575
+ pragma [ nomagic]
1576
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1551
1577
lastNode ( this .getDomain ( ) , pred , normalCompletion ( ) ) and
1552
1578
succ = MkNextNode ( this )
1553
1579
or
@@ -1622,7 +1648,8 @@ module CFG {
1622
1648
1623
1649
override Completion getCompletion ( ) { result = Return ( ) }
1624
1650
1625
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1651
+ pragma [ nomagic]
1652
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1626
1653
exists ( int i |
1627
1654
lastNode ( this .getExpr ( i ) , pred , normalCompletion ( ) ) and
1628
1655
succ = this .complete ( i )
@@ -1678,8 +1705,9 @@ module CFG {
1678
1705
)
1679
1706
}
1680
1707
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 )
1683
1711
or
1684
1712
exists ( CommClause cc , int i , Stmt comm |
1685
1713
cc = this .getNonDefaultCommClause ( i ) and
@@ -1777,7 +1805,8 @@ module CFG {
1777
1805
cmpl = Done ( )
1778
1806
}
1779
1807
1780
- override predicate succ ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1808
+ pragma [ nomagic]
1809
+ override predicate succ0 ( ControlFlow:: Node pred , ControlFlow:: Node succ ) {
1781
1810
exists ( int i | pred = this .getStepWithRank ( i ) and succ = this .getStepWithRank ( i + 1 ) )
1782
1811
}
1783
1812
@@ -1814,8 +1843,9 @@ module CFG {
1814
1843
( cmpl = Done ( ) or cmpl = Panic ( ) )
1815
1844
}
1816
1845
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 )
1819
1849
or
1820
1850
not this = any ( CommClause cc ) .getComm ( ) and
1821
1851
lastNode ( this .getValue ( ) , pred , normalCompletion ( ) ) and
@@ -1843,8 +1873,9 @@ module CFG {
1843
1873
( cmpl = Done ( ) or cmpl = Panic ( ) )
1844
1874
}
1845
1875
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 )
1848
1879
or
1849
1880
lastNode ( this .getBase ( ) , pred , normalCompletion ( ) ) and
1850
1881
(
@@ -1930,8 +1961,9 @@ module CFG {
1930
1961
)
1931
1962
}
1932
1963
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 )
1935
1967
or
1936
1968
lastNode ( this .getInit ( ) , pred , normalCompletion ( ) ) and
1937
1969
(
@@ -2004,8 +2036,9 @@ module CFG {
2004
2036
)
2005
2037
}
2006
2038
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 )
2009
2042
or
2010
2043
not this = any ( RecvStmt recv ) .getExpr ( ) and
2011
2044
lastNode ( this .getOperand ( ) , pred , normalCompletion ( ) ) and
@@ -2033,19 +2066,19 @@ module CFG {
2033
2066
}
2034
2067
2035
2068
/** 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 ) {
2037
2070
not result = MkDeferNode ( _) and
2038
- result = succ ( nd )
2071
+ result = succ0 ( nd )
2039
2072
}
2040
2073
2041
2074
/** Gets `defer` statements that can be the first defer statement after `nd` in the CFG */
2042
2075
private ControlFlow:: Node nextDefer ( ControlFlow:: Node nd ) {
2043
2076
nd = MkDeferNode ( _) and
2044
2077
result = MkDeferNode ( _) and
2045
2078
(
2046
- result = succ ( nd )
2079
+ result = succ0 ( nd )
2047
2080
or
2048
- result = succ ( notDeferSucc + ( nd ) )
2081
+ result = succ0 ( notDeferSucc0 + ( nd ) )
2049
2082
)
2050
2083
}
2051
2084
@@ -2074,6 +2107,15 @@ module CFG {
2074
2107
)
2075
2108
}
2076
2109
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
+
2077
2119
/** Gets a successor of `nd`, that is, a node that is executed after `nd`. */
2078
2120
cached
2079
2121
ControlFlow:: Node succ ( ControlFlow:: Node nd ) { any ( ControlFlowTree tree ) .succ ( nd , result ) }
0 commit comments