@@ -48,7 +48,7 @@ module LocalFlow {
48
48
49
49
/**
50
50
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
51
- * SSA definition `def.
51
+ * SSA definition `def` .
52
52
*/
53
53
predicate localSsaFlowStep ( Ssa:: Definition def , Node nodeFrom , Node nodeTo ) {
54
54
// Flow from parameter into SSA definition
@@ -114,6 +114,12 @@ private module Cached {
114
114
newtype TNode =
115
115
TExprNode ( CfgNodes:: ExprCfgNode n ) or
116
116
TReturningNode ( CfgNodes:: ReturningCfgNode n ) or
117
+ TSynthReturnNode ( CfgScope scope , ReturnKind kind ) {
118
+ exists ( ReturningNode ret |
119
+ ret .( NodeImpl ) .getCfgScope ( ) = scope and
120
+ ret .getKind ( ) = kind
121
+ )
122
+ } or
117
123
TSsaDefinitionNode ( Ssa:: Definition def ) or
118
124
TNormalParameterNode ( Parameter p ) { not p instanceof BlockParameter } or
119
125
TSelfParameterNode ( MethodBase m ) or
@@ -140,14 +146,12 @@ private module Cached {
140
146
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or TSummaryParameterNode ;
141
147
142
148
/**
143
- * This is the local flow predicate that is used as a building block in global
144
- * data flow. It excludes SSA flow through instance fields, as flow through fields
145
- * is handled by the global data-flow library, but includes various other steps
146
- * that are only relevant for global flow.
149
+ * This is the local flow predicate that is shared between local data flow
150
+ * and global data flow.
147
151
*/
148
152
cached
149
- predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
150
- exists ( Ssa :: Definition def | LocalFlow:: localSsaFlowStep ( def , nodeFrom , nodeTo ) )
153
+ predicate simpleLocalFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
154
+ LocalFlow:: localSsaFlowStep ( _ , nodeFrom , nodeTo )
151
155
or
152
156
nodeTo .( ParameterNode ) .getParameter ( ) .( OptionalParameter ) .getDefaultValue ( ) =
153
157
nodeFrom .asExpr ( ) .getExpr ( )
@@ -186,12 +190,39 @@ private module Cached {
186
190
) and
187
191
nodeFrom .asExpr ( ) = for .getValue ( )
188
192
)
193
+ }
194
+
195
+ /**
196
+ * 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.
200
+ */
201
+ cached
202
+ predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
203
+ simpleLocalFlowStepCommon ( nodeFrom , nodeTo )
204
+ or
205
+ nodeTo .( SynthReturnNode ) .getAnInput ( ) = nodeFrom
189
206
or
190
207
FlowSummaryImpl:: Private:: Steps:: summaryLocalStep ( nodeFrom , nodeTo , true )
191
208
}
192
209
193
210
cached
194
- predicate isLocalSourceNode ( Node n ) { not simpleLocalFlowStep + ( any ( ExprNode e ) , n ) }
211
+ predicate isLocalSourceNode ( Node n ) {
212
+ n instanceof ParameterNode
213
+ or
214
+ // This case should not be needed once we have proper use-use flow
215
+ // for `self`. At that point, the `self`s returned by `trackInstance`
216
+ // in `DataFlowDispatch.qll` should refer to the post-update node,
217
+ // and we can remove this case.
218
+ n instanceof SelfArgumentNode
219
+ or
220
+ not simpleLocalFlowStepCommon + ( any ( Node e |
221
+ e instanceof ExprNode
222
+ or
223
+ e instanceof ParameterNode
224
+ ) , n )
225
+ }
195
226
196
227
cached
197
228
newtype TContent = TTodoContent ( ) // stub
@@ -208,6 +239,8 @@ predicate nodeIsHidden(Node n) {
208
239
n instanceof SummaryNode
209
240
or
210
241
n instanceof SummaryParameterNode
242
+ or
243
+ n instanceof SynthReturnNode
211
244
}
212
245
213
246
/** An SSA definition, viewed as a node in a data flow graph. */
@@ -234,7 +267,7 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
234
267
* `ControlFlow::Node`s.
235
268
*/
236
269
class ReturningStatementNode extends NodeImpl , TReturningNode {
237
- private CfgNodes:: ReturningCfgNode n ;
270
+ CfgNodes:: ReturningCfgNode n ;
238
271
239
272
ReturningStatementNode ( ) { this = TReturningNode ( n ) }
240
273
@@ -436,6 +469,12 @@ private module ArgumentNodes {
436
469
437
470
import ArgumentNodes
438
471
472
+ /** A data-flow node that represents a value syntactically returned by a callable. */
473
+ abstract class ReturningNode extends Node {
474
+ /** Gets the kind of this return node. */
475
+ abstract ReturnKind getKind ( ) ;
476
+ }
477
+
439
478
/** A data-flow node that represents a value returned by a callable. */
440
479
abstract class ReturnNode extends Node {
441
480
/** Gets the kind of this return node. */
@@ -463,11 +502,9 @@ private module ReturnNodes {
463
502
* A data-flow node that represents an expression returned by a callable,
464
503
* either using an explict `return` statement or as the expression of a method body.
465
504
*/
466
- class ExplicitReturnNode extends ReturnNode , ReturningStatementNode {
467
- private CfgNodes:: ReturningCfgNode n ;
468
-
505
+ class ExplicitReturnNode extends ReturningNode , ReturningStatementNode {
469
506
ExplicitReturnNode ( ) {
470
- isValid ( this . getReturningNode ( ) ) and
507
+ isValid ( n ) and
471
508
n .getASuccessor ( ) .( CfgNodes:: AnnotatedExitNode ) .isNormal ( ) and
472
509
n .getScope ( ) instanceof Callable
473
510
}
@@ -479,7 +516,7 @@ private module ReturnNodes {
479
516
}
480
517
}
481
518
482
- class ExprReturnNode extends ReturnNode , ExprNode {
519
+ class ExprReturnNode extends ReturningNode , ExprNode {
483
520
ExprReturnNode ( ) {
484
521
this .getExprNode ( ) .getASuccessor ( ) .( CfgNodes:: AnnotatedExitNode ) .isNormal ( ) and
485
522
this .( NodeImpl ) .getCfgScope ( ) instanceof Callable
@@ -488,6 +525,34 @@ private module ReturnNodes {
488
525
override ReturnKind getKind ( ) { result instanceof NormalReturnKind }
489
526
}
490
527
528
+ /**
529
+ * A synthetic data-flow node for joining flow from different syntactic
530
+ * returns into a single node.
531
+ *
532
+ * This node only exists to avoid computing the product of a large fan-in
533
+ * with a large fan-out.
534
+ */
535
+ class SynthReturnNode extends NodeImpl , ReturnNode , TSynthReturnNode {
536
+ private CfgScope scope ;
537
+ private ReturnKind kind ;
538
+
539
+ SynthReturnNode ( ) { this = TSynthReturnNode ( scope , kind ) }
540
+
541
+ /** Get a syntactic return node that flows into this synthetic node. */
542
+ ReturningNode getAnInput ( ) {
543
+ result .( NodeImpl ) .getCfgScope ( ) = scope and
544
+ result .getKind ( ) = kind
545
+ }
546
+
547
+ override ReturnKind getKind ( ) { result = kind }
548
+
549
+ override CfgScope getCfgScope ( ) { result = scope }
550
+
551
+ override Location getLocationImpl ( ) { result = scope .getLocation ( ) }
552
+
553
+ override string toStringImpl ( ) { result = "return " + kind + " in " + scope }
554
+ }
555
+
491
556
private class SummaryReturnNode extends SummaryNode , ReturnNode {
492
557
private ReturnKind rk ;
493
558
@@ -631,7 +696,7 @@ private import PostUpdateNodes
631
696
632
697
/** A node that performs a type cast. */
633
698
class CastNode extends Node {
634
- CastNode ( ) { none ( ) }
699
+ CastNode ( ) { this instanceof ReturningNode }
635
700
}
636
701
637
702
class DataFlowExpr = CfgNodes:: ExprCfgNode ;
0 commit comments