@@ -20,6 +20,7 @@ Date: April 2017
2020#include < util/allocate_objects.h>
2121#include < util/arith_tools.h>
2222#include < util/c_types.h>
23+ #include < util/expr_initializer.h>
2324#include < util/fresh_symbol.h>
2425#include < util/refined_string_type.h>
2526#include < util/std_code.h>
@@ -188,6 +189,17 @@ java_string_library_preprocesst::get_string_type_base_classes(
188189
189190 std::vector<irep_idt> bases;
190191 bases.reserve (3 );
192+
193+ // StringBuilder and StringBuffer derive from AbstractStringBuilder;
194+ // other String types (String and CharSequence) derive directly from Object.
195+ if (
196+ class_name == " java.lang.StringBuilder" ||
197+ class_name == " java.lang.StringBuffer" )
198+ bases.push_back (" java.lang.AbstractStringBuilder" );
199+ else
200+ bases.push_back (" java.lang.Object" );
201+
202+ // Interfaces:
191203 if (class_name != " java.lang.CharSequence" )
192204 {
193205 bases.push_back (" java.io.Serializable" );
@@ -196,10 +208,6 @@ java_string_library_preprocesst::get_string_type_base_classes(
196208 if (class_name == " java.lang.String" )
197209 bases.push_back (" java.lang.Comparable" );
198210
199- if (class_name == " java.lang.StringBuilder" ||
200- class_name == " java.lang.StringBuffer" )
201- bases.push_back (" java.lang.AbstractStringBuilder" );
202-
203211 return bases;
204212}
205213
@@ -209,36 +217,55 @@ java_string_library_preprocesst::get_string_type_base_classes(
209217void java_string_library_preprocesst::add_string_type (
210218 const irep_idt &class_name, symbol_tablet &symbol_table)
211219{
212- java_class_typet string_type;
213- string_type.set_tag (class_name);
214- string_type.set_name (" java::" + id2string (class_name));
220+ irep_idt class_symbol_name = " java::" + id2string (class_name);
221+ symbolt tmp_string_symbol;
222+ tmp_string_symbol.name = class_symbol_name;
223+ symbolt *string_symbol = nullptr ;
224+ bool already_exists = symbol_table.move (tmp_string_symbol, string_symbol);
225+
226+ if (already_exists)
227+ {
228+ // A library has already defined this type -- we'll replace its
229+ // components with those required for internal string modelling, but
230+ // otherwise leave it alone.
231+ to_java_class_type (string_symbol->type ).components ().clear ();
232+ }
233+ else
234+ {
235+ // No definition of this type exists -- define it as it usually occurs in
236+ // the JDK:
237+ java_class_typet new_string_type;
238+ new_string_type.set_tag (class_name);
239+ new_string_type.set_name (class_symbol_name);
240+ new_string_type.set_access (ID_public);
241+
242+ std::vector<irep_idt> bases = get_string_type_base_classes (class_name);
243+ for (const irep_idt &base_name : bases)
244+ new_string_type.add_base (
245+ struct_tag_typet (" java::" + id2string (base_name)));
246+
247+ string_symbol->base_name = id2string (class_name);
248+ string_symbol->pretty_name = id2string (class_name);
249+ string_symbol->type = new_string_type;
250+ string_symbol->is_type = true ;
251+ string_symbol->mode = ID_java;
252+ }
253+
254+ auto &string_type = to_java_class_type (string_symbol->type );
255+
215256 string_type.components ().resize (3 );
216- string_type.components ()[0 ].set_name (" @java.lang.Object" );
217- string_type.components ()[0 ].set_pretty_name (" @java.lang.Object" );
218- string_type.components ()[0 ].type () =
219- struct_tag_typet (" java::java.lang.Object" );
257+ const struct_tag_typet &supertype = string_type.bases ().front ().type ();
258+ irep_idt supertype_component_name =
259+ " @" + id2string (supertype.get_identifier ()).substr (6 );
260+ string_type.components ()[0 ].set_name (supertype_component_name);
261+ string_type.components ()[0 ].set_pretty_name (supertype_component_name);
262+ string_type.components ()[0 ].type () = supertype;
220263 string_type.components ()[1 ].set_name (" length" );
221264 string_type.components ()[1 ].set_pretty_name (" length" );
222265 string_type.components ()[1 ].type ()=string_length_type ();
223266 string_type.components ()[2 ].set_name (" data" );
224267 string_type.components ()[2 ].set_pretty_name (" data" );
225268 string_type.components ()[2 ].type () = pointer_type (java_char_type ());
226- string_type.set_access (ID_public);
227- string_type.add_base (struct_tag_typet (" java::java.lang.Object" ));
228-
229- std::vector<irep_idt> bases = get_string_type_base_classes (class_name);
230- for (const irep_idt &base_name : bases)
231- string_type.add_base (struct_tag_typet (" java::" + id2string (base_name)));
232-
233- symbolt tmp_string_symbol;
234- tmp_string_symbol.name =" java::" +id2string (class_name);
235- symbolt *string_symbol=nullptr ;
236- symbol_table.move (tmp_string_symbol, string_symbol);
237- string_symbol->base_name =id2string (class_name);
238- string_symbol->pretty_name =id2string (class_name);
239- string_symbol->type =string_type;
240- string_symbol->is_type =true ;
241- string_symbol->mode = ID_java;
242269}
243270
244271// / calls string_refine_preprocesst::process_operands with a list of parameters.
@@ -776,14 +803,15 @@ codet java_string_library_preprocesst::code_assign_components_to_java_string(
776803
777804 if (is_constructor)
778805 {
779- // A String has a field Object with @clsid = String
780- struct_tag_typet jlo_tag (" java::java.lang.Object" );
781- struct_exprt jlo_init ({}, jlo_tag);
782- irep_idt clsid = get_tag (lhs.type ().subtype ());
806+ // Initialise the supertype with the appropriate classid:
783807 namespacet ns (symbol_table);
784- java_root_class_init (jlo_init, ns.follow_tag (jlo_tag), clsid);
785-
786- struct_exprt struct_rhs ({jlo_init, rhs_length, rhs_array}, deref.type ());
808+ const struct_typet &lhs_type = to_struct_type (ns.follow (deref.type ()));
809+ auto zero_base_object = *zero_initializer (
810+ lhs_type.components ().front ().type (), source_locationt{}, ns);
811+ set_class_identifier (
812+ to_struct_expr (zero_base_object), ns, to_struct_tag_type (deref.type ()));
813+ struct_exprt struct_rhs (
814+ {zero_base_object, rhs_length, rhs_array}, deref.type ());
787815 return code_assignt (checked_dereference (lhs), struct_rhs);
788816 }
789817 else
0 commit comments