@@ -99,7 +99,7 @@ has_enum_type(const exprt &expr, const symbol_table_baset &symbol_table)
99
99
// / \param declaring_class_type: type of the class where \p expr is declared.
100
100
// / \return `true` if \p expr has an enum type and is declared within the
101
101
// / definition of that same type, `false` otherwise.
102
- bool is_enum_with_type_equal_to_declaring_type (
102
+ static bool is_enum_with_type_equal_to_declaring_type (
103
103
const exprt &expr,
104
104
const symbol_table_baset &symbol_table,
105
105
const java_class_typet &declaring_class_type)
@@ -188,9 +188,8 @@ static bool has_nondet_length(const jsont &json)
188
188
if (!json.is_object ())
189
189
return false ;
190
190
const auto &json_object = to_json_object (json);
191
- if (json_object.find (" @nondetLength" ) != json_object.end ())
192
- return (json[" @nondetLength" ].is_true ());
193
- return false ;
191
+ auto nondet_it = json_object.find (" @nondetLength" );
192
+ return nondet_it != json_object.end () && nondet_it->second .is_true ();
194
193
}
195
194
196
195
// / For typed versions of primitive, string or array types, looks up their
@@ -438,63 +437,82 @@ static void allocate_array(
438
437
info.block .add (assign);
439
438
}
440
439
440
+ // / Declare a non-deterministic length expression
441
+ // / \param[out] allocate: allocation functor
442
+ // / \param[out] code: code block to which code will get appended
443
+ // / \param loc: location for the created code
444
+ // / \return the length expression that has been non-deterministically created
445
+ static symbol_exprt nondet_length (
446
+ allocate_objectst &allocate,
447
+ code_blockt &code,
448
+ source_locationt loc)
449
+ {
450
+ const symbol_exprt length_expr = allocate.allocate_automatic_local_object (
451
+ java_int_type (), " user_specified_array_length" );
452
+ code.add (code_assignt{
453
+ length_expr, side_effect_expr_nondett{java_int_type (), std::move (loc)}});
454
+ code.add (code_assumet{binary_predicate_exprt{
455
+ length_expr, ID_ge, from_integer (0 , java_int_type ())}});
456
+ return length_expr;
457
+ }
458
+
441
459
// / One of the cases in the recursive algorithm: the case where \p expr
442
- // / represents an array.
443
- // / The length of the array is given by a symbol: \p given_length_expr if it is
444
- // / specified (this will be the case when there are two or more reference-equal
445
- // / arrays), or a fresh symbol otherwise.
446
- // / If \p given_length_expr is specified, we assume that an array with this
447
- // / symbol as its length has already been allocated and that \p expr has been
448
- // / assigned to it.
449
- // / Either way, the length symbol stores a nondet integer, and we add
450
- // / constraints on this: if "nondetLength" is specified in \p json, then the
451
- // / number of elements specified in \p json should be the minimum length of the
452
- // / array. Otherwise the number of elements should be the exact length of the
453
- // / array.
460
+ // / represents an array which is not flagged with `@nondetLength`.
461
+ // / The length of the array is given by symbol \p given_length_expr.
462
+ // / We assume that an array with this symbol as its length has already been
463
+ // / allocated and that \p expr has been assigned to it.
464
+ // / We constraint the length of the array to be the number of elements, which
465
+ // / is known and constant.
454
466
// / For the assignment of the array elements, see
455
467
// / \ref assign_array_data_component_from_json.
456
468
// / For the overall algorithm, see \ref assign_from_json_rec.
457
- static void assign_array_from_json (
469
+ static void assign_det_length_array_from_json (
458
470
const exprt &expr,
459
471
const jsont &json,
460
- const optionalt<symbol_exprt> &given_length_expr,
472
+ const exprt &given_length_expr,
461
473
const optionalt<std::string> &type_from_array,
462
474
object_creation_infot &info)
463
475
{
464
476
PRECONDITION (is_java_array_type (expr.type ()));
465
477
const auto &element_type =
466
478
java_array_element_type (to_struct_tag_type (expr.type ().subtype ()));
479
+ const json_arrayt json_array = get_untyped_array (json, element_type);
480
+ const auto number_of_elements =
481
+ from_integer (json_array.size (), java_int_type ());
482
+ info.block .add (
483
+ code_assumet{equal_exprt{given_length_expr, number_of_elements}});
484
+ assign_array_data_component_from_json (expr, json, type_from_array, info);
485
+ }
467
486
468
- exprt length_expr;
469
- if (given_length_expr)
470
- length_expr = *given_length_expr;
471
- else
472
- {
473
- length_expr = info.allocate_objects .allocate_automatic_local_object (
474
- java_int_type (), " user_specified_array_length" );
475
- info.block .add (code_assignt{
476
- length_expr, side_effect_expr_nondett{java_int_type (), info.loc }});
477
- info.block .add (code_assumet{binary_predicate_exprt{
478
- length_expr, ID_ge, from_integer (0 , java_int_type ())}});
479
- allocate_array (expr, length_expr, info);
480
- }
487
+ // / One of the cases in the recursive algorithm: the case where \p expr
488
+ // / represents an array which is flagged with @nondetLength.
489
+ // / The length of the array is given by symbol \p given_length_expr.
490
+ // / We assume that an array with this symbol as its length has already been
491
+ // / allocated and that \p expr has been assigned to it.
492
+ // / We constrain the length of the array to be greater or equal to the number
493
+ // / of elements specified in \p json.
494
+ // / For the assignment of the array elements, see
495
+ // / \ref assign_array_data_component_from_json.
496
+ // / For the overall algorithm, see \ref assign_from_json_rec.
497
+ static void assign_nondet_length_array_from_json (
498
+ const exprt &expr,
499
+ const jsont &json,
500
+ const exprt &given_length_expr,
501
+ const optionalt<std::string> &type_from_array,
502
+ object_creation_infot &info)
503
+ {
504
+ PRECONDITION (is_java_array_type (expr.type ()));
505
+ const auto &element_type =
506
+ java_array_element_type (to_struct_tag_type (expr.type ().subtype ()));
481
507
const json_arrayt json_array = get_untyped_array (json, element_type);
482
508
const auto number_of_elements =
483
509
from_integer (json_array.size (), java_int_type ());
484
- info.block .add (code_assumet{
485
- binary_predicate_exprt{length_expr, ID_ge, number_of_elements}});
486
- if (has_nondet_length (json))
487
- {
488
- info.block .add (code_assumet{binary_predicate_exprt{
489
- length_expr,
510
+ info.block .add (code_assumet{and_exprt{
511
+ binary_predicate_exprt{given_length_expr, ID_ge, number_of_elements},
512
+ binary_predicate_exprt{
513
+ given_length_expr,
490
514
ID_le,
491
- from_integer (info.max_user_array_length , java_int_type ())}});
492
- }
493
- else
494
- {
495
- info.block .add (code_assumet{
496
- binary_predicate_exprt{length_expr, ID_le, number_of_elements}});
497
- }
515
+ from_integer (info.max_user_array_length , java_int_type ())}}});
498
516
assign_array_data_component_from_json (expr, json, type_from_array, info);
499
517
}
500
518
@@ -771,8 +789,18 @@ static void assign_reference_from_json(
771
789
{
772
790
if (is_java_array_type (expr.type ()))
773
791
{
774
- assign_array_from_json (
775
- reference.expr , json, reference.array_length , type_from_array, info);
792
+ INVARIANT (
793
+ reference.array_length , " an array reference should store its length" );
794
+ if (has_nondet_length (json))
795
+ {
796
+ assign_nondet_length_array_from_json (
797
+ reference.expr , json, *reference.array_length , type_from_array, info);
798
+ }
799
+ else
800
+ {
801
+ assign_det_length_array_from_json (
802
+ reference.expr , json, *reference.array_length , type_from_array, info);
803
+ }
776
804
}
777
805
else
778
806
assign_struct_from_json (dereference_exprt (reference.expr ), json, info);
@@ -810,7 +838,26 @@ void assign_from_json_rec(
810
838
assign_reference_from_json (expr, json, type_from_array, info);
811
839
}
812
840
else if (is_java_array_type (expr.type ()))
813
- assign_array_from_json (expr, json, {}, type_from_array, info);
841
+ {
842
+ if (has_nondet_length (json))
843
+ {
844
+ const exprt length =
845
+ nondet_length (info.allocate_objects , info.block , info.loc );
846
+ allocate_array (expr, length, info);
847
+ assign_nondet_length_array_from_json (
848
+ expr, json, length, type_from_array, info);
849
+ }
850
+ else
851
+ {
852
+ PRECONDITION (is_java_array_type (expr.type ()));
853
+ const auto &element_type =
854
+ java_array_element_type (to_struct_tag_type (expr.type ().subtype ()));
855
+ const std::size_t length = get_untyped_array (json, element_type).size ();
856
+ allocate_array (expr, from_integer (length, java_int_type ()), info);
857
+ assign_array_data_component_from_json (
858
+ expr, json, type_from_array, info);
859
+ }
860
+ }
814
861
else if (
815
862
const auto runtime_type =
816
863
::runtime_type (json, type_from_array, info.symbol_table))
0 commit comments