@@ -264,6 +264,41 @@ private module Cached {
264264 e = getConvertedResultExpression ( node .asInstruction ( ) , n )
265265 }
266266
267+ /**
268+ * The IR doesn't have an instruction `i` for which this holds:
269+ * ```
270+ * i.getUnconvertedResultExpression() instanceof ClassAggregateLiteral
271+ * ```
272+ * and thus we don't automaticallt get a dataflow node for which:
273+ * ```
274+ * node.asExpr() instanceof ClassAggregateLiteral
275+ * ```
276+ * This is because the IR represents a `ClassAggregateLiteral` as a sequence
277+ * of field writes. To work around this we map `asExpr` on the
278+ * `PostUpdateNode` for the last field write to the class aggregate literal.
279+ */
280+ private class ClassAggregateInitializerPostUpdateNode extends PostFieldUpdateNode {
281+ ClassAggregateLiteral aggr ;
282+
283+ ClassAggregateInitializerPostUpdateNode ( ) {
284+ exists ( Node node1 , FieldContent fc , int position , StoreInstruction store |
285+ store .getSourceValue ( ) .getUnconvertedResultExpression ( ) =
286+ aggr .getFieldExpr ( fc .getField ( ) , position ) and
287+ node1 .asInstruction ( ) = store and
288+ // This is the last field write from the aggregate initialization.
289+ not exists ( aggr .getFieldExpr ( _, position + 1 ) ) and
290+ storeStep ( node1 , fc , this )
291+ )
292+ }
293+
294+ ClassAggregateLiteral getClassAggregateLiteral ( ) { result = aggr }
295+ }
296+
297+ private predicate exprNodeShouldBePostUpdateNode ( Node node , Expr e , int n ) {
298+ node .( ClassAggregateInitializerPostUpdateNode ) .getClassAggregateLiteral ( ) = e and
299+ n = 0
300+ }
301+
267302 /** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
268303 private predicate indirectExprNodeShouldBeIndirectInstruction (
269304 IndirectInstruction node , Expr e , int n , int indirectionIndex
@@ -294,7 +329,8 @@ private module Cached {
294329 exprNodeShouldBeInstruction ( _, e , n ) or
295330 exprNodeShouldBeOperand ( _, e , n ) or
296331 exprNodeShouldBeIndirectOutNode ( _, e , n ) or
297- exprNodeShouldBeIndirectOperand ( _, e , n )
332+ exprNodeShouldBeIndirectOperand ( _, e , n ) or
333+ exprNodeShouldBePostUpdateNode ( _, e , n )
298334 }
299335
300336 private class InstructionExprNode extends ExprNodeBase , InstructionNode {
@@ -442,6 +478,12 @@ private module Cached {
442478 final override Expr getConvertedExpr ( int n ) { exprNodeShouldBeIndirectOperand ( this , result , n ) }
443479 }
444480
481+ private class PostUpdateExprNode extends ExprNodeBase instanceof PostUpdateNode {
482+ PostUpdateExprNode ( ) { exprNodeShouldBePostUpdateNode ( this , _, _) }
483+
484+ final override Expr getConvertedExpr ( int n ) { exprNodeShouldBePostUpdateNode ( this , result , n ) }
485+ }
486+
445487 /**
446488 * An expression, viewed as a node in a data flow graph.
447489 */
0 commit comments