@@ -260,6 +260,54 @@ class Node extends TIRDataFlowNode {
260260 */
261261 Expr asDefiningArgument ( ) { result = this .asDefiningArgument ( _) }
262262
263+ /**
264+ * Gets the definition associated with this node, if any.
265+ *
266+ * For example, consider the following example
267+ * ```cpp
268+ * int x = 42; // 1
269+ * x = 34; // 2
270+ * ++x; // 3
271+ * x++; // 4
272+ * x += 1; // 5
273+ * int y = x += 2; // 6
274+ * ```
275+ * - For (1) the result is `42`.
276+ * - For (2) the result is `x = 34`.
277+ * - For (3) the result is `++x`.
278+ * - For (4) the result is `x++`.
279+ * - For (5) the result is `x += 1`.
280+ * - For (6) there are two results:
281+ * - For the definition generated by `x += 2` the result is `x += 2`
282+ * - For the definition generated by `int y = ...` the result is
283+ * also `x += 2`
284+ */
285+ Expr asDefinition ( ) {
286+ exists ( StoreInstruction store |
287+ store = this .asInstruction ( ) and
288+ result = asDefinitionImpl ( store )
289+ )
290+ }
291+
292+ /**
293+ * Gets the indirect definition at a given indirection corresponding to this
294+ * node, if any.
295+ *
296+ * See the comments on `Node.asDefinition` for examples.
297+ */
298+ Expr asIndirectDefinition ( int indirectionIndex ) {
299+ exists ( StoreInstruction store |
300+ this .( IndirectInstruction ) .hasInstructionAndIndirectionIndex ( store , indirectionIndex ) and
301+ result = asDefinitionImpl ( store )
302+ )
303+ }
304+
305+ /**
306+ * Gets the indirect definition at some indirection corresponding to this
307+ * node, if any.
308+ */
309+ Expr asIndirectDefinition ( ) { result = this .asIndirectDefinition ( _) }
310+
263311 /**
264312 * Gets the argument that defines this `DefinitionByReferenceNode`, if any.
265313 *
@@ -1142,22 +1190,6 @@ private module GetConvertedResultExpression {
11421190 }
11431191
11441192 private Expr getConvertedResultExpressionImpl0 ( Instruction instr ) {
1145- // For an expression such as `i += 2` we pretend that the generated
1146- // `StoreInstruction` contains the result of the expression even though
1147- // this isn't totally aligned with the C/C++ standard.
1148- exists ( TranslatedAssignOperation tao |
1149- result = tao .getExpr ( ) and
1150- instr = tao .getInstruction ( any ( AssignmentStoreTag tag ) )
1151- )
1152- or
1153- // Similarly for `i++` and `++i` we pretend that the generated
1154- // `StoreInstruction` is contains the result of the expression even though
1155- // this isn't totally aligned with the C/C++ standard.
1156- exists ( TranslatedCrementOperation tco |
1157- result = tco .getExpr ( ) and
1158- instr = tco .getInstruction ( any ( CrementStoreTag tag ) )
1159- )
1160- or
11611193 // IR construction inserts an additional cast to a `size_t` on the extent
11621194 // of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
11631195 // a result for `getConvertedResultExpression`. We remap this here so that
@@ -1182,6 +1214,75 @@ private module GetConvertedResultExpression {
11821214 not exists ( getConvertedResultExpressionImpl0 ( instr ) ) and
11831215 result = instr .getConvertedResultExpression ( )
11841216 }
1217+
1218+ /**
1219+ * Gets the result for `node.asDefinition()` (when `node` is the instruction
1220+ * node that wraps `store`) in the cases where `store.getAst()` should not be
1221+ * used to define the result of `node.asDefinition()`.
1222+ */
1223+ private Expr asDefinitionImpl0 ( StoreInstruction store ) {
1224+ // For an expression such as `i += 2` we pretend that the generated
1225+ // `StoreInstruction` contains the result of the expression even though
1226+ // this isn't totally aligned with the C/C++ standard.
1227+ exists ( TranslatedAssignOperation tao |
1228+ store = tao .getInstruction ( any ( AssignmentStoreTag tag ) ) and
1229+ result = tao .getExpr ( )
1230+ )
1231+ or
1232+ // Similarly for `i++` and `++i` we pretend that the generated
1233+ // `StoreInstruction` is contains the result of the expression even though
1234+ // this isn't totally aligned with the C/C++ standard.
1235+ exists ( TranslatedCrementOperation tco |
1236+ store = tco .getInstruction ( any ( CrementStoreTag tag ) ) and
1237+ result = tco .getExpr ( )
1238+ )
1239+ }
1240+
1241+ /**
1242+ * Holds if the expression returned by `store.getAst()` should not be
1243+ * returned as the result of `node.asDefinition()` when `node` is the
1244+ * instruction node that wraps `store`.
1245+ */
1246+ private predicate excludeAsDefinitionResult ( StoreInstruction store ) {
1247+ // Exclude the store to the temporary generated by a ternary expression.
1248+ exists ( TranslatedConditionalExpr tce |
1249+ store = tce .getInstruction ( any ( ConditionValueFalseStoreTag tag ) )
1250+ or
1251+ store = tce .getInstruction ( any ( ConditionValueTrueStoreTag tag ) )
1252+ )
1253+ }
1254+
1255+ /**
1256+ * Gets the expression that represents the result of `StoreInstruction` for
1257+ * dataflow purposes.
1258+ *
1259+ * For example, consider the following example
1260+ * ```cpp
1261+ * int x = 42; // 1
1262+ * x = 34; // 2
1263+ * ++x; // 3
1264+ * x++; // 4
1265+ * x += 1; // 5
1266+ * int y = x += 2; // 6
1267+ * ```
1268+ * For (1) the result is `42`.
1269+ * For (2) the result is `x = 34`.
1270+ * For (3) the result is `++x`.
1271+ * For (4) the result is `x++`.
1272+ * For (5) the result is `x += 1`.
1273+ * For (6) there are two results:
1274+ * - For the `StoreInstruction` generated by `x += 2` the result
1275+ * is `x += 2`
1276+ * - For the `StoreInstruction` generated by `int y = ...` the result
1277+ * is also `x += 2`
1278+ */
1279+ Expr asDefinitionImpl ( StoreInstruction store ) {
1280+ not exists ( asDefinitionImpl0 ( store ) ) and
1281+ not excludeAsDefinitionResult ( store ) and
1282+ result = store .getAst ( ) .( Expr ) .getUnconverted ( )
1283+ or
1284+ result = asDefinitionImpl0 ( store )
1285+ }
11851286}
11861287
11871288private import GetConvertedResultExpression
@@ -1947,7 +2048,12 @@ module ExprFlowCached {
19472048 isIndirectBaseOfArrayAccess ( n , result )
19482049 or
19492050 not isIndirectBaseOfArrayAccess ( n , _) and
1950- result = n .asExpr ( )
2051+ (
2052+ result = n .asExpr ( )
2053+ or
2054+ result = n .asDefinition ( ) and
2055+ result instanceof CrementOperation
2056+ )
19512057 }
19522058
19532059 /**
0 commit comments