@@ -60,16 +60,144 @@ class StmtCfgNode extends AstCfgNode {
60
60
Stmt getStmt ( ) { result = s }
61
61
}
62
62
63
+ /**
64
+ * A class for mapping parent-child AST nodes to parent-child CFG nodes.
65
+ */
66
+ abstract private class ChildMapping extends Ast {
67
+ /**
68
+ * Holds if `child` is a (possibly nested) child of this expression
69
+ * for which we would like to find a matching CFG child.
70
+ */
71
+ abstract predicate relevantChild ( Ast child ) ;
72
+
73
+ pragma [ nomagic]
74
+ abstract predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) ;
75
+
76
+ /**
77
+ * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn`
78
+ * is a control-flow node for this expression, and `cfnChild` is a control-flow
79
+ * node for `child`.
80
+ *
81
+ * The path never escapes the syntactic scope of this expression.
82
+ */
83
+ cached
84
+ predicate hasCfgChild ( Ast child , CfgNode cfn , CfgNode cfnChild ) {
85
+ this .reachesBasicBlock ( child , cfn , cfnChild .getBasicBlock ( ) ) and
86
+ cfnChild .getAstNode ( ) = child
87
+ }
88
+ }
89
+
90
+ /**
91
+ * A class for mapping parent-child AST nodes to parent-child CFG nodes.
92
+ */
93
+ abstract private class ExprChildMapping extends Expr , ChildMapping {
94
+ pragma [ nomagic]
95
+ override predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) {
96
+ this .relevantChild ( child ) and
97
+ cfn .getAstNode ( ) = this and
98
+ bb .getANode ( ) = cfn
99
+ or
100
+ exists ( BasicBlock mid |
101
+ this .reachesBasicBlock ( child , cfn , mid ) and
102
+ bb = mid .getAPredecessor ( ) and
103
+ not mid .getANode ( ) .getAstNode ( ) = child
104
+ )
105
+ }
106
+ }
107
+
108
+ /**
109
+ * A class for mapping parent-child AST nodes to parent-child CFG nodes.
110
+ */
111
+ abstract private class NonExprChildMapping extends ChildMapping {
112
+ NonExprChildMapping ( ) { not this instanceof Expr }
113
+
114
+ pragma [ nomagic]
115
+ override predicate reachesBasicBlock ( Ast child , CfgNode cfn , BasicBlock bb ) {
116
+ this .relevantChild ( child ) and
117
+ cfn .getAstNode ( ) = this and
118
+ bb .getANode ( ) = cfn
119
+ or
120
+ exists ( BasicBlock mid |
121
+ this .reachesBasicBlock ( child , cfn , mid ) and
122
+ bb = mid .getASuccessor ( ) and
123
+ not mid .getANode ( ) .getAstNode ( ) = child
124
+ )
125
+ }
126
+ }
127
+
63
128
/** Provides classes for control-flow nodes that wrap AST expressions. */
64
- module ExprNodes { }
129
+ module ExprNodes {
130
+ private class VarAccessChildMapping extends ExprChildMapping , VarAccess {
131
+ override predicate relevantChild ( Ast n ) { none ( ) }
132
+ }
133
+
134
+ class VarAccessCfgNode extends ExprCfgNode {
135
+ override string getAPrimaryQlClass ( ) { result = "VarAccessCfgNode" }
136
+
137
+ override VarAccessChildMapping e ;
138
+
139
+ override VarAccess getExpr ( ) { result = super .getExpr ( ) }
140
+ }
141
+
142
+ private class VarReadAccessChildMapping extends VarAccessChildMapping , VarReadAccess { }
143
+
144
+ class VarReadAccessCfgNode extends VarAccessCfgNode {
145
+ override string getAPrimaryQlClass ( ) { result = "VarReadAccessCfgNode" }
146
+
147
+ override VarReadAccessChildMapping e ;
148
+
149
+ override VarReadAccess getExpr ( ) { result = super .getExpr ( ) }
150
+ }
151
+
152
+ private class VarWriteAccessChildMapping extends VarAccessChildMapping , VarWriteAccess { }
153
+
154
+ class VariableWriteAccessCfgNode extends VarAccessCfgNode {
155
+ override string getAPrimaryQlClass ( ) { result = "VarWriteAccessCfgNode" }
156
+
157
+ override VarWriteAccessChildMapping e ;
158
+
159
+ override VarWriteAccess getExpr ( ) { result = super .getExpr ( ) }
160
+
161
+ Variable getVariable ( ) { result = e .getVariable ( ) }
162
+
163
+ predicate isExplicitWrite ( StmtNodes:: AssignStmtCfgNode assignment ) {
164
+ this = assignment .getLeftHandSide ( )
165
+ }
166
+ }
167
+ }
65
168
66
169
module StmtNodes {
170
+ private class CmdChildMapping extends NonExprChildMapping , Cmd {
171
+ override predicate relevantChild ( Ast n ) { n = this .getElement ( _) }
172
+ }
173
+
67
174
/** A control-flow node that wraps a `Cmd` AST expression. */
68
- class CallCfgNode extends StmtCfgNode {
69
- override string getAPrimaryQlClass ( ) { result = "CallCfgNode " }
175
+ class CmdCfgNode extends StmtCfgNode {
176
+ override string getAPrimaryQlClass ( ) { result = "CmdCfgNode " }
70
177
71
- override Cmd s ;
178
+ override CmdChildMapping s ;
72
179
73
180
override Cmd getStmt ( ) { result = super .getStmt ( ) }
74
181
}
182
+
183
+ private class AssignStmtChildMapping extends NonExprChildMapping , AssignStmt {
184
+ override predicate relevantChild ( Ast n ) {
185
+ n = this .getLeftHandSide ( ) or n = this .getRightHandSide ( )
186
+ }
187
+ }
188
+
189
+ /** A control-flow node that wraps an `AssignStmt` AST expression. */
190
+ class AssignStmtCfgNode extends StmtCfgNode {
191
+ override string getAPrimaryQlClass ( ) { result = "AssignCfgNode" }
192
+
193
+ override AssignStmtChildMapping s ;
194
+
195
+ override AssignStmt getStmt ( ) { result = super .getStmt ( ) }
196
+
197
+ /** Gets the LHS of this assignment. */
198
+ final ExprCfgNode getLeftHandSide ( ) { s .hasCfgChild ( s .getLeftHandSide ( ) , this , result ) }
199
+
200
+ /** Gets the RHS of this assignment. */
201
+ final StmtCfgNode getRightHandSide ( ) { s .hasCfgChild ( s .getRightHandSide ( ) , this , result ) }
202
+ }
75
203
}
0 commit comments