@@ -394,65 +394,103 @@ void java_object_factoryt::gen_pointer_target_init(
394
394
update_in_placet update_in_place,
395
395
const source_locationt &location)
396
396
{
397
- PRECONDITION (expr.type ().id ()== ID_pointer);
398
- PRECONDITION (update_in_place!= update_in_placet::MAY_UPDATE_IN_PLACE);
397
+ PRECONDITION (expr.type ().id () == ID_pointer);
398
+ PRECONDITION (update_in_place != update_in_placet::MAY_UPDATE_IN_PLACE);
399
399
400
- if (target_type.id ()==ID_struct &&
401
- has_prefix (
402
- id2string (to_struct_type (target_type).get_tag ()),
403
- " java::array[" ))
404
- {
405
- gen_nondet_array_init (
406
- assignments, expr, depth + 1 , update_in_place, location);
407
- }
408
- else
400
+ if (target_type.id () == ID_struct)
409
401
{
410
- // obtain a target pointer to initialize; if in MUST_UPDATE_IN_PLACE mode we
411
- // initialize the fields of the object pointed by `expr`; if in
412
- // NO_UPDATE_IN_PLACE then we allocate a new object, get a pointer to it
413
- // (return value of `allocate_object`), emit a statement of the form
414
- // `<expr> := address-of(<new-object>)` and recursively initialize such new
415
- // object.
416
- exprt target;
417
- if (update_in_place==update_in_placet::NO_UPDATE_IN_PLACE)
402
+ const auto &target_class_type = to_java_class_type (target_type);
403
+ if (has_prefix (id2string (target_class_type.get_tag ()), " java::array[" ))
418
404
{
419
- target=allocate_object (
420
- assignments,
421
- expr,
422
- target_type,
423
- alloc_type);
424
- INVARIANT (
425
- target.type ().id ()==ID_pointer,
426
- " Pointer-typed expression expected" );
405
+ gen_nondet_array_init (
406
+ assignments, expr, depth + 1 , update_in_place, location);
407
+ return ;
427
408
}
428
- else
409
+ if (target_class_type. get_base ( " java::java.lang.Enum " ))
429
410
{
430
- target=expr;
431
- }
411
+ // We nondet-initialize enums to be equal to one of the constants defined
412
+ // for their type:
413
+ // int i = nondet(int)
414
+ // assume(0 < = i < $VALUES.length)
415
+ // expr = $VALUES[i]
416
+ // where $VALUES is a variable generated by the Java compiler that stores
417
+ // the array that is returned by Enum.values().
418
+
419
+ const irep_idt &class_name = target_class_type.get_name ();
420
+ const irep_idt values_name = id2string (class_name) + " .$VALUES" ;
421
+ INVARIANT (
422
+ ns.get_symbol_table ().has_symbol (values_name),
423
+ " The $VALUES array (populated by clinit_wrapper) should be in the "
424
+ " symbol table" );
425
+ const symbolt &values = ns.lookup (values_name);
426
+
427
+ // Access members (length and data) of $VALUES array
428
+ dereference_exprt deref_expr (values.symbol_expr ());
429
+ const auto &deref_struct_type =
430
+ to_struct_type (ns.follow (deref_expr.type ()));
431
+ PRECONDITION (is_valid_java_array (deref_struct_type));
432
+ const auto &comps = deref_struct_type.components ();
433
+ const member_exprt length_expr (deref_expr, " length" , comps[1 ].type ());
434
+ const member_exprt enum_array_expr =
435
+ member_exprt (deref_expr, " data" , comps[2 ].type ());
436
+
437
+ const symbol_exprt &index_expr = gen_nondet_int_init (
438
+ assignments,
439
+ " enum_index_init" ,
440
+ from_integer (0 , java_int_type ()),
441
+ minus_exprt (length_expr, from_integer (1 , java_int_type ())),
442
+ location);
432
443
433
- // we dereference the pointer and initialize the resulting object using a
434
- // recursive call
435
- exprt init_expr;
436
- if (target.id ()==ID_address_of)
437
- init_expr=target.op0 ();
438
- else
439
- {
440
- init_expr=
441
- dereference_exprt (target, target.type ().subtype ());
444
+ // Generate statement using pointer arithmetic to access array element:
445
+ // expr = (expr.type())*(enum_array_expr + index_expr);
446
+ plus_exprt plus (enum_array_expr, index_expr);
447
+ const dereference_exprt arraycellref (
448
+ plus, enum_array_expr.type ().subtype ());
449
+ code_assignt enum_assign (expr, typecast_exprt (arraycellref, expr.type ()));
450
+ assignments.add (enum_assign);
451
+ return ;
442
452
}
443
- gen_nondet_init (
444
- assignments,
445
- init_expr,
446
- false , // is_sub
447
- " " , // class_identifier
448
- false , // skip_classid
449
- alloc_type,
450
- false ,
451
- typet (),
452
- depth + 1 ,
453
- update_in_place,
454
- location);
455
453
}
454
+
455
+ // obtain a target pointer to initialize; if in MUST_UPDATE_IN_PLACE mode we
456
+ // initialize the fields of the object pointed by `expr`; if in
457
+ // NO_UPDATE_IN_PLACE then we allocate a new object, get a pointer to it
458
+ // (return value of `allocate_object`), emit a statement of the form
459
+ // `<expr> := address-of(<new-object>)` and recursively initialize such new
460
+ // object.
461
+ exprt target;
462
+ if (update_in_place == update_in_placet::NO_UPDATE_IN_PLACE)
463
+ {
464
+ target = allocate_object (assignments, expr, target_type, alloc_type);
465
+ INVARIANT (
466
+ target.type ().id () == ID_pointer, " Pointer-typed expression expected" );
467
+ }
468
+ else
469
+ {
470
+ target = expr;
471
+ }
472
+
473
+ // we dereference the pointer and initialize the resulting object using a
474
+ // recursive call
475
+ exprt init_expr;
476
+ if (target.id () == ID_address_of)
477
+ init_expr = target.op0 ();
478
+ else
479
+ {
480
+ init_expr = dereference_exprt (target, target.type ().subtype ());
481
+ }
482
+ gen_nondet_init (
483
+ assignments,
484
+ init_expr,
485
+ false , // is_sub
486
+ " " , // class_identifier
487
+ false , // skip_classid
488
+ alloc_type,
489
+ false , // override
490
+ typet (), // override type immaterial
491
+ depth + 1 ,
492
+ update_in_place,
493
+ location);
456
494
}
457
495
458
496
// / Recursion-set entry owner class. If a recursion-set entry is added
@@ -1258,7 +1296,7 @@ const symbol_exprt java_object_factoryt::gen_nondet_int_init(
1258
1296
gen_nondet_init (
1259
1297
assignments,
1260
1298
int_symbol_expr,
1261
- false , // is_sub
1299
+ false , // is_sub
1262
1300
irep_idt (),
1263
1301
false , // skip_classid
1264
1302
allocation_typet::LOCAL, // immaterial, type is primitive
0 commit comments