@@ -59,6 +59,9 @@ module CfgImpl = Make<Location, CfgInput>;
59
59
60
60
import CfgImpl
61
61
62
+ /** A trivial pattern that is always guaranteed to match. */
63
+ predicate trivialPat ( Pat p ) { p instanceof WildcardPat or p instanceof IdentPat }
64
+
62
65
class AwaitExprTree extends StandardPostOrderTree instanceof AwaitExpr {
63
66
override ControlFlowTree getChildNode ( int i ) { i = 0 and result = super .getExpr ( ) }
64
67
}
@@ -236,11 +239,43 @@ class LetExprTree extends StandardPostOrderTree instanceof LetExpr {
236
239
override ControlFlowTree getChildNode ( int i ) { i = 0 and result = super .getExpr ( ) }
237
240
}
238
241
239
- class LetStmtTree extends StandardPreOrderTree instanceof LetStmt {
242
+ // We handle `let` statements with trivial patterns separately as they don't
243
+ // lead to non-standard control flow. For instance, in `let a = ...` it is not
244
+ // interesing to create match edges as it would carry no information.
245
+ class LetStmtTreeTrivialPat extends StandardPreOrderTree instanceof LetStmt {
246
+ LetStmtTreeTrivialPat ( ) { trivialPat ( super .getPat ( ) ) }
247
+
240
248
override ControlFlowTree getChildNode ( int i ) {
241
- // TODO: For now we ignore the else branch (`super.getElse`). This branch
242
- // is guaranteed to be diverging so will need special treatment in the CFG.
243
249
i = 0 and result = super .getInitializer ( )
250
+ or
251
+ i = 1 and result = super .getPat ( )
252
+ }
253
+ }
254
+
255
+ // `let` statements with interesting patterns that we want to be reflected in
256
+ // the CFG.
257
+ class LetStmtTree extends PreOrderTree instanceof LetStmt {
258
+ LetStmtTree ( ) { not trivialPat ( super .getPat ( ) ) }
259
+
260
+ final override predicate propagatesAbnormal ( AstNode child ) {
261
+ child = super .getInitializer ( ) or child = super .getElse ( )
262
+ }
263
+
264
+ override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
265
+ // Edge to start of initializer.
266
+ pred = this and first ( super .getInitializer ( ) , succ ) and completionIsSimple ( c )
267
+ or
268
+ // Edge from end of initializer to pattern.
269
+ last ( super .getInitializer ( ) , pred , c ) and succ = super .getPat ( )
270
+ or
271
+ // Edge from failed pattern to `else` branch.
272
+ pred = super .getPat ( ) and first ( super .getElse ( ) , succ ) and c .( MatchCompletion ) .failed ( )
273
+ }
274
+
275
+ override predicate last ( AstNode node , Completion c ) {
276
+ // Edge out of a successfully matched pattern.
277
+ node = super .getPat ( ) and c .( MatchCompletion ) .succeeded ( )
278
+ // NOTE: No edge out of the `else` branch as that is guaranteed to diverge.
244
279
}
245
280
}
246
281
@@ -327,6 +362,8 @@ class MethodCallExprTree extends StandardPostOrderTree instanceof MethodCallExpr
327
362
328
363
class OffsetOfExprTree extends LeafTree instanceof OffsetOfExpr { }
329
364
365
+ class PatExprTree extends LeafTree instanceof Pat { }
366
+
330
367
class PathExprTree extends LeafTree instanceof PathExpr { }
331
368
332
369
class RecordExprTree extends StandardPostOrderTree instanceof RecordExpr {
0 commit comments