@@ -260,6 +260,54 @@ class Node extends TIRDataFlowNode {
260
260
*/
261
261
Expr asDefiningArgument ( ) { result = this .asDefiningArgument ( _) }
262
262
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
+
263
311
/**
264
312
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
265
313
*
@@ -1142,22 +1190,6 @@ private module GetConvertedResultExpression {
1142
1190
}
1143
1191
1144
1192
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
1161
1193
// IR construction inserts an additional cast to a `size_t` on the extent
1162
1194
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
1163
1195
// a result for `getConvertedResultExpression`. We remap this here so that
@@ -1182,6 +1214,75 @@ private module GetConvertedResultExpression {
1182
1214
not exists ( getConvertedResultExpressionImpl0 ( instr ) ) and
1183
1215
result = instr .getConvertedResultExpression ( )
1184
1216
}
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
+ }
1185
1286
}
1186
1287
1187
1288
private import GetConvertedResultExpression
@@ -1947,7 +2048,12 @@ module ExprFlowCached {
1947
2048
isIndirectBaseOfArrayAccess ( n , result )
1948
2049
or
1949
2050
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
+ )
1951
2057
}
1952
2058
1953
2059
/**
0 commit comments