@@ -394,65 +394,103 @@ void java_object_factoryt::gen_pointer_target_init(
394394 update_in_placet update_in_place,
395395 const source_locationt &location)
396396{
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);
399399
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)
409401 {
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[" ))
418404 {
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 ;
427408 }
428- else
409+ if (target_class_type. get_base ( " java::java.lang.Enum " ))
429410 {
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);
432443
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 ;
442452 }
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);
455453 }
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);
456494}
457495
458496// / 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(
12581296 gen_nondet_init (
12591297 assignments,
12601298 int_symbol_expr,
1261- false , // is_sub
1299+ false , // is_sub
12621300 irep_idt (),
12631301 false , // skip_classid
12641302 allocation_typet::LOCAL, // immaterial, type is primitive
0 commit comments