@@ -1179,7 +1179,7 @@ module Exprs {
11791179 }
11801180
11811181 /**
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 .
11831183 *
11841184 * This is needed because the Swift AST for `b1 && b2` is really syntactic sugar a function call:
11851185 * ```swift
@@ -1188,10 +1188,13 @@ module Exprs {
11881188 * So the `true` edge from `b1` cannot just go to `b2` since this is an implicit autoclosure.
11891189 * To handle this dig into the autoclosure when it's an operand of a logical operator.
11901190 */
1191- private class LogicalAutoClosureTree extends AstPreOrderTree {
1191+ private class ShortCircuitingAutoClosureTree extends AstPreOrderTree {
11921192 override AutoClosureExpr ast ;
11931193
1194- LogicalAutoClosureTree ( ) { ast = any ( LogicalOperation op ) .getAnOperand ( ) }
1194+ ShortCircuitingAutoClosureTree ( ) {
1195+ ast = any ( LogicalOperation op ) .getAnOperand ( ) or
1196+ ast = any ( NilCoalescingExpr expr ) .getAnOperand ( )
1197+ }
11951198
11961199 override predicate last ( ControlFlowElement last , Completion c ) {
11971200 exists ( Completion completion | astLast ( ast .getReturn ( ) , last , completion ) |
@@ -1217,7 +1220,7 @@ module Exprs {
12171220 private class AutoClosureTree extends AstLeafTree {
12181221 override AutoClosureExpr ast ;
12191222
1220- AutoClosureTree ( ) { not this instanceof LogicalAutoClosureTree }
1223+ AutoClosureTree ( ) { not this instanceof ShortCircuitingAutoClosureTree }
12211224 }
12221225 }
12231226
@@ -1557,7 +1560,9 @@ module Exprs {
15571560 // This one is handled in `LogicalNotTree`.
15581561 not ast instanceof UnaryLogicalOperation and
15591562 // 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
15611566 }
15621567
15631568 final override ControlFlowElement getChildElement ( int i ) {
@@ -1581,6 +1586,36 @@ module Exprs {
15811586 }
15821587 }
15831588
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+
15841619 private class LogicalAndTree extends AstPostOrderTree {
15851620 override LogicalAndExpr ast ;
15861621
0 commit comments