@@ -166,6 +166,16 @@ class java_object_factoryt
166
166
code_blockt &assignments,
167
167
const exprt &instance_expr,
168
168
const irep_idt &method_name);
169
+
170
+ void array_loop_init_code (
171
+ code_blockt &assignments,
172
+ const exprt &init_array_expr,
173
+ const exprt &length_expr,
174
+ const typet &element_type,
175
+ const exprt &max_length_expr,
176
+ size_t depth,
177
+ update_in_placet update_in_place,
178
+ const source_locationt &location);
169
179
};
170
180
171
181
// / Returns a codet that assigns \p expr, of type \p ptr_type, a NULL value.
@@ -1210,55 +1220,51 @@ codet make_allocate_code(const symbol_exprt &lhs, const exprt &size)
1210
1220
return code_assignt (lhs, alloc);
1211
1221
}
1212
1222
1213
- // / Create code to initialize a Java array whose size will be at most
1214
- // / `max_nondet_array_length`. The code is emitted to \p assignments does as
1215
- // / follows:
1216
- // / 1. non-deterministically choose a length for the array
1217
- // / 2. assume that such length is >=0 and <= max_length
1218
- // / 3. loop through all elements of the array and initialize them
1219
- void java_object_factoryt::gen_nondet_array_init (
1223
+ // / Create code to nondeterministically initialise each element of an array in a
1224
+ // / loop.
1225
+ // / The code produced is of the form (supposing an array of type OBJ):
1226
+ // / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1227
+ // / struct java.lang.Integer **array_data_init;
1228
+ // / int array_init_iter;
1229
+ // / array_data_init = (struct OBJ **)init_array_expr;
1230
+ // / array_init_iter = 0;
1231
+ // / 2: IF array_init_iter == length_expr THEN GOTO 5
1232
+ // / IF array_init_iter == max_length_expr THEN GOTO 5
1233
+ // / IF !NONDET(__CPROVER_bool) THEN GOTO 3
1234
+ // / array_data_init[array_init_iter] = null;
1235
+ // / GOTO 4
1236
+ // / 3: malloc_site = ALLOCATE(...);
1237
+ // / array_data_init[array_init_iter] = (struct OBJ *)malloc_site;
1238
+ // / *malloc_site = {...};
1239
+ // / malloc_site->value = NONDET(int);
1240
+ // / 4: array_init_iter = array_init_iter + 1;
1241
+ // / GOTO 2
1242
+ // / 5: ...
1243
+ // / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1244
+ // / \param [out] assignments : Code block to which the initializing assignments
1245
+ // / will be appended.
1246
+ // / \param init_array_expr : array data
1247
+ // / \param length_expr : array length
1248
+ // / \param element_type: type of array elements
1249
+ // / \param max_length_expr : max length, as specified by max-nondet-array-length
1250
+ // / \param depth: Number of times that a pointer has been dereferenced from the
1251
+ // / root of the object tree that we are initializing.
1252
+ // / \param update_in_place:
1253
+ // / NO_UPDATE_IN_PLACE: initialize `expr` from scratch
1254
+ // / MAY_UPDATE_IN_PLACE: generate a runtime nondet branch between the NO_
1255
+ // / and MUST_ cases.
1256
+ // / MUST_UPDATE_IN_PLACE: reinitialize an existing object
1257
+ // / \param location: Source location associated with nondet-initialization.
1258
+ void java_object_factoryt::array_loop_init_code (
1220
1259
code_blockt &assignments,
1221
- const exprt &expr,
1260
+ const exprt &init_array_expr,
1261
+ const exprt &length_expr,
1262
+ const typet &element_type,
1263
+ const exprt &max_length_expr,
1222
1264
size_t depth,
1223
1265
update_in_placet update_in_place,
1224
1266
const source_locationt &location)
1225
1267
{
1226
- PRECONDITION (expr.type ().id ()==ID_pointer);
1227
- PRECONDITION (expr.type ().subtype ().id () == ID_struct_tag);
1228
- PRECONDITION (update_in_place!=update_in_placet::MAY_UPDATE_IN_PLACE);
1229
-
1230
- const typet &type=ns.follow (expr.type ().subtype ());
1231
- const struct_typet &struct_type=to_struct_type (type);
1232
- const typet &element_type =
1233
- static_cast <const typet &>(expr.type ().subtype ().find (ID_element_type));
1234
-
1235
- auto max_length_expr=from_integer (
1236
- object_factory_parameters.max_nondet_array_length , java_int_type ());
1237
-
1238
- // In NO_UPDATE_IN_PLACE mode we allocate a new array and recursively
1239
- // initialize its elements
1240
- if (update_in_place==update_in_placet::NO_UPDATE_IN_PLACE)
1241
- {
1242
- allocate_nondet_length_array (
1243
- assignments, expr, max_length_expr, element_type, location);
1244
- }
1245
-
1246
- // Otherwise we're updating the array in place, and use the
1247
- // existing array allocation and length.
1248
-
1249
- INVARIANT (
1250
- is_valid_java_array (struct_type),
1251
- " Java struct array does not conform to expectations" );
1252
-
1253
- dereference_exprt deref_expr (expr, expr.type ().subtype ());
1254
- const auto &comps=struct_type.components ();
1255
- const member_exprt length_expr (deref_expr, " length" , comps[1 ].type ());
1256
- exprt init_array_expr=member_exprt (deref_expr, " data" , comps[2 ].type ());
1257
-
1258
- if (init_array_expr.type ()!=pointer_type (element_type))
1259
- init_array_expr=
1260
- typecast_exprt (init_array_expr, pointer_type (element_type));
1261
-
1262
1268
const symbol_exprt &array_init_symexpr =
1263
1269
allocate_objects.allocate_automatic_local_object (
1264
1270
init_array_expr.type (), " array_data_init" );
@@ -1334,6 +1340,67 @@ void java_object_factoryt::gen_nondet_array_init(
1334
1340
assignments.add (std::move (init_done_label));
1335
1341
}
1336
1342
1343
+ // / Create code to initialize a Java array whose size will be at most
1344
+ // / `max_nondet_array_length`. The code is emitted to \p assignments does as
1345
+ // / follows:
1346
+ // / 1. non-deterministically choose a length for the array
1347
+ // / 2. assume that such length is >=0 and <= max_length
1348
+ // / 3. loop through all elements of the array and initialize them
1349
+ void java_object_factoryt::gen_nondet_array_init (
1350
+ code_blockt &assignments,
1351
+ const exprt &expr,
1352
+ size_t depth,
1353
+ update_in_placet update_in_place,
1354
+ const source_locationt &location)
1355
+ {
1356
+ PRECONDITION (expr.type ().id () == ID_pointer);
1357
+ PRECONDITION (expr.type ().subtype ().id () == ID_struct_tag);
1358
+ PRECONDITION (update_in_place != update_in_placet::MAY_UPDATE_IN_PLACE);
1359
+
1360
+ const typet &type = ns.follow (expr.type ().subtype ());
1361
+ const struct_typet &struct_type = to_struct_type (type);
1362
+ const typet &element_type =
1363
+ static_cast <const typet &>(expr.type ().subtype ().find (ID_element_type));
1364
+
1365
+ auto max_length_expr = from_integer (
1366
+ object_factory_parameters.max_nondet_array_length , java_int_type ());
1367
+
1368
+ // In NO_UPDATE_IN_PLACE mode we allocate a new array and recursively
1369
+ // initialize its elements
1370
+ if (update_in_place == update_in_placet::NO_UPDATE_IN_PLACE)
1371
+ {
1372
+ allocate_nondet_length_array (
1373
+ assignments, expr, max_length_expr, element_type, location);
1374
+ }
1375
+
1376
+ // Otherwise we're updating the array in place, and use the
1377
+ // existing array allocation and length.
1378
+
1379
+ INVARIANT (
1380
+ is_valid_java_array (struct_type),
1381
+ " Java struct array does not conform to expectations" );
1382
+
1383
+ dereference_exprt deref_expr (expr, expr.type ().subtype ());
1384
+ const auto &comps = struct_type.components ();
1385
+ const member_exprt length_expr (deref_expr, " length" , comps[1 ].type ());
1386
+ exprt init_array_expr = member_exprt (deref_expr, " data" , comps[2 ].type ());
1387
+
1388
+ if (init_array_expr.type () != pointer_type (element_type))
1389
+ init_array_expr =
1390
+ typecast_exprt (init_array_expr, pointer_type (element_type));
1391
+
1392
+ // Nondeterministically initialise each element of the array
1393
+ array_loop_init_code (
1394
+ assignments,
1395
+ init_array_expr,
1396
+ length_expr,
1397
+ element_type,
1398
+ max_length_expr,
1399
+ depth,
1400
+ update_in_place,
1401
+ location);
1402
+ }
1403
+
1337
1404
// / We nondet-initialize enums to be equal to one of the constants defined
1338
1405
// / for their type:
1339
1406
// / int i = nondet(int);
0 commit comments