@@ -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 PositionalParameterNode extends ParameterNode , TParameterNode {
157191 override ParamCfgNode n ;
158192
159- ParameterNode ( ) { this = TParameterNode ( n ) }
193+ PositionalParameterNode ( ) { 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,7 @@ 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 ( ) { this .getCfgNode ( ) .getASuccessor ( ) instanceof AnnotatedExitCfgNode }
189234
190235 ReturnKind getKind ( ) { any ( ) }
191236 }
@@ -197,10 +242,10 @@ module Node {
197242 }
198243
199244 final private class ExprOutNode extends ExprNode , OutNode {
200- ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprCfgNode }
245+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExprBaseCfgNode }
201246
202247 /** 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 ( ) }
204249 }
205250
206251 /**
@@ -214,9 +259,19 @@ module Node {
214259 * Nodes corresponding to AST elements, for example `ExprNode`, usually refer
215260 * to the value before the update.
216261 */
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+
218267 /** 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 ( ) }
220275 }
221276
222277 final class CastNode = NaNode ;
@@ -226,25 +281,27 @@ final class Node = Node::Node;
226281
227282/** Provides logic related to SSA. */
228283module SsaFlow {
229- private module Impl = SsaImpl:: DataFlowIntegration;
284+ private module SsaFlow = SsaImpl:: DataFlowIntegration;
230285
231- private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) { result .getParameter ( ) = p }
286+ private Node:: ParameterNode toParameterNode ( ParamCfgNode p ) {
287+ result .( Node:: PositionalParameterNode ) .getParameter ( ) = p
288+ }
232289
233290 /** Converts a control flow node into an SSA control flow node. */
234- Impl :: Node asNode ( Node n ) {
291+ SsaFlow :: Node asNode ( Node n ) {
235292 n = TSsaNode ( result )
236293 or
237- result .( Impl :: ExprNode ) .getExpr ( ) = n .asExpr ( )
294+ result .( SsaFlow :: ExprNode ) .getExpr ( ) = n .asExpr ( )
238295 or
239- n = toParameterNode ( result .( Impl :: ParameterNode ) .getParameter ( ) )
296+ n = toParameterNode ( result .( SsaFlow :: ParameterNode ) .getParameter ( ) )
240297 }
241298
242299 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 )
244301 }
245302
246303 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 ) )
248305 }
249306}
250307
@@ -276,6 +333,9 @@ module LocalFlow {
276333 nodeFrom .( Node:: AstCfgFlowNode ) .getCfgNode ( ) =
277334 nodeTo .( Node:: SsaNode ) .getDefinitionExt ( ) .( Ssa:: WriteDefinition ) .getControlFlowNode ( )
278335 or
336+ nodeFrom .( Node:: PositionalParameterNode ) .getParameter ( ) .getPat ( ) =
337+ nodeTo .( Node:: PatNode ) .getPat ( )
338+ or
279339 SsaFlow:: localFlowStep ( _, nodeFrom , nodeTo , _)
280340 or
281341 exists ( AssignmentExprCfgNode a |
@@ -291,6 +351,8 @@ private class ReturnKindAlias = ReturnKind;
291351
292352private class DataFlowCallAlias = DataFlowCall ;
293353
354+ private class ParameterPositionAlias = ParameterPosition ;
355+
294356module RustDataFlow implements InputSig< Location > {
295357 /**
296358 * An element, viewed as a node in a data flow graph. Either an expression
@@ -310,9 +372,15 @@ module RustDataFlow implements InputSig<Location> {
310372
311373 final class CastNode = Node:: NaNode ;
312374
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+ }
314379
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+ }
316384
317385 DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node .getEnclosingCallable ( ) }
318386
@@ -335,10 +403,9 @@ module RustDataFlow implements InputSig<Location> {
335403 DataFlowCallable viableCallable ( DataFlowCall c ) {
336404 exists ( Function f , string name | result .asCfgScope ( ) = f and name = f .getName ( ) .toString ( ) |
337405 if f .getParamList ( ) .hasSelfParam ( )
338- then name = c .asMethodCallExprCfgNode ( ) .getMethodCallExpr ( ) . getNameRef ( ) .getText ( )
406+ then name = c .asMethodCallExprCfgNode ( ) .getNameRef ( ) .getText ( )
339407 else
340- name =
341- c .asCallExprCfgNode ( ) .getCallExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
408+ name = c .asCallExprCfgNode ( ) .getExpr ( ) .getExpr ( ) .( PathExpr ) .getPath ( ) .getPart ( ) .toString ( )
342409 )
343410 }
344411
@@ -377,19 +444,15 @@ module RustDataFlow implements InputSig<Location> {
377444
378445 ContentApprox getContentApprox ( Content c ) { any ( ) }
379446
380- class ParameterPosition extends string {
381- ParameterPosition ( ) { this = "pos" }
382- }
447+ class ParameterPosition = ParameterPositionAlias ;
383448
384- class ArgumentPosition extends string {
385- ArgumentPosition ( ) { this = "pos" }
386- }
449+ class ArgumentPosition = ParameterPosition ;
387450
388451 /**
389452 * Holds if the parameter position `ppos` matches the argument position
390453 * `apos`.
391454 */
392- predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { none ( ) }
455+ predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { ppos = apos }
393456
394457 /**
395458 * Holds if there is a simple local flow step from `node1` to `node2`. These
@@ -497,13 +560,13 @@ private module Cached {
497560 newtype TNode =
498561 TExprNode ( ExprCfgNode n ) or
499562 TParameterNode ( ParamCfgNode p ) or
563+ TSelfParameterNode ( SelfParamCfgNode p ) or
500564 TPatNode ( PatCfgNode p ) or
565+ TArgumentPostUpdateNode ( ExprCfgNode e ) { isArgumentForCall ( e , _, _) } or
501566 TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
502567
503568 cached
504- newtype TDataFlowCall =
505- TNormalCall ( CallExprCfgNode c ) or
506- TMethodCall ( MethodCallExprCfgNode c )
569+ newtype TDataFlowCall = TCall ( CallExprBaseCfgNode c )
507570
508571 cached
509572 newtype TOptionalContentSet =
@@ -521,6 +584,13 @@ private module Cached {
521584 predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
522585 LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
523586 }
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 ( )
524594}
525595
526596import Cached
0 commit comments