@@ -794,77 +794,69 @@ 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 skip_special_string_fields =
807
+ is_char_sequence && has_length_and_data;
808
+ const bool has_string_input_values =
809
+ !object_factory_parameters.string_input_values .empty ();
810
+
811
+ if (skip_special_string_fields && has_string_input_values && !skip_classid)
812
+ { // We're dealing with a string and we should set fixed input values.
813
+ // We create a switch statement where each case is an assignment
814
+ // of one of the fixed input strings to the input variable in question
815
+ const alternate_casest cases = get_string_input_values_code (
816
+ expr, object_factory_parameters.string_input_values , symbol_table);
817
+ assignments.add (generate_nondet_switch (
818
+ id2string (object_factory_parameters.function_id ),
819
+ cases,
820
+ java_int_type (),
821
+ ID_java,
822
+ location,
823
+ symbol_table));
824
+ }
825
+ else if (
826
+ (!is_sub && !skip_classid &&
827
+ update_in_place != update_in_placet::MUST_UPDATE_IN_PLACE) ||
828
+ skip_special_string_fields)
803
829
{
804
- class_identifier = struct_tag;
830
+ // Add an initial all-zero write. Most of the fields of this will be
831
+ // overwritten, but it helps to have a whole-structure write that analysis
832
+ // passes can easily recognise leaves no uninitialised state behind.
805
833
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,
834
+ // This code mirrors the `remove_java_new` pass:
835
+ auto initial_object = zero_initializer (expr.type (), source_locationt (), ns);
836
+ CHECK_RETURN (initial_object.has_value ());
837
+ class_identifier = struct_tag;
838
+ const irep_idt qualified_clsid = " java::" + id2string (class_identifier);
839
+ set_class_identifier (
840
+ to_struct_expr (*initial_object), ns, struct_tag_typet (qualified_clsid));
841
+
842
+ // If the initialised type is a special-cased String type (one with length
843
+ // and data fields introduced by string-library preprocessing), initialise
844
+ // those fields with nondet values
845
+ if (skip_special_string_fields)
846
+ { // We're dealing with a string
847
+ initialize_nondet_string_fields (
848
+ to_struct_expr (*initial_object),
849
+ assignments,
850
+ object_factory_parameters.min_nondet_string_length ,
851
+ object_factory_parameters.max_nondet_string_length ,
831
852
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));
853
+ object_factory_parameters.function_id ,
854
+ symbol_table,
855
+ object_factory_parameters.string_printable ,
856
+ allocate_objects);
867
857
}
858
+
859
+ assignments.add (code_assignt (expr, *initial_object));
868
860
}
869
861
870
862
for (const auto &component : components)
0 commit comments