@@ -1181,7 +1181,7 @@ module Exprs {
11811181 }
11821182
11831183 /**
1184- * An autoclosure expression that is generated as part of a logical operation.
1184+ * An autoclosure expression that is generated as part of a logical operation or nil coalescing expression .
11851185 *
11861186 * This is needed because the Swift AST for `b1 && b2` is really syntactic sugar a function call:
11871187 * ```swift
@@ -1190,10 +1190,13 @@ module Exprs {
11901190 * So the `true` edge from `b1` cannot just go to `b2` since this is an implicit autoclosure.
11911191 * To handle this dig into the autoclosure when it's an operand of a logical operator.
11921192 */
1193- private class LogicalAutoClosureTree extends AstPreOrderTree {
1193+ private class ShortCircuitingAutoClosureTree extends AstPreOrderTree {
11941194 override AutoClosureExpr ast ;
11951195
1196- LogicalAutoClosureTree ( ) { ast = any ( LogicalOperation op ) .getAnOperand ( ) }
1196+ ShortCircuitingAutoClosureTree ( ) {
1197+ ast = any ( LogicalOperation op ) .getAnOperand ( ) or
1198+ ast = any ( NilCoalescingExpr expr ) .getAnOperand ( )
1199+ }
11971200
11981201 override predicate last ( ControlFlowElement last , Completion c ) {
11991202 exists ( Completion completion | astLast ( ast .getReturn ( ) , last , completion ) |
@@ -1219,7 +1222,7 @@ module Exprs {
12191222 private class AutoClosureTree extends AstLeafTree {
12201223 override AutoClosureExpr ast ;
12211224
1222- AutoClosureTree ( ) { not this instanceof LogicalAutoClosureTree }
1225+ AutoClosureTree ( ) { not this instanceof ShortCircuitingAutoClosureTree }
12231226 }
12241227 }
12251228
@@ -1559,7 +1562,9 @@ module Exprs {
15591562 // This one is handled in `LogicalNotTree`.
15601563 not ast instanceof UnaryLogicalOperation and
15611564 // These are handled in `LogicalOrTree` and `LogicalAndTree`.
1562- not ast instanceof BinaryLogicalOperation
1565+ not ast instanceof BinaryLogicalOperation and
1566+ // This one is handled in `NilCoalescingTree`
1567+ not ast instanceof NilCoalescingExpr
15631568 }
15641569
15651570 final override ControlFlowElement getChildElement ( int i ) {
@@ -1583,6 +1588,38 @@ module Exprs {
15831588 }
15841589 }
15851590
1591+ private class NilCoalescingTestTree extends LeafTree , NilCoalescingElement { }
1592+
1593+ private class NilCoalescingTree extends AstPostOrderTree {
1594+ override NilCoalescingExpr ast ;
1595+
1596+ final override predicate propagatesAbnormal ( ControlFlowElement child ) {
1597+ child .asAstNode ( ) = ast .getAnOperand ( ) .getFullyConverted ( )
1598+ }
1599+
1600+ final override predicate first ( ControlFlowElement first ) {
1601+ astFirst ( ast .getLeftOperand ( ) .getFullyConverted ( ) , first )
1602+ }
1603+
1604+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1605+ astLast ( ast .getLeftOperand ( ) .getFullyConverted ( ) , pred , c ) and
1606+ c instanceof NormalCompletion and
1607+ succ .( NilCoalescingTestTree ) .getAst ( ) = ast
1608+ or
1609+ pred .( NilCoalescingTestTree ) .getAst ( ) = ast and
1610+ exists ( EmptinessCompletion ec | c = ec | ec .isEmpty ( ) ) and
1611+ astFirst ( ast .getRightOperand ( ) .getFullyConverted ( ) , succ )
1612+ or
1613+ pred .( NilCoalescingTestTree ) .getAst ( ) = ast and
1614+ exists ( EmptinessCompletion ec | c = ec | not ec .isEmpty ( ) ) and
1615+ succ .asAstNode ( ) = ast
1616+ or
1617+ astLast ( ast .getRightOperand ( ) .getFullyConverted ( ) , pred , c ) and
1618+ c instanceof NormalCompletion and
1619+ succ .asAstNode ( ) = ast
1620+ }
1621+ }
1622+
15861623 private class LogicalAndTree extends AstPostOrderTree {
15871624 override LogicalAndExpr ast ;
15881625
0 commit comments