@@ -320,6 +320,50 @@ class BuilderNode extends TDataFlowNodeStage1 {
320320 result = call .getLocation ( )
321321 )
322322 }
323+
324+ /**
325+ * Holds if this data flow node is associated with the `i`'th index in the given basic block.
326+ *
327+ * Note that some data flow nodes may have an index appearing before the first or after the
328+ * last `ControlFlowNode` node in the basic block. Multiple data flow nodes may share the same control flow position.
329+ *
330+ * Also note that some data flow nodes have no associated control flow position, either because they are
331+ * in unreachable code, or belong to a synthesized callable that has no control flow graph.
332+ */
333+ predicate hasControlFlowPosition ( BasicBlock bb , int i ) {
334+ exists ( ControlFlowNode cfgNode | cfgNode = bb .getNode ( i ) |
335+ exists ( Expr expr |
336+ this .isResultValue ( expr ) and cfgNode .asExpr ( ) = expr
337+ or
338+ this .isIncomingValue ( expr ) and hasIncomingValueAtCfgNode ( expr , cfgNode )
339+ or
340+ this .isPostUpdate ( expr ) and hasPostUpdate ( expr , cfgNode )
341+ )
342+ or
343+ exists ( AstNode repr , LocalVariable var , VariableRefKind kind |
344+ this .isLocalVariableRef ( repr , var , kind ) and
345+ performsVariableAccess ( repr , var , kind , cfgNode )
346+ )
347+ or
348+ exists ( DataFlowCallable callable |
349+ this .isImplicitParameter ( callable , _) and
350+ cfgNode .( ControlFlow:: EntryNode ) .getEnclosingCallable ( ) = callable .asSourceCallable ( )
351+ or
352+ this .isCallableEx ( callable ) and
353+ cfgNode .injects ( callable .asSourceCallable ( ) )
354+ )
355+ or
356+ exists ( DataFlowCall call , CallExpr sourceCall , boolean isPost |
357+ call .asExplicitCall ( ) = sourceCall and
358+ this .isImplicitArgument ( call , _, isPost ) and
359+ (
360+ isPost = false and cfgNode .injects ( sourceCall )
361+ or
362+ isPost = true and cfgNode .isAfter ( sourceCall )
363+ )
364+ )
365+ )
366+ }
323367}
324368
325369/** A node in stage 2, which includes stage 1 and local SSA nodes. */
@@ -343,6 +387,16 @@ class Stage2Node extends TDataFlowNodeStage2 {
343387 result = node .getLocation ( )
344388 )
345389 }
390+
391+ predicate hasControlFlowPosition ( BasicBlock bb , int i ) {
392+ this .( BuilderNode ) .hasControlFlowPosition ( bb , i )
393+ or
394+ exists ( LocalSsaDataFlowOutput:: SsaNode node |
395+ this = TLocalSsaNode ( node ) and
396+ bb = node .getBasicBlock ( ) and
397+ i = node .getIndex ( ) // TODO: why is this marked as internal in the SSA library?
398+ )
399+ }
346400}
347401
348402class Node extends TDataFlowNode {
@@ -491,44 +545,7 @@ class Node extends TDataFlowNode {
491545 * in unreachable code, or belong to a synthesized callable that has no control flow graph.
492546 */
493547 predicate hasControlFlowPosition ( BasicBlock bb , int i ) {
494- exists ( ControlFlowNode cfgNode | cfgNode = bb .getNode ( i ) |
495- exists ( Expr expr |
496- this .isResultValue ( expr ) and cfgNode .asExpr ( ) = expr
497- or
498- this .isIncomingValue ( expr ) and hasIncomingValueAtCfgNode ( expr , cfgNode )
499- or
500- this .isPostUpdate ( expr ) and hasPostUpdate ( expr , cfgNode )
501- )
502- or
503- exists ( AstNode repr , LocalVariable var , VariableRefKind kind |
504- this .isLocalVariableRef ( repr , var , kind ) and
505- performsVariableAccess ( repr , var , kind , cfgNode )
506- )
507- or
508- exists ( DataFlowCallable callable |
509- this .( BuilderNode ) .isImplicitParameter ( callable , _) and
510- cfgNode .( ControlFlow:: EntryNode ) .getEnclosingCallable ( ) = callable .asSourceCallable ( )
511- or
512- this .isCallableEx ( callable ) and
513- cfgNode .injects ( callable .asSourceCallable ( ) )
514- )
515- or
516- exists ( DataFlowCall call , CallExpr sourceCall , boolean isPost |
517- call .asExplicitCall ( ) = sourceCall and
518- this .( BuilderNode ) .isImplicitArgument ( call , _, isPost ) and
519- (
520- isPost = false and cfgNode .injects ( sourceCall )
521- or
522- isPost = true and cfgNode .isAfter ( sourceCall )
523- )
524- )
525- )
526- or
527- exists ( LocalSsaDataFlowOutput:: SsaNode node |
528- this = TLocalSsaNode ( node ) and
529- bb = node .getBasicBlock ( ) and
530- i = node .getIndex ( ) // TODO: why is this marked as internal in the SSA library?
531- )
548+ this .( Stage2Node ) .hasControlFlowPosition ( bb , i )
532549 or
533550 exists ( CaptureSsaOutput:: SynthesizedCaptureNode node |
534551 this = TCaptureSsaNode ( node ) and
0 commit comments