@@ -46,18 +46,19 @@ module LocalFlow {
46
46
)
47
47
}
48
48
49
+ /** Gets the SSA definition node corresponding to parameter `p`. */
50
+ SsaDefinitionNode getParameterDefNode ( NamedParameter p ) {
51
+ exists ( BasicBlock bb , int i |
52
+ bb .getNode ( i ) .getNode ( ) = p .getDefiningAccess ( ) and
53
+ result .getDefinition ( ) .definesAt ( _, bb , i )
54
+ )
55
+ }
56
+
49
57
/**
50
58
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
51
59
* SSA definition `def`.
52
60
*/
53
61
predicate localSsaFlowStep ( Ssa:: Definition def , Node nodeFrom , Node nodeTo ) {
54
- // Flow from parameter into SSA definition
55
- exists ( BasicBlock bb , int i |
56
- bb .getNode ( i ) .getNode ( ) =
57
- nodeFrom .( ParameterNode ) .getParameter ( ) .( NamedParameter ) .getDefiningAccess ( ) and
58
- nodeTo .( SsaDefinitionNode ) .getDefinition ( ) .definesAt ( _, bb , i )
59
- )
60
- or
61
62
// Flow from assignment into SSA definition
62
63
def .( Ssa:: WriteDefinition ) .assigns ( nodeFrom .asExpr ( ) ) and
63
64
nodeTo .( SsaDefinitionNode ) .getDefinition ( ) = def
@@ -145,19 +146,14 @@ private module Cached {
145
146
class TParameterNode =
146
147
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or TSummaryParameterNode ;
147
148
148
- /**
149
- * This is the local flow predicate that is shared between local data flow
150
- * and global data flow.
151
- */
152
- cached
153
- predicate simpleLocalFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
154
- LocalFlow:: localSsaFlowStep ( _, nodeFrom , nodeTo )
149
+ private predicate defaultValueFlow ( NamedParameter p , ExprNode e ) {
150
+ p .( OptionalParameter ) .getDefaultValue ( ) = e .getExprNode ( ) .getExpr ( )
155
151
or
156
- nodeTo . ( ParameterNode ) . getParameter ( ) . ( OptionalParameter ) . getDefaultValue ( ) =
157
- nodeFrom . asExpr ( ) . getExpr ( )
158
- or
159
- nodeTo . ( ParameterNode ) . getParameter ( ) . ( KeywordParameter ) . getDefaultValue ( ) =
160
- nodeFrom . asExpr ( ) . getExpr ( )
152
+ p . ( KeywordParameter ) . getDefaultValue ( ) = e . getExprNode ( ) . getExpr ( )
153
+ }
154
+
155
+ private predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
156
+ LocalFlow :: localSsaFlowStep ( _ , nodeFrom , nodeTo )
161
157
or
162
158
nodeFrom .( SelfParameterNode ) .getMethod ( ) = nodeTo .asExpr ( ) .getExpr ( ) .getEnclosingCallable ( ) and
163
159
nodeTo .asExpr ( ) .getExpr ( ) instanceof Self
@@ -194,19 +190,46 @@ private module Cached {
194
190
195
191
/**
196
192
* This is the local flow predicate that is used as a building block in global
197
- * data flow. It excludes SSA flow through instance fields, as flow through fields
198
- * is handled by the global data-flow library, but includes various other steps
199
- * that are only relevant for global flow.
193
+ * data flow.
200
194
*/
201
195
cached
202
196
predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
203
- simpleLocalFlowStepCommon ( nodeFrom , nodeTo )
197
+ localFlowStepCommon ( nodeFrom , nodeTo )
198
+ or
199
+ defaultValueFlow ( nodeTo .( ParameterNode ) .getParameter ( ) , nodeFrom )
200
+ or
201
+ nodeTo = LocalFlow:: getParameterDefNode ( nodeFrom .( ParameterNode ) .getParameter ( ) )
204
202
or
205
203
nodeTo .( SynthReturnNode ) .getAnInput ( ) = nodeFrom
206
204
or
207
205
FlowSummaryImpl:: Private:: Steps:: summaryLocalStep ( nodeFrom , nodeTo , true )
208
206
}
209
207
208
+ /** This is the local flow predicate that is exposed. */
209
+ cached
210
+ predicate localFlowStepImpl ( Node nodeFrom , Node nodeTo ) {
211
+ localFlowStepCommon ( nodeFrom , nodeTo )
212
+ or
213
+ defaultValueFlow ( nodeTo .( ParameterNode ) .getParameter ( ) , nodeFrom )
214
+ or
215
+ nodeTo = LocalFlow:: getParameterDefNode ( nodeFrom .( ParameterNode ) .getParameter ( ) )
216
+ or
217
+ // Simple flow through library code is included in the exposed local
218
+ // step relation, even though flow is technically inter-procedural
219
+ FlowSummaryImpl:: Private:: Steps:: summaryThroughStep ( nodeFrom , nodeTo , true )
220
+ }
221
+
222
+ /** This is the local flow predicate that is used in type tracking. */
223
+ cached
224
+ predicate localFlowStepTypeTracker ( Node nodeFrom , Node nodeTo ) {
225
+ localFlowStepCommon ( nodeFrom , nodeTo )
226
+ or
227
+ exists ( NamedParameter p |
228
+ defaultValueFlow ( p , nodeFrom ) and
229
+ nodeTo = LocalFlow:: getParameterDefNode ( p )
230
+ )
231
+ }
232
+
210
233
cached
211
234
predicate isLocalSourceNode ( Node n ) {
212
235
n instanceof ParameterNode
@@ -217,7 +240,7 @@ private module Cached {
217
240
// and we can remove this case.
218
241
n instanceof SelfArgumentNode
219
242
or
220
- not simpleLocalFlowStepCommon + ( any ( Node e |
243
+ not localFlowStepTypeTracker + ( any ( Node e |
221
244
e instanceof ExprNode
222
245
or
223
246
e instanceof ParameterNode
@@ -538,7 +561,7 @@ private module ReturnNodes {
538
561
539
562
SynthReturnNode ( ) { this = TSynthReturnNode ( scope , kind ) }
540
563
541
- /** Get a syntactic return node that flows into this synthetic node. */
564
+ /** Gets a syntactic return node that flows into this synthetic node. */
542
565
ReturningNode getAnInput ( ) {
543
566
result .( NodeImpl ) .getCfgScope ( ) = scope and
544
567
result .getKind ( ) = kind
0 commit comments