@@ -288,3 +288,67 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
288288 getBasicBlock ( ) .hasLocationInfo ( filepath , startline , startcolumn , _, _)
289289 }
290290}
291+
292+ /**
293+ * An SSA variable, possibly with a chain of field reads on it.
294+ */
295+ private newtype TSsaWithFields =
296+ TRoot ( SsaVariable v ) or
297+ TStep ( SsaWithFields base , Field f ) { exists ( accessPathAux ( base , f ) ) }
298+
299+ /**
300+ * Gets a representation of `nd` as an ssa-with-fields value if there is one.
301+ */
302+ private TSsaWithFields accessPath ( IR:: Instruction insn ) {
303+ exists ( SsaVariable v | insn = v .getAUse ( ) | result = TRoot ( v ) )
304+ or
305+ exists ( SsaWithFields base , Field f | insn = accessPathAux ( base , f ) | result = TStep ( base , f ) )
306+ }
307+
308+ /**
309+ * Gets a data-flow node that reads a field `f` from a node that is represented
310+ * by ssa-with-fields value `base`.
311+ */
312+ private IR:: Instruction accessPathAux ( TSsaWithFields base , Field f ) {
313+ exists ( IR:: FieldReadInstruction fr | fr = result |
314+ base = accessPath ( fr .getBase ( ) ) and
315+ f = fr .getField ( )
316+ )
317+ }
318+
319+ class SsaWithFields extends TSsaWithFields {
320+ /**
321+ * Gets the SSA variable corresponding to the base of this SSA variable with fields.
322+ *
323+ * For example, the SSA variable corresponding to `a` for the SSA variable with fields
324+ * corresponding to `a.b`.
325+ */
326+ SsaVariable getBaseVariable ( ) {
327+ this = TRoot ( result )
328+ or
329+ exists ( SsaWithFields base , Field f | this = TStep ( base , f ) | result = base .getBaseVariable ( ) )
330+ }
331+
332+ /** Gets a use that refers to this SSA variable with fields. */
333+ DataFlow:: Node getAUse ( ) { this = accessPath ( result .asInstruction ( ) ) }
334+
335+ /** Gets a textual representation of this element. */
336+ string toString ( ) {
337+ exists ( SsaVariable var | this = TRoot ( var ) | result = "(" + var + ")" )
338+ or
339+ exists ( SsaWithFields base , Field f | this = TStep ( base , f ) | result = base + "." + f .getName ( ) )
340+ }
341+
342+ /**
343+ * Holds if this element is at the specified location.
344+ * The location spans column `startcolumn` of line `startline` to
345+ * column `endcolumn` of line `endline` in file `filepath`.
346+ * For more information, see
347+ * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
348+ */
349+ predicate hasLocationInfo (
350+ string filepath , int startline , int startcolumn , int endline , int endcolumn
351+ ) {
352+ this .getBaseVariable ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
353+ }
354+ }
0 commit comments