@@ -149,25 +149,15 @@ private AstNode desugar(AstNode n) {
149
149
/**
150
150
* A class for mapping parent-child AST nodes to parent-child CFG nodes.
151
151
*/
152
- abstract private class ExprChildMapping extends Expr {
152
+ abstract private class ChildMapping extends AstNode {
153
153
/**
154
154
* Holds if `child` is a (possibly nested) child of this expression
155
155
* for which we would like to find a matching CFG child.
156
156
*/
157
157
abstract predicate relevantChild ( AstNode child ) ;
158
158
159
159
pragma [ nomagic]
160
- private predicate reachesBasicBlock ( AstNode child , CfgNode cfn , BasicBlock bb ) {
161
- this .relevantChild ( child ) and
162
- cfn = this .getAControlFlowNode ( ) and
163
- bb .getANode ( ) = cfn
164
- or
165
- exists ( BasicBlock mid |
166
- this .reachesBasicBlock ( child , cfn , mid ) and
167
- bb = mid .getAPredecessor ( ) and
168
- not mid .getANode ( ) .getNode ( ) = child
169
- )
170
- }
160
+ abstract predicate reachesBasicBlock ( AstNode child , CfgNode cfn , BasicBlock bb ) ;
171
161
172
162
/**
173
163
* Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn`
@@ -183,6 +173,44 @@ abstract private class ExprChildMapping extends Expr {
183
173
}
184
174
}
185
175
176
+ /**
177
+ * A class for mapping parent-child AST nodes to parent-child CFG nodes.
178
+ */
179
+ abstract private class ExprChildMapping extends Expr , ChildMapping {
180
+ pragma [ nomagic]
181
+ override predicate reachesBasicBlock ( AstNode child , CfgNode cfn , BasicBlock bb ) {
182
+ this .relevantChild ( child ) and
183
+ cfn = this .getAControlFlowNode ( ) and
184
+ bb .getANode ( ) = cfn
185
+ or
186
+ exists ( BasicBlock mid |
187
+ this .reachesBasicBlock ( child , cfn , mid ) and
188
+ bb = mid .getAPredecessor ( ) and
189
+ not mid .getANode ( ) .getNode ( ) = child
190
+ )
191
+ }
192
+ }
193
+
194
+ /**
195
+ * A class for mapping parent-child AST nodes to parent-child CFG nodes.
196
+ */
197
+ abstract private class NonExprChildMapping extends ChildMapping {
198
+ NonExprChildMapping ( ) { not this instanceof Expr }
199
+
200
+ pragma [ nomagic]
201
+ override predicate reachesBasicBlock ( AstNode child , CfgNode cfn , BasicBlock bb ) {
202
+ this .relevantChild ( child ) and
203
+ cfn .getNode ( ) = this and
204
+ bb .getANode ( ) = cfn
205
+ or
206
+ exists ( BasicBlock mid |
207
+ this .reachesBasicBlock ( child , cfn , mid ) and
208
+ bb = mid .getASuccessor ( ) and
209
+ not mid .getANode ( ) .getNode ( ) = child
210
+ )
211
+ }
212
+ }
213
+
186
214
/** Provides classes for control-flow nodes that wrap AST expressions. */
187
215
module ExprNodes {
188
216
private class LiteralChildMapping extends ExprChildMapping , Literal {
@@ -346,17 +374,17 @@ module ExprNodes {
346
374
final ExprCfgNode getBlock ( ) { e .hasCfgChild ( e .( MethodCall ) .getBlock ( ) , this , result ) }
347
375
}
348
376
349
- private class CaseExprChildMapping extends ExprChildMapping , CaseExpr {
350
- override predicate relevantChild ( AstNode e ) { e = this .getValue ( ) }
351
- }
352
-
353
377
/** A control-flow node that wraps a `MethodCall` AST expression. */
354
378
class MethodCallCfgNode extends CallCfgNode {
355
379
MethodCallCfgNode ( ) { super .getExpr ( ) instanceof MethodCall }
356
380
357
381
override MethodCall getExpr ( ) { result = super .getExpr ( ) }
358
382
}
359
383
384
+ private class CaseExprChildMapping extends ExprChildMapping , CaseExpr {
385
+ override predicate relevantChild ( AstNode e ) { e = this .getValue ( ) or e = this .getABranch ( ) }
386
+ }
387
+
360
388
/** A control-flow node that wraps a `CaseExpr` AST expression. */
361
389
class CaseExprCfgNode extends ExprCfgNode {
362
390
override CaseExprChildMapping e ;
@@ -365,6 +393,47 @@ module ExprNodes {
365
393
366
394
/** Gets the expression being compared, if any. */
367
395
final ExprCfgNode getValue ( ) { e .hasCfgChild ( e .getValue ( ) , this , result ) }
396
+
397
+ /**
398
+ * Gets the `n`th branch of this case expression, either a `when` clause, an `in` clause, or an `else` branch.
399
+ */
400
+ final AstCfgNode getBranch ( int n ) { e .hasCfgChild ( e .getBranch ( n ) , this , result ) }
401
+ }
402
+
403
+ private class InClauseChildMapping extends NonExprChildMapping , InClause {
404
+ override predicate relevantChild ( AstNode e ) {
405
+ e = this .getPattern ( ) or
406
+ e = this .getCondition ( ) or
407
+ e = this .getBody ( )
408
+ }
409
+ }
410
+
411
+ /** A control-flow node that wraps an `InClause` AST expression. */
412
+ class InClauseCfgNode extends AstCfgNode {
413
+ private InClauseChildMapping e ;
414
+
415
+ /**
416
+ * Gets the pattern in this `in`-clause.
417
+ */
418
+ final AstCfgNode getPattern ( ) { e .hasCfgChild ( e .getPattern ( ) , this , result ) }
419
+
420
+ /** Gets the pattern guard condition in this `in` clause, if any. */
421
+ final ExprCfgNode getCondition ( ) { e .hasCfgChild ( e .getCondition ( ) , this , result ) }
422
+
423
+ /** Gets the body of this `in`-clause. */
424
+ final ExprCfgNode getBody ( ) { e .hasCfgChild ( e .getBody ( ) , this , result ) }
425
+ }
426
+
427
+ private class WhenClauseChildMapping extends NonExprChildMapping , WhenClause {
428
+ override predicate relevantChild ( AstNode e ) { e = this .getBody ( ) }
429
+ }
430
+
431
+ /** A control-flow node that wraps a `WhenClause` AST expression. */
432
+ class WhenClauseCfgNode extends AstCfgNode {
433
+ private WhenClauseChildMapping e ;
434
+
435
+ /** Gets the body of this `when`-clause. */
436
+ final ExprCfgNode getBody ( ) { e .hasCfgChild ( e .getBody ( ) , this , result ) }
368
437
}
369
438
370
439
private class ConditionalExprChildMapping extends ExprChildMapping , ConditionalExpr {
0 commit comments