@@ -794,77 +794,68 @@ void java_object_factoryt::gen_nondet_struct_init(
794
794
// * Not if the object has already been initialised by our caller, in which
795
795
// case they will set `skip_classid`
796
796
// * Not if we're re-initializing an existing object (i.e. update_in_place)
797
-
798
- bool skip_special_string_fields = false ;
799
-
800
- if (!is_sub &&
801
- !skip_classid &&
802
- update_in_place != update_in_placet::MUST_UPDATE_IN_PLACE)
797
+ // * Always if it has a string type. Strings should not be partially updated,
798
+ // and the `length` and `data` components of string types need to be
799
+ // generated differently from object fields in the general case, see
800
+ // \ref java_object_factoryt::initialize_nondet_string_fields.
801
+
802
+ const bool is_char_sequence =
803
+ java_string_library_preprocesst::implements_java_char_sequence (struct_type);
804
+ const bool has_length_and_data =
805
+ struct_type.has_component (" length" ) && struct_type.has_component (" data" );
806
+ const bool is_string_type = is_char_sequence && has_length_and_data;
807
+ const bool has_string_input_values =
808
+ !object_factory_parameters.string_input_values .empty ();
809
+
810
+ if (is_string_type && has_string_input_values && !skip_classid)
811
+ { // We're dealing with a string and we should set fixed input values.
812
+ // We create a switch statement where each case is an assignment
813
+ // of one of the fixed input strings to the input variable in question
814
+ const alternate_casest cases = get_string_input_values_code (
815
+ expr, object_factory_parameters.string_input_values , symbol_table);
816
+ assignments.add (generate_nondet_switch (
817
+ id2string (object_factory_parameters.function_id ),
818
+ cases,
819
+ java_int_type (),
820
+ ID_java,
821
+ location,
822
+ symbol_table));
823
+ }
824
+ else if (
825
+ (!is_sub && !skip_classid &&
826
+ update_in_place != update_in_placet::MUST_UPDATE_IN_PLACE) ||
827
+ is_string_type)
803
828
{
804
- class_identifier = struct_tag;
829
+ // Add an initial all-zero write. Most of the fields of this will be
830
+ // overwritten, but it helps to have a whole-structure write that analysis
831
+ // passes can easily recognise leaves no uninitialised state behind.
805
832
806
- const bool is_char_sequence =
807
- java_string_library_preprocesst
808
- ::implements_java_char_sequence (struct_type);
809
- const bool has_length_and_data =
810
- struct_type.has_component (" length" ) && struct_type.has_component (" data" );
811
- const bool has_string_input_values =
812
- !object_factory_parameters.string_input_values .empty ();
813
-
814
- if (is_char_sequence && has_length_and_data && has_string_input_values)
815
- { // We're dealing with a string and we should set fixed input values.
816
- skip_special_string_fields = true ;
817
-
818
- // We create a switch statement where each case is an assignment
819
- // of one of the fixed input strings to the input variable in question
820
-
821
- const alternate_casest cases =
822
- get_string_input_values_code (
823
- expr,
824
- object_factory_parameters.string_input_values ,
825
- symbol_table);
826
- assignments.add (generate_nondet_switch (
827
- id2string (object_factory_parameters.function_id ),
828
- cases,
829
- java_int_type (),
830
- ID_java,
833
+ // This code mirrors the `remove_java_new` pass:
834
+ auto initial_object = zero_initializer (expr.type (), source_locationt (), ns);
835
+ CHECK_RETURN (initial_object.has_value ());
836
+ class_identifier = struct_tag;
837
+ const irep_idt qualified_clsid = " java::" + id2string (class_identifier);
838
+ set_class_identifier (
839
+ to_struct_expr (*initial_object), ns, struct_tag_typet (qualified_clsid));
840
+
841
+ // If the initialised type is a special-cased String type (one with length
842
+ // and data fields introduced by string-library preprocessing), initialise
843
+ // those fields with nondet values
844
+ if (is_string_type)
845
+ { // We're dealing with a string
846
+ initialize_nondet_string_fields (
847
+ to_struct_expr (*initial_object),
848
+ assignments,
849
+ object_factory_parameters.min_nondet_string_length ,
850
+ object_factory_parameters.max_nondet_string_length ,
831
851
location,
832
- symbol_table));
833
- }
834
- else
835
- {
836
- // Add an initial all-zero write. Most of the fields of this will be
837
- // overwritten, but it helps to have a whole-structure write that analysis
838
- // passes can easily recognise leaves no uninitialised state behind.
839
-
840
- // This code mirrors the `remove_java_new` pass:
841
- auto initial_object =
842
- zero_initializer (expr.type (), source_locationt (), ns);
843
- CHECK_RETURN (initial_object.has_value ());
844
- const irep_idt qualified_clsid = " java::" + id2string (class_identifier);
845
- set_class_identifier (
846
- to_struct_expr (*initial_object), ns, struct_tag_typet (qualified_clsid));
847
-
848
- // If the initialised type is a special-cased String type (one with length
849
- // and data fields introduced by string-library preprocessing), initialise
850
- // those fields with nondet values
851
- if (is_char_sequence && has_length_and_data)
852
- { // We're dealing with a string
853
- skip_special_string_fields = true ;
854
- initialize_nondet_string_fields (
855
- to_struct_expr (*initial_object),
856
- assignments,
857
- object_factory_parameters.min_nondet_string_length ,
858
- object_factory_parameters.max_nondet_string_length ,
859
- location,
860
- object_factory_parameters.function_id ,
861
- symbol_table,
862
- object_factory_parameters.string_printable ,
863
- allocate_objects);
864
- }
865
-
866
- assignments.add (code_assignt (expr, *initial_object));
852
+ object_factory_parameters.function_id ,
853
+ symbol_table,
854
+ object_factory_parameters.string_printable ,
855
+ allocate_objects);
867
856
}
857
+
858
+ assignments.add (code_assignt (expr, *initial_object));
868
859
}
869
860
870
861
for (const auto &component : components)
@@ -890,7 +881,7 @@ void java_object_factoryt::gen_nondet_struct_init(
890
881
code.add_source_location () = location;
891
882
assignments.add (code);
892
883
}
893
- else if (skip_special_string_fields && (name == " length" || name == " data" ))
884
+ else if (is_string_type && (name == " length" || name == " data" ))
894
885
{
895
886
// In this case these were set up above.
896
887
continue ;
0 commit comments