@@ -288,3 +288,97 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
288
288
getBasicBlock ( ) .hasLocationInfo ( filepath , startline , startcolumn , _, _)
289
289
}
290
290
}
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