@@ -320,6 +320,9 @@ newtype TDataFlowCallable =
320320 // same to keep things easy to reason about (and therefore exclude things that do
321321 // not have a definition)
322322 exists ( func .getDefinition ( ) )
323+ or
324+ // ...scratch that, variable capture requires a callable
325+ exists ( Comp c | c .getFunction ( ) = func )
323326 } or
324327 /** see QLDoc for `DataFlowModuleScope` for why we need this. */
325328 TModule ( Module m ) or
@@ -1382,6 +1385,7 @@ private predicate sameEnclosingCallable(Node node1, Node node2) {
13821385// =============================================================================
13831386newtype TDataFlowCall =
13841387 TNormalCall ( CallNode call , Function target , CallType type ) { resolveCall ( call , target , type ) } or
1388+ TComprehensionCall ( Comp c ) or
13851389 TPotentialLibraryCall ( CallNode call ) or
13861390 /** A synthesized call inside a summarized callable */
13871391 TSummaryCall (
@@ -1468,6 +1472,30 @@ class NormalCall extends ExtractedDataFlowCall, TNormalCall {
14681472 CallType getCallType ( ) { result = type }
14691473}
14701474
1475+ class ComprehensionCall extends ExtractedDataFlowCall , TComprehensionCall {
1476+ Comp c ;
1477+ Function target ;
1478+
1479+ ComprehensionCall ( ) {
1480+ this = TComprehensionCall ( c ) and
1481+ target = c .getFunction ( )
1482+ }
1483+
1484+ Comp getComprehension ( ) { result = c }
1485+
1486+ override string toString ( ) { result = "comprehension call" }
1487+
1488+ override ControlFlowNode getNode ( ) { result .getNode ( ) = c }
1489+
1490+ override Scope getScope ( ) { result = c .getScope ( ) }
1491+
1492+ override DataFlowCallable getCallable ( ) { result .( DataFlowFunction ) .getScope ( ) = target }
1493+
1494+ override ArgumentNode getArgument ( ArgumentPosition apos ) { none ( ) }
1495+
1496+ override Location getLocation ( ) { result = c .getLocation ( ) }
1497+ }
1498+
14711499/**
14721500 * A potential call to a summarized callable, a `LibraryCallable`.
14731501 *
@@ -1698,6 +1726,24 @@ class CapturedVariablesArgumentNode extends CfgNode, ArgumentNode {
16981726 }
16991727}
17001728
1729+ class ComprehensionCapturedVariablesArgumentNode extends CfgNode , ArgumentNode {
1730+ Comp comp ;
1731+
1732+ ComprehensionCapturedVariablesArgumentNode ( ) {
1733+ node .getNode ( ) = comp and
1734+ exists ( Function target | target = comp .getFunction ( ) |
1735+ target = any ( VariableCapture:: CapturedVariable v ) .getACapturingScope ( )
1736+ )
1737+ }
1738+
1739+ override string toString ( ) { result = "Capturing closure argument (comp)" }
1740+
1741+ override predicate argumentOf ( DataFlowCall call , ArgumentPosition pos ) {
1742+ call .( ComprehensionCall ) .getComprehension ( ) = comp and
1743+ pos .isLambdaSelf ( )
1744+ }
1745+ }
1746+
17011747/** Gets a viable run-time target for the call `call`. */
17021748DataFlowCallable viableCallable ( DataFlowCall call ) {
17031749 call instanceof ExtractedDataFlowCall and
0 commit comments