@@ -146,7 +146,8 @@ class java_object_factoryt
146
146
code_blockt &assignments,
147
147
const std::string &basename_prefix,
148
148
const exprt &min_length_expr,
149
- const exprt &max_length_expr);
149
+ const exprt &max_length_expr,
150
+ bool include_max);
150
151
151
152
void gen_method_call (
152
153
code_blockt &assignments,
@@ -384,67 +385,95 @@ void java_object_factoryt::gen_pointer_target_init(
384
385
size_t depth,
385
386
update_in_placet update_in_place)
386
387
{
387
- PRECONDITION (expr.type ().id ()== ID_pointer);
388
- PRECONDITION (update_in_place!= update_in_placet::MAY_UPDATE_IN_PLACE);
388
+ PRECONDITION (expr.type ().id () == ID_pointer);
389
+ PRECONDITION (update_in_place != update_in_placet::MAY_UPDATE_IN_PLACE);
389
390
390
- if (target_type.id ()==ID_struct &&
391
- has_prefix (
392
- id2string (to_struct_type (target_type).get_tag ()),
393
- " java::array[" ))
394
- {
395
- gen_nondet_array_init (
396
- assignments,
397
- expr,
398
- depth+1 ,
399
- update_in_place);
400
- }
401
- else
391
+ if (target_type.id () == ID_struct)
402
392
{
403
- // obtain a target pointer to initialize; if in MUST_UPDATE_IN_PLACE mode we
404
- // initialize the fields of the object pointed by `expr`; if in
405
- // NO_UPDATE_IN_PLACE then we allocate a new object, get a pointer to it
406
- // (return value of `allocate_object`), emit a statement of the form
407
- // `<expr> := address-of(<new-object>)` and recursively initialize such new
408
- // object.
409
- exprt target;
410
- if (update_in_place==update_in_placet::NO_UPDATE_IN_PLACE)
393
+ const auto &target_class_type = to_java_class_type (target_type);
394
+ if (has_prefix (id2string (target_class_type.get_tag ()), " java::array[" ))
411
395
{
412
- target=allocate_object (
413
- assignments,
414
- expr,
415
- target_type,
416
- alloc_type);
417
- INVARIANT (
418
- target.type ().id ()==ID_pointer,
419
- " Pointer-typed expression expected" );
396
+ gen_nondet_array_init (assignments, expr, depth + 1 , update_in_place);
397
+ return ;
420
398
}
421
- else
399
+ if (target_class_type. get_base ( " java::java.lang.Enum " ))
422
400
{
423
- target=expr;
401
+ // We nondet-initialize enums to be equal to one of the constants defined
402
+ // for their type:
403
+ // int i = nondet(int)
404
+ // assume(0 < = i < $VALUES.length)
405
+ // expr = $VALUES[i]
406
+ // where $VALUES is a variable generated by the Java compiler that stores
407
+ // the array that is returned by Enum.values().
408
+
409
+ const irep_idt &class_name = target_class_type.get_name ();
410
+ const symbolt &values = ns.lookup (id2string (class_name) + " .$VALUES" );
411
+
412
+ // Access members (length and data) of $VALUES array
413
+ dereference_exprt deref_expr (values.symbol_expr ());
414
+ const auto &deref_struct_type =
415
+ to_struct_type (ns.follow (deref_expr.type ()));
416
+ const auto &comps = deref_struct_type.components ();
417
+ const member_exprt length_expr (deref_expr, " length" , comps[1 ].type ());
418
+ const member_exprt enum_array_expr =
419
+ member_exprt (deref_expr, " data" , comps[2 ].type ());
420
+
421
+ const symbol_exprt &index_expr = gen_nondet_int_init (
422
+ assignments,
423
+ " enum_index_init" ,
424
+ from_integer (0 , java_int_type ()),
425
+ length_expr,
426
+ false );
427
+
428
+ // Index array using pointer arithmetic
429
+ plus_exprt plus (enum_array_expr, index_expr, enum_array_expr.type ());
430
+ const dereference_exprt arraycellref (
431
+ plus_exprt (enum_array_expr, index_expr, enum_array_expr.type ()),
432
+ enum_array_expr.type ().subtype ());
433
+ code_assignt enum_assign (expr, typecast_exprt (arraycellref, expr.type ()));
434
+ assignments.add (enum_assign);
435
+ return ;
424
436
}
437
+ }
425
438
426
- // we dereference the pointer and initialize the resulting object using a
427
- // recursive call
428
- exprt init_expr;
429
- if (target.id ()==ID_address_of)
430
- init_expr=target.op0 ();
431
- else
432
- {
433
- init_expr=
434
- dereference_exprt (target, target.type ().subtype ());
435
- }
436
- gen_nondet_init (
437
- assignments,
438
- init_expr,
439
- false , // is_sub
440
- " " , // class_identifier
441
- false , // skip_classid
442
- alloc_type,
443
- false , // override
444
- typet (), // override type immaterial
445
- depth+1 ,
446
- update_in_place);
439
+ // obtain a target pointer to initialize; if in MUST_UPDATE_IN_PLACE mode we
440
+ // initialize the fields of the object pointed by `expr`; if in
441
+ // NO_UPDATE_IN_PLACE then we allocate a new object, get a pointer to it
442
+ // (return value of `allocate_object`), emit a statement of the form
443
+ // `<expr> := address-of(<new-object>)` and recursively initialize such new
444
+ // object.
445
+ exprt target;
446
+ if (update_in_place == update_in_placet::NO_UPDATE_IN_PLACE)
447
+ {
448
+ target = allocate_object (assignments, expr, target_type, alloc_type);
449
+ INVARIANT (
450
+ target.type ().id () == ID_pointer, " Pointer-typed expression expected" );
451
+ }
452
+ else
453
+ {
454
+ target = expr;
455
+ }
456
+
457
+ // we dereference the pointer and initialize the resulting object using a
458
+ // recursive call
459
+ exprt init_expr;
460
+ if (target.id () == ID_address_of)
461
+ init_expr = target.op0 ();
462
+ else
463
+ {
464
+ init_expr = dereference_exprt (target, target.type ().subtype ());
447
465
}
466
+ gen_nondet_init (
467
+ assignments,
468
+ init_expr,
469
+ false , // is_sub
470
+ " " , // class_identifier
471
+ false , // skip_classid
472
+ alloc_type,
473
+ false , // override
474
+ typet (), // override type immaterial
475
+ depth + 1 ,
476
+ update_in_place);
448
477
}
449
478
450
479
// / Recursion-set entry owner class. If a recursion-set entry is added
@@ -1207,20 +1236,25 @@ void java_object_factoryt::gen_nondet_init(
1207
1236
}
1208
1237
}
1209
1238
1210
- // / Nondeterministically initializes an int i in the range min <= i <= max,
1239
+ // / Nondeterministically initializes an int i in the range min <= i <= max (if
1240
+ // / `include_max` is true) or min <= i < max (if `include_max` is false),
1211
1241
// / where min is the integer represented by `min_value_expr` and max is the
1212
1242
// / integer represented by `max_value_expr`.
1213
1243
// / \param [out] assignments: A code block that the initializing assignments
1214
1244
// / will be appended to.
1215
1245
// / \param basename_prefix: Used for naming the newly created symbol.
1216
1246
// / \param min_value_expr: Represents the minimum value for the integer.
1217
1247
// / \param max_value_expr: Represents the maximum value for the integer.
1248
+ // / \param include_max: true if the maximum value should be included in the
1249
+ // / range, false otherwise (i.e. if the maximum value for the integer is
1250
+ // / max_value_expr - 1).
1218
1251
// / \return A symbol expression for the resulting integer.
1219
1252
const symbol_exprt java_object_factoryt::gen_nondet_int_init (
1220
1253
code_blockt &assignments,
1221
1254
const std::string &basename_prefix,
1222
1255
const exprt &min_value_expr,
1223
- const exprt &max_value_expr)
1256
+ const exprt &max_value_expr,
1257
+ bool include_max)
1224
1258
{
1225
1259
// Allocate a new symbol for the int
1226
1260
const symbolt &int_symbol = get_fresh_aux_symbol (
@@ -1237,7 +1271,7 @@ const symbol_exprt java_object_factoryt::gen_nondet_int_init(
1237
1271
gen_nondet_init (
1238
1272
assignments,
1239
1273
int_symbol_expr,
1240
- false , // is_sub
1274
+ false , // is_sub
1241
1275
irep_idt (),
1242
1276
false , // skip_classid
1243
1277
allocation_typet::LOCAL, // immaterial, type is primitive
@@ -1250,7 +1284,8 @@ const symbol_exprt java_object_factoryt::gen_nondet_int_init(
1250
1284
const auto min_assume_expr =
1251
1285
binary_relation_exprt (int_symbol_expr, ID_ge, min_value_expr);
1252
1286
const auto max_assume_expr =
1253
- binary_relation_exprt (int_symbol_expr, ID_le, max_value_expr);
1287
+ include_max ? binary_relation_exprt (int_symbol_expr, ID_le, max_value_expr)
1288
+ : binary_relation_exprt (int_symbol_expr, ID_lt, max_value_expr);
1254
1289
assignments.add (code_assumet (min_assume_expr));
1255
1290
assignments.add (code_assumet (max_assume_expr));
1256
1291
@@ -1280,7 +1315,8 @@ void java_object_factoryt::allocate_nondet_length_array(
1280
1315
assignments,
1281
1316
" nondet_array_length" ,
1282
1317
from_integer (0 , java_int_type ()),
1283
- max_length_expr);
1318
+ max_length_expr,
1319
+ true );
1284
1320
1285
1321
side_effect_exprt java_new_array (ID_java_new_array, lhs.type ());
1286
1322
java_new_array.copy_to_operands (length_sym_expr);
0 commit comments