@@ -149,25 +149,15 @@ private AstNode desugar(AstNode n) {
149149/**
150150 * A class for mapping parent-child AST nodes to parent-child CFG nodes.
151151 */
152- abstract private class ExprChildMapping extends Expr {
152+ abstract private class ChildMapping extends AstNode {
153153 /**
154154 * Holds if `child` is a (possibly nested) child of this expression
155155 * for which we would like to find a matching CFG child.
156156 */
157157 abstract predicate relevantChild ( AstNode child ) ;
158158
159159 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 ) ;
171161
172162 /**
173163 * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn`
@@ -183,6 +173,44 @@ abstract private class ExprChildMapping extends Expr {
183173 }
184174}
185175
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+
186214/** Provides classes for control-flow nodes that wrap AST expressions. */
187215module ExprNodes {
188216 private class LiteralChildMapping extends ExprChildMapping , Literal {
@@ -346,17 +374,17 @@ module ExprNodes {
346374 final ExprCfgNode getBlock ( ) { e .hasCfgChild ( e .( MethodCall ) .getBlock ( ) , this , result ) }
347375 }
348376
349- private class CaseExprChildMapping extends ExprChildMapping , CaseExpr {
350- override predicate relevantChild ( AstNode e ) { e = this .getValue ( ) }
351- }
352-
353377 /** A control-flow node that wraps a `MethodCall` AST expression. */
354378 class MethodCallCfgNode extends CallCfgNode {
355379 MethodCallCfgNode ( ) { super .getExpr ( ) instanceof MethodCall }
356380
357381 override MethodCall getExpr ( ) { result = super .getExpr ( ) }
358382 }
359383
384+ private class CaseExprChildMapping extends ExprChildMapping , CaseExpr {
385+ override predicate relevantChild ( AstNode e ) { e = this .getValue ( ) or e = this .getABranch ( ) }
386+ }
387+
360388 /** A control-flow node that wraps a `CaseExpr` AST expression. */
361389 class CaseExprCfgNode extends ExprCfgNode {
362390 override CaseExprChildMapping e ;
@@ -365,6 +393,47 @@ module ExprNodes {
365393
366394 /** Gets the expression being compared, if any. */
367395 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 ) }
368437 }
369438
370439 private class ConditionalExprChildMapping extends ExprChildMapping , ConditionalExpr {
0 commit comments