@@ -288,3 +288,97 @@ 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+ abstract 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+ abstract SsaVariable getBaseVariable ( ) ;
327+
328+ /** Gets the type of this SSA variable with fields. */
329+ abstract Type getType ( ) ;
330+
331+ /** Gets a use in basic block `bb` that refers to this SSA variable with fields. */
332+ abstract IR:: Instruction getAUseIn ( ReachableBasicBlock bb ) ;
333+
334+ /** Gets a use that refers to this SSA variable with fields. */
335+ IR:: Instruction getAUse ( ) { result = this .getAUseIn ( _) }
336+
337+ /** Gets a textual representation of this element. */
338+ abstract string toString ( ) ;
339+
340+ /**
341+ * Holds if this element is at the specified location.
342+ * The location spans column `startcolumn` of line `startline` to
343+ * column `endcolumn` of line `endline` in file `filepath`.
344+ * For more information, see
345+ * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
346+ */
347+ predicate hasLocationInfo (
348+ string filepath , int startline , int startcolumn , int endline , int endcolumn
349+ ) {
350+ this .getBaseVariable ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
351+ }
352+ }
353+
354+ private class SsaWithFieldsRoot extends SsaWithFields , TRoot {
355+ SsaVariable self ;
356+
357+ SsaWithFieldsRoot ( ) { this = TRoot ( self ) }
358+
359+ override SsaVariable getBaseVariable ( ) { result = self }
360+
361+ override Type getType ( ) { result = self .getType ( ) }
362+
363+ override IR:: Instruction getAUseIn ( ReachableBasicBlock bb ) { result = self .getAUseIn ( bb ) }
364+
365+ override string toString ( ) { result = "(" + self .toString ( ) + ")" }
366+ }
367+
368+ private class SsaWithFieldsStep extends SsaWithFields , TStep {
369+ SsaWithFields base ;
370+ Field f ;
371+
372+ SsaWithFieldsStep ( ) { this = TStep ( base , f ) }
373+
374+ override SsaVariable getBaseVariable ( ) { result = base .getBaseVariable ( ) }
375+
376+ override Type getType ( ) { result = f .getType ( ) }
377+
378+ override IR:: FieldReadInstruction getAUseIn ( ReachableBasicBlock bb ) {
379+ result .getBase ( ) = base .getAUseIn ( bb ) and
380+ result .getField ( ) = f
381+ }
382+
383+ override string toString ( ) { result = base .toString ( ) + "." + f .getName ( ) }
384+ }
0 commit comments