@@ -97,15 +97,20 @@ module LocalFlow {
9797 }
9898}
9999
100- /** An argument of a call (including qualifier arguments). */
101- private class Argument extends Expr {
102- private Call call ;
100+ /** An argument of a call (including qualifier arguments, excluding block arguments ). */
101+ private class Argument extends CfgNodes :: ExprCfgNode {
102+ private CfgNodes :: ExprNodes :: CallCfgNode call ;
103103 private int arg ;
104104
105- Argument ( ) { this = call .getArgument ( arg ) }
105+ Argument ( ) {
106+ this = call .getArgument ( arg ) and
107+ not this .getExpr ( ) instanceof BlockArgument
108+ or
109+ this = call .getReceiver ( ) and arg = - 1
110+ }
106111
107112 /** Holds if this expression is the `i`th argument of `c`. */
108- predicate isArgumentOf ( Expr c , int i ) { c = call and i = arg }
113+ predicate isArgumentOf ( CfgNodes :: ExprNodes :: CallCfgNode c , int i ) { c = call and i = arg }
109114}
110115
111116/** A collection of cached types and predicates to be evaluated in the same stage. */
@@ -125,14 +130,7 @@ private module Cached {
125130 TNormalParameterNode ( Parameter p ) { not p instanceof BlockParameter } or
126131 TSelfParameterNode ( MethodBase m ) or
127132 TBlockParameterNode ( MethodBase m ) or
128- TExprPostUpdateNode ( CfgNodes:: ExprCfgNode n ) {
129- exists ( AstNode node | node = n .getNode ( ) |
130- node instanceof Argument and
131- not node instanceof BlockArgument
132- or
133- n = any ( CfgNodes:: ExprNodes:: CallCfgNode call ) .getReceiver ( )
134- )
135- } or
133+ TExprPostUpdateNode ( CfgNodes:: ExprCfgNode n ) { n instanceof Argument } or
136134 TSummaryNode (
137135 FlowSummaryImpl:: Public:: SummarizedCallable c ,
138136 FlowSummaryImpl:: Private:: SummaryNodeState state
@@ -438,24 +436,18 @@ abstract class ArgumentNode extends Node {
438436private module ArgumentNodes {
439437 /** A data-flow node that represents an explicit call argument. */
440438 class ExplicitArgumentNode extends ArgumentNode {
441- ExplicitArgumentNode ( ) {
442- this .asExpr ( ) .getExpr ( ) instanceof Argument and
443- not this .asExpr ( ) .getExpr ( ) instanceof BlockArgument
444- }
439+ Argument arg ;
440+
441+ ExplicitArgumentNode ( ) { this .asExpr ( ) = arg }
445442
446443 override predicate sourceArgumentOf ( CfgNodes:: ExprNodes:: CallCfgNode call , int pos ) {
447- this . asExpr ( ) = call . getArgument ( pos )
444+ arg . isArgumentOf ( call , pos )
448445 }
449446 }
450447
451448 /** A data-flow node that represents the `self` argument of a call. */
452- class SelfArgumentNode extends ArgumentNode {
453- SelfArgumentNode ( ) { this .asExpr ( ) = any ( CfgNodes:: ExprNodes:: CallCfgNode call ) .getReceiver ( ) }
454-
455- override predicate sourceArgumentOf ( CfgNodes:: ExprNodes:: CallCfgNode call , int pos ) {
456- this .asExpr ( ) = call .getReceiver ( ) and
457- pos = - 1
458- }
449+ class SelfArgumentNode extends ExplicitArgumentNode {
450+ SelfArgumentNode ( ) { arg .isArgumentOf ( _, - 1 ) }
459451 }
460452
461453 /** A data-flow node that represents a block argument. */
@@ -522,8 +514,8 @@ private module ReturnNodes {
522514 }
523515
524516 /**
525- * A data-flow node that represents an expression returned by a callable,
526- * either using an explict `return` statement or as the expression of a method body .
517+ * A data-flow node that represents an expression explicitly returned by
518+ * a callable .
527519 */
528520 class ExplicitReturnNode extends ReturningNode , ReturningStatementNode {
529521 ExplicitReturnNode ( ) {
@@ -539,11 +531,25 @@ private module ReturnNodes {
539531 }
540532 }
541533
534+ pragma [ noinline]
535+ private AstNode implicitReturn ( Callable c , ExprNode n ) {
536+ exists ( CfgNodes:: ExprCfgNode en |
537+ en = n .getExprNode ( ) and
538+ en .getASuccessor ( ) .( CfgNodes:: AnnotatedExitNode ) .isNormal ( ) and
539+ n .( NodeImpl ) .getCfgScope ( ) = c and
540+ result = en .getExpr ( )
541+ )
542+ or
543+ result = implicitReturn ( c , n ) .getParent ( )
544+ }
545+
546+ /**
547+ * A data-flow node that represents an expression implicitly returned by
548+ * a callable. An implicit return happens when an expression can be the
549+ * last thing that is evaluated in the body of the callable.
550+ */
542551 class ExprReturnNode extends ReturningNode , ExprNode {
543- ExprReturnNode ( ) {
544- this .getExprNode ( ) .getASuccessor ( ) .( CfgNodes:: AnnotatedExitNode ) .isNormal ( ) and
545- this .( NodeImpl ) .getCfgScope ( ) instanceof Callable
546- }
552+ ExprReturnNode ( ) { exists ( Callable c | implicitReturn ( c , this ) = c .getAStmt ( ) ) }
547553
548554 override ReturnKind getKind ( ) { result instanceof NormalReturnKind }
549555 }
0 commit comments