@@ -43,22 +43,59 @@ final class DataFlowCallable extends TDataFlowCallable {
43
43
}
44
44
45
45
final class DataFlowCall extends TDataFlowCall {
46
+ private CallExprBaseCfgNode call ;
47
+
48
+ DataFlowCall ( ) { this = TCall ( call ) }
49
+
46
50
/** Gets the underlying call in the CFG, if any. */
47
- CallExprCfgNode asCallExprCfgNode ( ) { this = TNormalCall ( result ) }
51
+ CallExprCfgNode asCallExprCfgNode ( ) { result = call }
48
52
49
- MethodCallExprCfgNode asMethodCallExprCfgNode ( ) { this = TMethodCall ( result ) }
53
+ MethodCallExprCfgNode asMethodCallExprCfgNode ( ) { result = call }
50
54
51
- CallExprBaseCfgNode asExprCfgNode ( ) {
52
- result = this .asCallExprCfgNode ( ) or result = this .asMethodCallExprCfgNode ( )
53
- }
55
+ CallExprBaseCfgNode asCallBaseExprCfgNode ( ) { result = call }
54
56
55
57
DataFlowCallable getEnclosingCallable ( ) {
56
- result = TCfgScope ( this .asExprCfgNode ( ) .getExpr ( ) .getEnclosingCfgScope ( ) )
58
+ result = TCfgScope ( call .getExpr ( ) .getEnclosingCfgScope ( ) )
59
+ }
60
+
61
+ string toString ( ) { result = this .asCallBaseExprCfgNode ( ) .toString ( ) }
62
+
63
+ Location getLocation ( ) { result = this .asCallBaseExprCfgNode ( ) .getLocation ( ) }
64
+ }
65
+
66
+ /**
67
+ * The position of a parameter or an argument in a function or call.
68
+ *
69
+ * As there is a 1-to-1 correspondence between parameter positions and
70
+ * arguments positions in Rust we use the same type for both.
71
+ */
72
+ final class ParameterPosition extends TParameterPosition {
73
+ /** Gets the underlying integer position, if any. */
74
+ int getPosition ( ) { this = TPositionalParameterPosition ( result ) }
75
+
76
+ /** Holds if this position represents the `self` position. */
77
+ predicate isSelf ( ) { this = TSelfParameterPosition ( ) }
78
+
79
+ /** Gets a textual representation of this position. */
80
+ string toString ( ) {
81
+ result = this .getPosition ( ) .toString ( )
82
+ or
83
+ result = "self" and this .isSelf ( )
57
84
}
58
85
59
- string toString ( ) { result = this .asExprCfgNode ( ) .toString ( ) }
86
+ AstNode getParameterIn ( ParamList ps ) {
87
+ result = ps .getParam ( this .getPosition ( ) )
88
+ or
89
+ result = ps .getSelfParam ( ) and this .isSelf ( )
90
+ }
91
+ }
60
92
61
- Location getLocation ( ) { result = this .asExprCfgNode ( ) .getLocation ( ) }
93
+ /** Holds if `arg` is an argument of `call` at the position `pos`. */
94
+ private predicate isArgumentForCall ( ExprCfgNode arg , CallExprBaseCfgNode call , ParameterPosition pos ) {
95
+ arg = call .getArgument ( pos .getPosition ( ) )
96
+ or
97
+ // The self argument in a method call.
98
+ arg = call .( MethodCallExprCfgNode ) .getReceiver ( ) and pos .isSelf ( )
62
99
}
63
100
64
101
module Node {
@@ -93,11 +130,6 @@ module Node {
93
130
* Gets this node's underlying SSA definition, if any.
94
131
*/
95
132
Ssa:: Definition asDefinition ( ) { none ( ) }
96
-
97
- /**
98
- * Gets the parameter that corresponds to this node, if any.
99
- */
100
- Param asParameter ( ) { none ( ) }
101
133
}
102
134
103
135
/** A node type that is not implemented. */
@@ -111,7 +143,7 @@ module Node {
111
143
override Location getLocation ( ) { none ( ) }
112
144
}
113
145
114
- /** A data flow node that corresponds to a CFG node for an AST node. */
146
+ /** A data flow node that corresponds directly to a CFG node for an AST node. */
115
147
abstract class AstCfgFlowNode extends Node {
116
148
AstCfgNode n ;
117
149
@@ -145,24 +177,37 @@ module Node {
145
177
146
178
PatNode ( ) { this = TPatNode ( n ) }
147
179
148
- /** Gets the `Pat ` in the AST that this node corresponds to. */
149
- Pat getPat ( ) { result = n . getPat ( ) }
180
+ /** Gets the `PatCfgNode ` in the CFG that this node corresponds to. */
181
+ PatCfgNode getPat ( ) { result = n }
150
182
}
151
183
184
+ abstract class ParameterNode extends AstCfgFlowNode { }
185
+
152
186
/**
153
187
* The value of a parameter at function entry, viewed as a node in a data
154
188
* flow graph.
155
189
*/
156
- final class ParameterNode extends AstCfgFlowNode , TParameterNode {
190
+ final class NormalParameterNode extends ParameterNode , TParameterNode {
157
191
override ParamCfgNode n ;
158
192
159
- ParameterNode ( ) { this = TParameterNode ( n ) }
193
+ NormalParameterNode ( ) { this = TParameterNode ( n ) }
160
194
161
195
/** Gets the parameter in the CFG that this node corresponds to. */
162
196
ParamCfgNode getParameter ( ) { result = n }
163
197
}
164
198
165
- final class ArgumentNode = NaNode ;
199
+ final class SelfParameterNode extends ParameterNode , TSelfParameterNode {
200
+ override SelfParamCfgNode n ;
201
+
202
+ SelfParameterNode ( ) { this = TSelfParameterNode ( n ) }
203
+
204
+ /** Gets the self parameter in the AST that this node corresponds to. */
205
+ SelfParamCfgNode getSelfParameter ( ) { result = n }
206
+ }
207
+
208
+ final class ArgumentNode extends ExprNode {
209
+ ArgumentNode ( ) { isArgumentForCall ( n , _, _) }
210
+ }
166
211
167
212
/** An SSA node. */
168
213
class SsaNode extends Node , TSsaNode {
@@ -185,7 +230,10 @@ module Node {
185
230
186
231
/** A data flow node that represents a value returned by a callable. */
187
232
final class ReturnNode extends ExprNode {
188
- ReturnNode ( ) { this .getCfgNode ( ) .getASuccessor ( ) instanceof ExitCfgNode }
233
+ ReturnNode ( ) {
234
+ this .getCfgNode ( ) .getASuccessor ( ) instanceof ExitCfgNode or
235
+ this .getCfgNode ( ) .getASuccessor ( ) instanceof AnnotatedExitCfgNode
236
+ }
189
237
190
238
ReturnKind getKind ( ) { any ( ) }
191
239
}
@@ -197,10 +245,10 @@ module Node {
197
245
}
198
246
199
247
final private class ExprOutNode extends ExprNode , OutNode {
200
- ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprCfgNode }
248
+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprBaseCfgNode }
201
249
202
250
/** Gets the underlying call CFG node that includes this out node. */
203
- override DataFlowCall getCall ( ) { result .asExprCfgNode ( ) = this .getCfgNode ( ) }
251
+ override DataFlowCall getCall ( ) { result .asCallBaseExprCfgNode ( ) = this .getCfgNode ( ) }
204
252
}
205
253
206
254
/**
@@ -214,9 +262,19 @@ module Node {
214
262
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
215
263
* to the value before the update.
216
264
*/
217
- final class PostUpdateNode extends Node:: NaNode {
265
+ final class PostUpdateNode extends Node , TArgumentPostUpdateNode {
266
+ private ExprCfgNode n ;
267
+
268
+ PostUpdateNode ( ) { this = TArgumentPostUpdateNode ( n ) }
269
+
218
270
/** Gets the node before the state update. */
219
- Node getPreUpdateNode ( ) { none ( ) }
271
+ Node getPreUpdateNode ( ) { result = TExprNode ( n ) }
272
+
273
+ final override CfgScope getCfgScope ( ) { result = n .getAstNode ( ) .getEnclosingCfgScope ( ) }
274
+
275
+ final override Location getLocation ( ) { result = n .getAstNode ( ) .getLocation ( ) }
276
+
277
+ final override string toString ( ) { result = n .getAstNode ( ) .toString ( ) }
220
278
}
221
279
222
280
final class CastNode = NaNode ;
@@ -226,25 +284,27 @@ final class Node = Node::Node;
226
284
227
285
/** Provides logic related to SSA. */
228
286
module SsaFlow {
229
- private module Impl = SsaImpl:: DataFlowIntegration;
287
+ private module SsaFlow = SsaImpl:: DataFlowIntegration;
230
288
231
- private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) { result .getParameter ( ) = p }
289
+ private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) {
290
+ result .( Node:: NormalParameterNode ) .getParameter ( ) = p
291
+ }
232
292
233
293
/** Converts a control flow node into an SSA control flow node. */
234
- Impl :: Node asNode ( Node n ) {
294
+ SsaFlow :: Node asNode ( Node n ) {
235
295
n = TSsaNode ( result )
236
296
or
237
- result .( Impl :: ExprNode ) .getExpr ( ) = n .asExpr ( )
297
+ result .( SsaFlow :: ExprNode ) .getExpr ( ) = n .asExpr ( )
238
298
or
239
- n = toParameterNode ( result .( Impl :: ParameterNode ) .getParameter ( ) )
299
+ n = toParameterNode ( result .( SsaFlow :: ParameterNode ) .getParameter ( ) )
240
300
}
241
301
242
302
predicate localFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo , boolean isUseStep ) {
243
- Impl :: localFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) , isUseStep )
303
+ SsaFlow :: localFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) , isUseStep )
244
304
}
245
305
246
306
predicate localMustFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
247
- Impl :: localMustFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) )
307
+ SsaFlow :: localMustFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) )
248
308
}
249
309
}
250
310
@@ -276,6 +336,8 @@ module LocalFlow {
276
336
nodeFrom .( Node:: AstCfgFlowNode ) .getCfgNode ( ) =
277
337
nodeTo .( Node:: SsaNode ) .getDefinitionExt ( ) .( Ssa:: WriteDefinition ) .getControlFlowNode ( )
278
338
or
339
+ nodeFrom .( Node:: NormalParameterNode ) .getParameter ( ) .getPat ( ) = nodeTo .( Node:: PatNode ) .getPat ( )
340
+ or
279
341
SsaFlow:: localFlowStep ( _, nodeFrom , nodeTo , _)
280
342
or
281
343
exists ( AssignmentExprCfgNode a |
@@ -291,6 +353,8 @@ private class ReturnKindAlias = ReturnKind;
291
353
292
354
private class DataFlowCallAlias = DataFlowCall ;
293
355
356
+ private class ParameterPositionAlias = ParameterPosition ;
357
+
294
358
module RustDataFlow implements InputSig< Location > {
295
359
/**
296
360
* An element, viewed as a node in a data flow graph. Either an expression
@@ -310,9 +374,15 @@ module RustDataFlow implements InputSig<Location> {
310
374
311
375
final class CastNode = Node:: NaNode ;
312
376
313
- predicate isParameterNode ( ParameterNode p , DataFlowCallable c , ParameterPosition pos ) { none ( ) }
377
+ /** Holds if `p` is a parameter of `c` at the position `pos`. */
378
+ predicate isParameterNode ( ParameterNode p , DataFlowCallable c , ParameterPosition pos ) {
379
+ p .getCfgNode ( ) .getAstNode ( ) = pos .getParameterIn ( c .asCfgScope ( ) .( Function ) .getParamList ( ) )
380
+ }
314
381
315
- predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) { none ( ) }
382
+ /** Holds if `n` is an argument of `c` at the position `pos`. */
383
+ predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) {
384
+ isArgumentForCall ( n .getCfgNode ( ) , call .asCallBaseExprCfgNode ( ) , pos )
385
+ }
316
386
317
387
DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node .getEnclosingCallable ( ) }
318
388
@@ -335,10 +405,9 @@ module RustDataFlow implements InputSig<Location> {
335
405
DataFlowCallable viableCallable ( DataFlowCall c ) {
336
406
exists ( Function f , string name | result .asCfgScope ( ) = f and name = f .getName ( ) .toString ( ) |
337
407
if f .getParamList ( ) .hasSelfParam ( )
338
- then name = c .asMethodCallExprCfgNode ( ) .getMethodCallExpr ( ) . getNameRef ( ) .getText ( )
408
+ then name = c .asMethodCallExprCfgNode ( ) .getNameRef ( ) .getText ( )
339
409
else
340
- name =
341
- c .asCallExprCfgNode ( ) .getCallExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
410
+ name = c .asCallExprCfgNode ( ) .getExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
342
411
)
343
412
}
344
413
@@ -377,19 +446,15 @@ module RustDataFlow implements InputSig<Location> {
377
446
378
447
ContentApprox getContentApprox ( Content c ) { any ( ) }
379
448
380
- class ParameterPosition extends string {
381
- ParameterPosition ( ) { this = "pos" }
382
- }
449
+ class ParameterPosition = ParameterPositionAlias ;
383
450
384
- class ArgumentPosition extends string {
385
- ArgumentPosition ( ) { this = "pos" }
386
- }
451
+ class ArgumentPosition = ParameterPosition ;
387
452
388
453
/**
389
454
* Holds if the parameter position `ppos` matches the argument position
390
455
* `apos`.
391
456
*/
392
- predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { none ( ) }
457
+ predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { ppos = apos }
393
458
394
459
/**
395
460
* Holds if there is a simple local flow step from `node1` to `node2`. These
@@ -497,13 +562,13 @@ private module Cached {
497
562
newtype TNode =
498
563
TExprNode ( ExprCfgNode n ) or
499
564
TParameterNode ( ParamCfgNode p ) or
565
+ TSelfParameterNode ( SelfParamCfgNode p ) or
500
566
TPatNode ( PatCfgNode p ) or
567
+ TArgumentPostUpdateNode ( ExprCfgNode e ) { isArgumentForCall ( e , _, _) } or
501
568
TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
502
569
503
570
cached
504
- newtype TDataFlowCall =
505
- TNormalCall ( CallExprCfgNode c ) or
506
- TMethodCall ( MethodCallExprCfgNode c )
571
+ newtype TDataFlowCall = TCall ( CallExprBaseCfgNode c )
507
572
508
573
cached
509
574
newtype TOptionalContentSet =
@@ -521,6 +586,13 @@ private module Cached {
521
586
predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
522
587
LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
523
588
}
589
+
590
+ cached
591
+ newtype TParameterPosition =
592
+ TPositionalParameterPosition ( int i ) {
593
+ exists ( any ( ParamList l ) .getParam ( i ) ) or exists ( any ( ArgList l ) .getArg ( i ) )
594
+ } or
595
+ TSelfParameterPosition ( )
524
596
}
525
597
526
598
import Cached
0 commit comments