@@ -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 PositionalParameterNode extends ParameterNode , TParameterNode {
157
191
override ParamCfgNode n ;
158
192
159
- ParameterNode ( ) { this = TParameterNode ( n ) }
193
+ PositionalParameterNode ( ) { 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,7 @@ 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 ( ) { this .getCfgNode ( ) .getASuccessor ( ) instanceof AnnotatedExitCfgNode }
189
234
190
235
ReturnKind getKind ( ) { any ( ) }
191
236
}
@@ -197,10 +242,10 @@ module Node {
197
242
}
198
243
199
244
final private class ExprOutNode extends ExprNode , OutNode {
200
- ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprCfgNode }
245
+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprBaseCfgNode }
201
246
202
247
/** Gets the underlying call CFG node that includes this out node. */
203
- override DataFlowCall getCall ( ) { result .asExprCfgNode ( ) = this .getCfgNode ( ) }
248
+ override DataFlowCall getCall ( ) { result .asCallBaseExprCfgNode ( ) = this .getCfgNode ( ) }
204
249
}
205
250
206
251
/**
@@ -214,9 +259,19 @@ module Node {
214
259
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
215
260
* to the value before the update.
216
261
*/
217
- final class PostUpdateNode extends Node:: NaNode {
262
+ final class PostUpdateNode extends Node , TArgumentPostUpdateNode {
263
+ private ExprCfgNode n ;
264
+
265
+ PostUpdateNode ( ) { this = TArgumentPostUpdateNode ( n ) }
266
+
218
267
/** Gets the node before the state update. */
219
- Node getPreUpdateNode ( ) { none ( ) }
268
+ Node getPreUpdateNode ( ) { result = TExprNode ( n ) }
269
+
270
+ final override CfgScope getCfgScope ( ) { result = n .getScope ( ) }
271
+
272
+ final override Location getLocation ( ) { result = n .getLocation ( ) }
273
+
274
+ final override string toString ( ) { result = n .toString ( ) }
220
275
}
221
276
222
277
final class CastNode = NaNode ;
@@ -226,25 +281,27 @@ final class Node = Node::Node;
226
281
227
282
/** Provides logic related to SSA. */
228
283
module SsaFlow {
229
- private module Impl = SsaImpl:: DataFlowIntegration;
284
+ private module SsaFlow = SsaImpl:: DataFlowIntegration;
230
285
231
- private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) { result .getParameter ( ) = p }
286
+ private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) {
287
+ result .( Node:: PositionalParameterNode ) .getParameter ( ) = p
288
+ }
232
289
233
290
/** Converts a control flow node into an SSA control flow node. */
234
- Impl :: Node asNode ( Node n ) {
291
+ SsaFlow :: Node asNode ( Node n ) {
235
292
n = TSsaNode ( result )
236
293
or
237
- result .( Impl :: ExprNode ) .getExpr ( ) = n .asExpr ( )
294
+ result .( SsaFlow :: ExprNode ) .getExpr ( ) = n .asExpr ( )
238
295
or
239
- n = toParameterNode ( result .( Impl :: ParameterNode ) .getParameter ( ) )
296
+ n = toParameterNode ( result .( SsaFlow :: ParameterNode ) .getParameter ( ) )
240
297
}
241
298
242
299
predicate localFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo , boolean isUseStep ) {
243
- Impl :: localFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) , isUseStep )
300
+ SsaFlow :: localFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) , isUseStep )
244
301
}
245
302
246
303
predicate localMustFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
247
- Impl :: localMustFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) )
304
+ SsaFlow :: localMustFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) )
248
305
}
249
306
}
250
307
@@ -276,6 +333,9 @@ module LocalFlow {
276
333
nodeFrom .( Node:: AstCfgFlowNode ) .getCfgNode ( ) =
277
334
nodeTo .( Node:: SsaNode ) .getDefinitionExt ( ) .( Ssa:: WriteDefinition ) .getControlFlowNode ( )
278
335
or
336
+ nodeFrom .( Node:: PositionalParameterNode ) .getParameter ( ) .getPat ( ) =
337
+ nodeTo .( Node:: PatNode ) .getPat ( )
338
+ or
279
339
SsaFlow:: localFlowStep ( _, nodeFrom , nodeTo , _)
280
340
or
281
341
exists ( AssignmentExprCfgNode a |
@@ -291,6 +351,8 @@ private class ReturnKindAlias = ReturnKind;
291
351
292
352
private class DataFlowCallAlias = DataFlowCall ;
293
353
354
+ private class ParameterPositionAlias = ParameterPosition ;
355
+
294
356
module RustDataFlow implements InputSig< Location > {
295
357
/**
296
358
* An element, viewed as a node in a data flow graph. Either an expression
@@ -310,9 +372,15 @@ module RustDataFlow implements InputSig<Location> {
310
372
311
373
final class CastNode = Node:: NaNode ;
312
374
313
- predicate isParameterNode ( ParameterNode p , DataFlowCallable c , ParameterPosition pos ) { none ( ) }
375
+ /** Holds if `p` is a parameter of `c` at the position `pos`. */
376
+ predicate isParameterNode ( ParameterNode p , DataFlowCallable c , ParameterPosition pos ) {
377
+ p .getCfgNode ( ) .getAstNode ( ) = pos .getParameterIn ( c .asCfgScope ( ) .( Callable ) .getParamList ( ) )
378
+ }
314
379
315
- predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) { none ( ) }
380
+ /** Holds if `n` is an argument of `c` at the position `pos`. */
381
+ predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) {
382
+ isArgumentForCall ( n .getCfgNode ( ) , call .asCallBaseExprCfgNode ( ) , pos )
383
+ }
316
384
317
385
DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node .getEnclosingCallable ( ) }
318
386
@@ -335,10 +403,9 @@ module RustDataFlow implements InputSig<Location> {
335
403
DataFlowCallable viableCallable ( DataFlowCall c ) {
336
404
exists ( Function f , string name | result .asCfgScope ( ) = f and name = f .getName ( ) .toString ( ) |
337
405
if f .getParamList ( ) .hasSelfParam ( )
338
- then name = c .asMethodCallExprCfgNode ( ) .getMethodCallExpr ( ) . getNameRef ( ) .getText ( )
406
+ then name = c .asMethodCallExprCfgNode ( ) .getNameRef ( ) .getText ( )
339
407
else
340
- name =
341
- c .asCallExprCfgNode ( ) .getCallExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
408
+ name = c .asCallExprCfgNode ( ) .getExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
342
409
)
343
410
}
344
411
@@ -377,19 +444,15 @@ module RustDataFlow implements InputSig<Location> {
377
444
378
445
ContentApprox getContentApprox ( Content c ) { any ( ) }
379
446
380
- class ParameterPosition extends string {
381
- ParameterPosition ( ) { this = "pos" }
382
- }
447
+ class ParameterPosition = ParameterPositionAlias ;
383
448
384
- class ArgumentPosition extends string {
385
- ArgumentPosition ( ) { this = "pos" }
386
- }
449
+ class ArgumentPosition = ParameterPosition ;
387
450
388
451
/**
389
452
* Holds if the parameter position `ppos` matches the argument position
390
453
* `apos`.
391
454
*/
392
- predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { none ( ) }
455
+ predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { ppos = apos }
393
456
394
457
/**
395
458
* Holds if there is a simple local flow step from `node1` to `node2`. These
@@ -497,13 +560,13 @@ private module Cached {
497
560
newtype TNode =
498
561
TExprNode ( ExprCfgNode n ) or
499
562
TParameterNode ( ParamCfgNode p ) or
563
+ TSelfParameterNode ( SelfParamCfgNode p ) or
500
564
TPatNode ( PatCfgNode p ) or
565
+ TArgumentPostUpdateNode ( ExprCfgNode e ) { isArgumentForCall ( e , _, _) } or
501
566
TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
502
567
503
568
cached
504
- newtype TDataFlowCall =
505
- TNormalCall ( CallExprCfgNode c ) or
506
- TMethodCall ( MethodCallExprCfgNode c )
569
+ newtype TDataFlowCall = TCall ( CallExprBaseCfgNode c )
507
570
508
571
cached
509
572
newtype TOptionalContentSet =
@@ -521,6 +584,13 @@ private module Cached {
521
584
predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
522
585
LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
523
586
}
587
+
588
+ cached
589
+ newtype TParameterPosition =
590
+ TPositionalParameterPosition ( int i ) {
591
+ i in [ 0 .. max ( [ any ( ParamList l ) .getNumberOfParams ( ) , any ( ArgList l ) .getNumberOfArgs ( ) ] ) - 1 ]
592
+ } or
593
+ TSelfParameterPosition ( )
524
594
}
525
595
526
596
import Cached
0 commit comments