@@ -72,8 +72,25 @@ abstract private class ChildMapping extends Ast {
7272 */
7373 abstract predicate relevantChild ( Ast child ) ;
7474
75+ /**
76+ * Holds if `child` appears before its parent in the control-flow graph.
77+ * This always holds for expressions, and _almost_ never for statements.
78+ */
79+ abstract predicate precedesParent ( Ast child ) ;
80+
7581 pragma [ nomagic]
76- abstract predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) ;
82+ final predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) {
83+ this .relevantChild ( child ) and
84+ cfn .getAstNode ( ) = this and
85+ bb .getANode ( ) = cfn
86+ or
87+ exists ( BasicBlock mid |
88+ this .reachesBasicBlock ( child , cfn , mid ) and
89+ not mid .getANode ( ) .getAstNode ( ) = child
90+ |
91+ if this .precedesParent ( child ) then bb = mid .getAPredecessor ( ) else bb = mid .getASuccessor ( )
92+ )
93+ }
7794
7895 /**
7996 * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn`
@@ -93,18 +110,7 @@ abstract private class ChildMapping extends Ast {
93110 * A class for mapping parent-child AST nodes to parent-child CFG nodes.
94111 */
95112abstract private class ExprChildMapping extends Expr , ChildMapping {
96- pragma [ nomagic]
97- override predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) {
98- this .relevantChild ( child ) and
99- cfn .getAstNode ( ) = this and
100- bb .getANode ( ) = cfn
101- or
102- exists ( BasicBlock mid |
103- this .reachesBasicBlock ( child , cfn , mid ) and
104- bb = mid .getAPredecessor ( ) and
105- not mid .getANode ( ) .getAstNode ( ) = child
106- )
107- }
113+ final override predicate precedesParent ( Ast child ) { this .relevantChild ( child ) }
108114}
109115
110116/**
@@ -113,18 +119,7 @@ abstract private class ExprChildMapping extends Expr, ChildMapping {
113119abstract private class NonExprChildMapping extends ChildMapping {
114120 NonExprChildMapping ( ) { not this instanceof Expr }
115121
116- pragma [ nomagic]
117- override predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) {
118- this .relevantChild ( child ) and
119- cfn .getAstNode ( ) = this and
120- bb .getANode ( ) = cfn
121- or
122- exists ( BasicBlock mid |
123- this .reachesBasicBlock ( child , cfn , mid ) and
124- bb = mid .getASuccessor ( ) and
125- not mid .getANode ( ) .getAstNode ( ) = child
126- )
127- }
122+ override predicate precedesParent ( Ast child ) { none ( ) } // this is not final because it is overriden by ForEachStmt
128123}
129124
130125private class AttributeBaseChildMapping extends NonExprChildMapping , AttributeBase {
@@ -1208,7 +1203,7 @@ module StmtNodes {
12081203 StmtCfgNode getBody ( ) { s .hasCfgChild ( s .getBody ( ) , this , result ) }
12091204 }
12101205
1211- private class LoopStmtChildMapping extends NonExprChildMapping , LoopStmt {
1206+ abstract private class LoopStmtChildMapping extends ChildMapping , LoopStmt {
12121207 override predicate relevantChild ( Ast child ) { child = this .getBody ( ) }
12131208 }
12141209
@@ -1222,7 +1217,9 @@ module StmtNodes {
12221217 StmtCfgNode getBody ( ) { s .hasCfgChild ( s .getBody ( ) , this , result ) }
12231218 }
12241219
1225- private class DoUntilStmtChildMapping extends LoopStmtChildMapping , DoUntilStmt {
1220+ private class DoUntilStmtChildMapping extends LoopStmtChildMapping , NonExprChildMapping ,
1221+ DoUntilStmt
1222+ {
12261223 override predicate relevantChild ( Ast child ) {
12271224 child = this .getCondition ( ) or super .relevantChild ( child )
12281225 }
@@ -1238,7 +1235,9 @@ module StmtNodes {
12381235 ExprCfgNode getCondition ( ) { s .hasCfgChild ( s .getCondition ( ) , this , result ) }
12391236 }
12401237
1241- private class DoWhileStmtChildMapping extends LoopStmtChildMapping , DoWhileStmt {
1238+ private class DoWhileStmtChildMapping extends LoopStmtChildMapping , NonExprChildMapping ,
1239+ DoWhileStmt
1240+ {
12421241 override predicate relevantChild ( Ast child ) {
12431242 child = this .getCondition ( ) or super .relevantChild ( child )
12441243 }
@@ -1300,10 +1299,14 @@ module StmtNodes {
13001299 ExprCfgNode getHashTableExpr ( ) { s .hasCfgChild ( s .getHashTableExpr ( ) , this , result ) }
13011300 }
13021301
1303- private class ForEachStmtChildMapping extends LoopStmtChildMapping , ForEachStmt {
1302+ private class ForEachStmtChildMapping extends LoopStmtChildMapping , NonExprChildMapping ,
1303+ ForEachStmt
1304+ {
13041305 override predicate relevantChild ( Ast child ) {
13051306 child = this .getVarAccess ( ) or child = this .getIterableExpr ( ) or super .relevantChild ( child )
13061307 }
1308+
1309+ override predicate precedesParent ( Ast child ) { child = this .getIterableExpr ( ) }
13071310 }
13081311
13091312 class ForEachStmtCfgNode extends LoopStmtCfgNode {
@@ -1313,12 +1316,12 @@ module StmtNodes {
13131316
13141317 override ForEachStmt getStmt ( ) { result = s }
13151318
1316- ExprCfgNode getVarAccess ( ) { s .hasCfgChild ( s .getVarAccess ( ) , this , result ) }
1319+ ExprNodes :: VarAccessCfgNode getVarAccess ( ) { s .hasCfgChild ( s .getVarAccess ( ) , this , result ) }
13171320
13181321 ExprCfgNode getIterableExpr ( ) { s .hasCfgChild ( s .getIterableExpr ( ) , this , result ) }
13191322 }
13201323
1321- private class ForStmtChildMapping extends LoopStmtChildMapping , ForStmt {
1324+ private class ForStmtChildMapping extends LoopStmtChildMapping , NonExprChildMapping , ForStmt {
13221325 override predicate relevantChild ( Ast child ) {
13231326 child = this .getInitializer ( ) or
13241327 child = this .getCondition ( ) or
@@ -1476,7 +1479,7 @@ module StmtNodes {
14761479 override UsingStmt getStmt ( ) { result = s }
14771480 }
14781481
1479- private class WhileStmtChildMapping extends LoopStmtChildMapping , WhileStmt {
1482+ private class WhileStmtChildMapping extends LoopStmtChildMapping , NonExprChildMapping , WhileStmt {
14801483 override predicate relevantChild ( Ast child ) {
14811484 child = this .getCondition ( ) or
14821485 super .relevantChild ( child )
0 commit comments