@@ -1179,7 +1179,7 @@ module Exprs {
1179
1179
}
1180
1180
1181
1181
/**
1182
- * An autoclosure expression that is generated as part of a logical operation.
1182
+ * An autoclosure expression that is generated as part of a logical operation or nil coalescing expression .
1183
1183
*
1184
1184
* This is needed because the Swift AST for `b1 && b2` is really syntactic sugar a function call:
1185
1185
* ```swift
@@ -1188,10 +1188,13 @@ module Exprs {
1188
1188
* So the `true` edge from `b1` cannot just go to `b2` since this is an implicit autoclosure.
1189
1189
* To handle this dig into the autoclosure when it's an operand of a logical operator.
1190
1190
*/
1191
- private class LogicalAutoClosureTree extends AstPreOrderTree {
1191
+ private class ShortCircuitingAutoClosureTree extends AstPreOrderTree {
1192
1192
override AutoClosureExpr ast ;
1193
1193
1194
- LogicalAutoClosureTree ( ) { ast = any ( LogicalOperation op ) .getAnOperand ( ) }
1194
+ ShortCircuitingAutoClosureTree ( ) {
1195
+ ast = any ( LogicalOperation op ) .getAnOperand ( ) or
1196
+ ast = any ( NilCoalescingExpr expr ) .getAnOperand ( )
1197
+ }
1195
1198
1196
1199
override predicate last ( ControlFlowElement last , Completion c ) {
1197
1200
exists ( Completion completion | astLast ( ast .getReturn ( ) , last , completion ) |
@@ -1217,7 +1220,7 @@ module Exprs {
1217
1220
private class AutoClosureTree extends AstLeafTree {
1218
1221
override AutoClosureExpr ast ;
1219
1222
1220
- AutoClosureTree ( ) { not this instanceof LogicalAutoClosureTree }
1223
+ AutoClosureTree ( ) { not this instanceof ShortCircuitingAutoClosureTree }
1221
1224
}
1222
1225
}
1223
1226
@@ -1557,7 +1560,9 @@ module Exprs {
1557
1560
// This one is handled in `LogicalNotTree`.
1558
1561
not ast instanceof UnaryLogicalOperation and
1559
1562
// These are handled in `LogicalOrTree` and `LogicalAndTree`.
1560
- not ast instanceof BinaryLogicalOperation
1563
+ not ast instanceof BinaryLogicalOperation and
1564
+ // This one is handled in `NilCoalescingTree`
1565
+ not ast instanceof NilCoalescingExpr
1561
1566
}
1562
1567
1563
1568
final override ControlFlowElement getChildElement ( int i ) {
@@ -1581,6 +1586,36 @@ module Exprs {
1581
1586
}
1582
1587
}
1583
1588
1589
+ private class NilCoalescingTree extends AstControlFlowTree {
1590
+ override NilCoalescingExpr ast ;
1591
+
1592
+ final override predicate propagatesAbnormal ( ControlFlowElement child ) {
1593
+ child .asAstNode ( ) = ast .getAnOperand ( ) .getFullyConverted ( )
1594
+ }
1595
+
1596
+ final override predicate first ( ControlFlowElement first ) {
1597
+ astFirst ( ast .getLeftOperand ( ) .getFullyConverted ( ) , first )
1598
+ }
1599
+
1600
+ final override predicate last ( ControlFlowElement last , Completion c ) {
1601
+ last .asAstNode ( ) = ast and
1602
+ exists ( EmptinessCompletion ec | ec = c | not ec .isEmpty ( ) )
1603
+ or
1604
+ astLast ( ast .getRightOperand ( ) .getFullyConverted ( ) , last , c ) and
1605
+ c instanceof NormalCompletion
1606
+ }
1607
+
1608
+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1609
+ astLast ( ast .getLeftOperand ( ) .getFullyConverted ( ) , pred , c ) and
1610
+ c instanceof NormalCompletion and
1611
+ succ .asAstNode ( ) = ast
1612
+ or
1613
+ pred .asAstNode ( ) = ast and
1614
+ c .( EmptinessCompletion ) .isEmpty ( ) and
1615
+ astFirst ( ast .getRightOperand ( ) .getFullyConverted ( ) , succ )
1616
+ }
1617
+ }
1618
+
1584
1619
private class LogicalAndTree extends AstPostOrderTree {
1585
1620
override LogicalAndExpr ast ;
1586
1621
0 commit comments