Skip to content

Commit d424d92

Browse files
committed
Java string types: properly mirror the class graph seen in the JDK
We expect that StringBuilder and StringBuffer should derive from AbstractStringBuilder, and that String and CharSequence should derive directly from Object.
1 parent de7b8d2 commit d424d92

File tree

1 file changed

+26
-16
lines changed

1 file changed

+26
-16
lines changed

jbmc/src/java_bytecode/java_string_library_preprocess.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

@@ -230,7 +238,6 @@ void java_string_library_preprocesst::add_string_type(
230238
new_string_type.set_tag(class_name);
231239
new_string_type.set_name(class_symbol_name);
232240
new_string_type.set_access(ID_public);
233-
new_string_type.add_base(struct_tag_typet("java::java.lang.Object"));
234241

235242
std::vector<irep_idt> bases = get_string_type_base_classes(class_name);
236243
for(const irep_idt &base_name : bases)
@@ -247,10 +254,12 @@ void java_string_library_preprocesst::add_string_type(
247254
auto &string_type = to_java_class_type(string_symbol->type);
248255

249256
string_type.components().resize(3);
250-
string_type.components()[0].set_name("@java.lang.Object");
251-
string_type.components()[0].set_pretty_name("@java.lang.Object");
252-
string_type.components()[0].type() =
253-
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;
254263
string_type.components()[1].set_name("length");
255264
string_type.components()[1].set_pretty_name("length");
256265
string_type.components()[1].type()=string_length_type();
@@ -794,14 +803,15 @@ codet java_string_library_preprocesst::code_assign_components_to_java_string(
794803

795804
if(is_constructor)
796805
{
797-
// A String has a field Object with @clsid = String
798-
struct_tag_typet jlo_tag("java::java.lang.Object");
799-
struct_exprt jlo_init({}, jlo_tag);
800-
irep_idt clsid = get_tag(lhs.type().subtype());
806+
// Initialise the supertype with the appropriate classid:
801807
namespacet ns(symbol_table);
802-
java_root_class_init(jlo_init, ns.follow_tag(jlo_tag), clsid);
803-
804-
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());
805815
return code_assignt(checked_dereference(lhs), struct_rhs);
806816
}
807817
else

0 commit comments

Comments
 (0)