@@ -43,22 +43,59 @@ final class DataFlowCallable extends TDataFlowCallable {
4343}
4444
4545final class DataFlowCall extends TDataFlowCall {
46+ private CallExprBaseCfgNode call ;
47+
48+ DataFlowCall ( ) { this = TCall ( call ) }
49+
4650 /** Gets the underlying call in the CFG, if any. */
47- CallExprCfgNode asCallExprCfgNode ( ) { this = TNormalCall ( result ) }
51+ CallExprCfgNode asCallExprCfgNode ( ) { result = call }
4852
49- MethodCallExprCfgNode asMethodCallExprCfgNode ( ) { this = TMethodCall ( result ) }
53+ MethodCallExprCfgNode asMethodCallExprCfgNode ( ) { result = call }
5054
51- CallExprBaseCfgNode asExprCfgNode ( ) {
52- result = this .asCallExprCfgNode ( ) or result = this .asMethodCallExprCfgNode ( )
53- }
55+ CallExprBaseCfgNode asCallBaseExprCfgNode ( ) { result = call }
5456
5557 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 ( )
5784 }
5885
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+ }
6092
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 ( )
6299}
63100
64101module Node {
@@ -93,11 +130,6 @@ module Node {
93130 * Gets this node's underlying SSA definition, if any.
94131 */
95132 Ssa:: Definition asDefinition ( ) { none ( ) }
96-
97- /**
98- * Gets the parameter that corresponds to this node, if any.
99- */
100- Param asParameter ( ) { none ( ) }
101133 }
102134
103135 /** A node type that is not implemented. */
@@ -111,7 +143,7 @@ module Node {
111143 override Location getLocation ( ) { none ( ) }
112144 }
113145
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. */
115147 abstract class AstCfgFlowNode extends Node {
116148 AstCfgNode n ;
117149
@@ -145,24 +177,37 @@ module Node {
145177
146178 PatNode ( ) { this = TPatNode ( n ) }
147179
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 }
150182 }
151183
184+ abstract class ParameterNode extends AstCfgFlowNode { }
185+
152186 /**
153187 * The value of a parameter at function entry, viewed as a node in a data
154188 * flow graph.
155189 */
156- final class ParameterNode extends AstCfgFlowNode , TParameterNode {
190+ final class NormalParameterNode extends ParameterNode , TParameterNode {
157191 override ParamCfgNode n ;
158192
159- ParameterNode ( ) { this = TParameterNode ( n ) }
193+ NormalParameterNode ( ) { this = TParameterNode ( n ) }
160194
161195 /** Gets the parameter in the CFG that this node corresponds to. */
162196 ParamCfgNode getParameter ( ) { result = n }
163197 }
164198
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+ }
166211
167212 /** An SSA node. */
168213 class SsaNode extends Node , TSsaNode {
@@ -185,7 +230,10 @@ module Node {
185230
186231 /** A data flow node that represents a value returned by a callable. */
187232 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+ }
189237
190238 ReturnKind getKind ( ) { any ( ) }
191239 }
@@ -197,10 +245,10 @@ module Node {
197245 }
198246
199247 final private class ExprOutNode extends ExprNode , OutNode {
200- ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprCfgNode }
248+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprBaseCfgNode }
201249
202250 /** 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 ( ) }
204252 }
205253
206254 /**
@@ -214,9 +262,19 @@ module Node {
214262 * Nodes corresponding to AST elements, for example `ExprNode`, usually refer
215263 * to the value before the update.
216264 */
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+
218270 /** 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 ( ) }
220278 }
221279
222280 final class CastNode = NaNode ;
@@ -226,25 +284,27 @@ final class Node = Node::Node;
226284
227285/** Provides logic related to SSA. */
228286module SsaFlow {
229- private module Impl = SsaImpl:: DataFlowIntegration;
287+ private module SsaFlow = SsaImpl:: DataFlowIntegration;
230288
231- private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) { result .getParameter ( ) = p }
289+ private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) {
290+ result .( Node:: NormalParameterNode ) .getParameter ( ) = p
291+ }
232292
233293 /** Converts a control flow node into an SSA control flow node. */
234- Impl :: Node asNode ( Node n ) {
294+ SsaFlow :: Node asNode ( Node n ) {
235295 n = TSsaNode ( result )
236296 or
237- result .( Impl :: ExprNode ) .getExpr ( ) = n .asExpr ( )
297+ result .( SsaFlow :: ExprNode ) .getExpr ( ) = n .asExpr ( )
238298 or
239- n = toParameterNode ( result .( Impl :: ParameterNode ) .getParameter ( ) )
299+ n = toParameterNode ( result .( SsaFlow :: ParameterNode ) .getParameter ( ) )
240300 }
241301
242302 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 )
244304 }
245305
246306 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 ) )
248308 }
249309}
250310
@@ -276,6 +336,8 @@ module LocalFlow {
276336 nodeFrom .( Node:: AstCfgFlowNode ) .getCfgNode ( ) =
277337 nodeTo .( Node:: SsaNode ) .getDefinitionExt ( ) .( Ssa:: WriteDefinition ) .getControlFlowNode ( )
278338 or
339+ nodeFrom .( Node:: NormalParameterNode ) .getParameter ( ) .getPat ( ) = nodeTo .( Node:: PatNode ) .getPat ( )
340+ or
279341 SsaFlow:: localFlowStep ( _, nodeFrom , nodeTo , _)
280342 or
281343 exists ( AssignmentExprCfgNode a |
@@ -291,6 +353,8 @@ private class ReturnKindAlias = ReturnKind;
291353
292354private class DataFlowCallAlias = DataFlowCall ;
293355
356+ private class ParameterPositionAlias = ParameterPosition ;
357+
294358module RustDataFlow implements InputSig< Location > {
295359 /**
296360 * An element, viewed as a node in a data flow graph. Either an expression
@@ -310,9 +374,15 @@ module RustDataFlow implements InputSig<Location> {
310374
311375 final class CastNode = Node:: NaNode ;
312376
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+ }
314381
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+ }
316386
317387 DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node .getEnclosingCallable ( ) }
318388
@@ -335,10 +405,9 @@ module RustDataFlow implements InputSig<Location> {
335405 DataFlowCallable viableCallable ( DataFlowCall c ) {
336406 exists ( Function f , string name | result .asCfgScope ( ) = f and name = f .getName ( ) .toString ( ) |
337407 if f .getParamList ( ) .hasSelfParam ( )
338- then name = c .asMethodCallExprCfgNode ( ) .getMethodCallExpr ( ) . getNameRef ( ) .getText ( )
408+ then name = c .asMethodCallExprCfgNode ( ) .getNameRef ( ) .getText ( )
339409 else
340- name =
341- c .asCallExprCfgNode ( ) .getCallExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
410+ name = c .asCallExprCfgNode ( ) .getExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
342411 )
343412 }
344413
@@ -377,19 +446,15 @@ module RustDataFlow implements InputSig<Location> {
377446
378447 ContentApprox getContentApprox ( Content c ) { any ( ) }
379448
380- class ParameterPosition extends string {
381- ParameterPosition ( ) { this = "pos" }
382- }
449+ class ParameterPosition = ParameterPositionAlias ;
383450
384- class ArgumentPosition extends string {
385- ArgumentPosition ( ) { this = "pos" }
386- }
451+ class ArgumentPosition = ParameterPosition ;
387452
388453 /**
389454 * Holds if the parameter position `ppos` matches the argument position
390455 * `apos`.
391456 */
392- predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { none ( ) }
457+ predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { ppos = apos }
393458
394459 /**
395460 * Holds if there is a simple local flow step from `node1` to `node2`. These
@@ -497,13 +562,13 @@ private module Cached {
497562 newtype TNode =
498563 TExprNode ( ExprCfgNode n ) or
499564 TParameterNode ( ParamCfgNode p ) or
565+ TSelfParameterNode ( SelfParamCfgNode p ) or
500566 TPatNode ( PatCfgNode p ) or
567+ TArgumentPostUpdateNode ( ExprCfgNode e ) { isArgumentForCall ( e , _, _) } or
501568 TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
502569
503570 cached
504- newtype TDataFlowCall =
505- TNormalCall ( CallExprCfgNode c ) or
506- TMethodCall ( MethodCallExprCfgNode c )
571+ newtype TDataFlowCall = TCall ( CallExprBaseCfgNode c )
507572
508573 cached
509574 newtype TOptionalContentSet =
@@ -521,6 +586,13 @@ private module Cached {
521586 predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
522587 LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
523588 }
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 ( )
524596}
525597
526598import Cached
0 commit comments