@@ -43,20 +43,38 @@ private SsaVariable getRefinedVariable(SsaVariable variable) {
4343 result = variable .getDefinition ( ) .( SsaRefinementNode ) .getAnInput ( )
4444}
4545
46- private SsaVariable getARefinementOf ( SsaVariable variable ) {
47- variable = getRefinedVariable ( result )
48- }
46+ private SsaVariable getARefinementOf ( SsaVariable variable ) { variable = getRefinedVariable ( result ) }
4947
5048/**
51- * A representation of a (nested) property access on an SSA variable
49+ * A representation of a (nested) property access on an SSA variable or captured variable
5250 * where each property name is either constant or itself an SSA variable.
5351 */
5452private newtype TAccessPath =
53+ /**
54+ * An access path rooted in an SSA variable.
55+ *
56+ * Refinement nodes are treated as no-ops so that all uses of a refined value are
57+ * given the same access path. Refinement nodes are therefore never treated as roots.
58+ */
5559 MkSsaRoot ( SsaVariable var ) {
56- not exists ( getRefinedVariable ( var ) )
57- }
58- or
60+ not exists ( getRefinedVariable ( var ) ) and
61+ not var .getSourceVariable ( ) .isCaptured ( ) // Handled by MkCapturedRoot
62+ } or
63+ /**
64+ * An access path rooted in a captured variable.
65+ *
66+ * The SSA form for captured variables is too conservative for constructing
67+ * access paths across function boundaries, so in this case we use the source
68+ * variable as the root.
69+ */
70+ MkCapturedRoot ( LocalVariable var ) { var .isCaptured ( ) } or
71+ /**
72+ * An access path rooted in the receiver of a function.
73+ */
5974 MkThisRoot ( Function function ) { function .getThisBinder ( ) = function } or
75+ /**
76+ * A property access on an access path.
77+ */
6078 MkAccessStep ( AccessPath base , PropertyName name ) {
6179 exists ( PropAccess pacc |
6280 pacc .getBase ( ) = base .getAnInstance ( ) and
@@ -65,7 +83,7 @@ private newtype TAccessPath =
6583 }
6684
6785/**
68- * A representation of a (nested) property access on an SSA variable
86+ * A representation of a (nested) property access on an SSA variable or captured variable
6987 * where each property name is either constant or itself an SSA variable.
7088 */
7189class AccessPath extends TAccessPath {
@@ -78,6 +96,12 @@ class AccessPath extends TAccessPath {
7896 result = getARefinementOf * ( var ) .getAUseIn ( bb )
7997 )
8098 or
99+ exists ( Variable var |
100+ this = MkCapturedRoot ( var ) and
101+ result = var .getAnAccess ( ) and
102+ result .getBasicBlock ( ) = bb
103+ )
104+ or
81105 exists ( ThisExpr this_ |
82106 this = MkThisRoot ( this_ .getBinder ( ) ) and
83107 result = this_ and
0 commit comments