Skip to content

Commit e1ecf26

Browse files
authored
Merge pull request #3545 from smowton/smowton/fix/string-refinement-dont-reinit-object
String preprocessing: don't re-initialise objects that already exist
2 parents a4fe9b6 + e6fca9b commit e1ecf26

File tree

2 files changed

+56
-33
lines changed

2 files changed

+56
-33
lines changed

jbmc/src/java_bytecode/java_string_library_preprocess.cpp

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,9 @@ refined_string_exprt java_string_library_preprocesst::string_expr_of_function(
818818
/// \param rhs_array: pointer to the array to assign
819819
/// \param rhs_length: length of the array to assign
820820
/// \param symbol_table: symbol table
821+
/// \param is_constructor: the assignment happens in the context of a
822+
/// constructor, so the whole object should be initialised, not just its
823+
/// length and data fields.
821824
/// \return return the following code:
822825
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
823826
/// lhs = { {Object}, length=rhs_length, data=rhs_array }
@@ -826,41 +829,55 @@ codet java_string_library_preprocesst::code_assign_components_to_java_string(
826829
const exprt &lhs,
827830
const exprt &rhs_array,
828831
const exprt &rhs_length,
829-
const symbol_table_baset &symbol_table)
832+
const symbol_table_baset &symbol_table,
833+
bool is_constructor)
830834
{
831835
PRECONDITION(implements_java_char_sequence_pointer(lhs.type()));
832836
dereference_exprt deref=checked_dereference(lhs, lhs.type().subtype());
833837

834-
// A String has a field Object with @clsid = String
835-
const symbolt &jlo_symbol=*symbol_table.lookup("java::java.lang.Object");
836-
const struct_typet &jlo_struct=to_struct_type(jlo_symbol.type);
837-
struct_exprt jlo_init(jlo_struct);
838-
irep_idt clsid = get_tag(lhs.type().subtype());
839-
java_root_class_init(jlo_init, jlo_struct, clsid);
840-
841-
struct_exprt struct_rhs(deref.type());
842-
struct_rhs.copy_to_operands(jlo_init);
843-
struct_rhs.copy_to_operands(rhs_length);
844-
struct_rhs.copy_to_operands(rhs_array);
845-
return code_assignt(
846-
checked_dereference(lhs, lhs.type().subtype()), struct_rhs);
838+
if(is_constructor)
839+
{
840+
// A String has a field Object with @clsid = String
841+
const symbolt &jlo_symbol = *symbol_table.lookup("java::java.lang.Object");
842+
const struct_typet &jlo_struct = to_struct_type(jlo_symbol.type);
843+
struct_exprt jlo_init(jlo_struct);
844+
irep_idt clsid = get_tag(lhs.type().subtype());
845+
java_root_class_init(jlo_init, jlo_struct, clsid);
846+
847+
struct_exprt struct_rhs(deref.type());
848+
struct_rhs.copy_to_operands(jlo_init);
849+
struct_rhs.copy_to_operands(rhs_length);
850+
struct_rhs.copy_to_operands(rhs_array);
851+
return code_assignt(
852+
checked_dereference(lhs, lhs.type().subtype()), struct_rhs);
853+
}
854+
else
855+
{
856+
return code_blockt(
857+
{code_assignt(get_length(deref, symbol_table), rhs_length),
858+
code_assignt(get_data(deref, symbol_table), rhs_array)});
859+
}
847860
}
848861

849862
/// Produce code for an assignemnt of a string expr to a Java string.
850863
/// \param lhs: an expression representing a java string
851864
/// \param rhs: a string expression
852865
/// \param symbol_table: symbol table
866+
/// \param is_constructor: the assignment happens in the context of a
867+
/// constructor, so the whole object should be initialised, not just its
868+
/// length and data fields.
853869
/// \return return the following code:
854870
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
855871
/// lhs = { {Object}, length=rhs.length, data=rhs.data }
856872
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
857873
codet java_string_library_preprocesst::code_assign_string_expr_to_java_string(
858874
const exprt &lhs,
859875
const refined_string_exprt &rhs,
860-
const symbol_table_baset &symbol_table)
876+
const symbol_table_baset &symbol_table,
877+
bool is_constructor)
861878
{
862879
return code_assign_components_to_java_string(
863-
lhs, rhs.content(), rhs.length(), symbol_table);
880+
lhs, rhs.content(), rhs.length(), symbol_table, is_constructor);
864881
}
865882

866883
/// \param lhs: a string expression
@@ -1044,14 +1061,14 @@ code_blockt java_string_library_preprocesst::make_float_to_string_code(
10441061

10451062
// We do not check the condition of the first element in the list as it
10461063
// will be reached only if all other conditions are not satisfied.
1047-
codet tmp_code=code_assign_string_expr_to_java_string(
1048-
str, string_expr_list[0], symbol_table);
1064+
codet tmp_code = code_assign_string_expr_to_java_string(
1065+
str, string_expr_list[0], symbol_table, true);
10491066
for(std::size_t i=1; i<condition_list.size(); i++)
10501067
{
10511068
code_ifthenelset ife;
10521069
ife.cond()=condition_list[i];
10531070
ife.then_case() = code_assign_string_expr_to_java_string(
1054-
str, string_expr_list[i], symbol_table);
1071+
str, string_expr_list[i], symbol_table, true);
10551072
ife.else_case()=tmp_code;
10561073
tmp_code=ife;
10571074
}
@@ -1067,9 +1084,8 @@ code_blockt java_string_library_preprocesst::make_float_to_string_code(
10671084
/// \param type: the type of the function call
10681085
/// \param loc: location in program
10691086
/// \param symbol_table: the symbol table to populate
1070-
/// \param ignore_first_arg: boolean flag telling that the first argument should
1071-
/// not be part of the arguments of the call (but only used to be assigned the
1072-
/// result)
1087+
/// \param is_constructor: the function being made is a constructor, so the
1088+
/// whole object should be initialised, not just its length and data fields.
10731089
/// \return code for the `String.<init>(args)` function:
10741090
///
10751091
/// cprover_string_length = fun(arg).length;
@@ -1083,14 +1099,14 @@ code_blockt java_string_library_preprocesst::make_init_function_from_call(
10831099
const java_method_typet &type,
10841100
const source_locationt &loc,
10851101
symbol_table_baset &symbol_table,
1086-
bool ignore_first_arg)
1102+
bool is_constructor)
10871103
{
10881104
java_method_typet::parameterst params = type.parameters();
10891105

10901106
// The first parameter is the object to be initialized
10911107
PRECONDITION(!params.empty());
10921108
const symbol_exprt arg_this(params[0].get_identifier(), params[0].type());
1093-
if(ignore_first_arg)
1109+
if(is_constructor)
10941110
params.erase(params.begin());
10951111

10961112
// Holder for output code
@@ -1105,7 +1121,8 @@ code_blockt java_string_library_preprocesst::make_init_function_from_call(
11051121

11061122
// arg_this <- string_expr
11071123
code.add(
1108-
code_assign_string_expr_to_java_string(arg_this, string_expr, symbol_table),
1124+
code_assign_string_expr_to_java_string(
1125+
arg_this, string_expr, symbol_table, is_constructor),
11091126
loc);
11101127

11111128
return code;
@@ -1466,7 +1483,7 @@ code_blockt java_string_library_preprocesst::make_string_format_code(
14661483
type.return_type(), loc, function_id, symbol_table, code);
14671484
code.add(
14681485
code_assign_string_expr_to_java_string(
1469-
java_string, string_expr, symbol_table),
1486+
java_string, string_expr, symbol_table, true),
14701487
loc);
14711488
code.add(code_returnt(java_string), loc);
14721489
return code;
@@ -1535,7 +1552,8 @@ code_blockt java_string_library_preprocesst::make_object_get_class_code(
15351552
exprt string1 = allocate_fresh_string(
15361553
string_ptr_type, loc, function_id, symbol_table, code);
15371554
code.add(
1538-
code_assign_string_expr_to_java_string(string1, string_expr1, symbol_table),
1555+
code_assign_string_expr_to_java_string(
1556+
string1, string_expr1, symbol_table, true),
15391557
loc);
15401558

15411559
// > class1 = Class.forName(string1)
@@ -1615,7 +1633,8 @@ java_string_library_preprocesst::make_string_returning_function_from_call(
16151633
exprt str = allocate_fresh_string(
16161634
type.return_type(), loc, function_name, symbol_table, code);
16171635
code.add(
1618-
code_assign_string_expr_to_java_string(str, string_expr, symbol_table),
1636+
code_assign_string_expr_to_java_string(
1637+
str, string_expr, symbol_table, true),
16191638
loc);
16201639

16211640
// Return value
@@ -1659,7 +1678,8 @@ code_blockt java_string_library_preprocesst::make_copy_string_code(
16591678
exprt str = allocate_fresh_string(
16601679
type.return_type(), loc, function_id, symbol_table, code);
16611680
code.add(
1662-
code_assign_string_expr_to_java_string(str, string_expr, symbol_table),
1681+
code_assign_string_expr_to_java_string(
1682+
str, string_expr, symbol_table, true),
16631683
loc);
16641684

16651685
// Return value
@@ -1702,7 +1722,8 @@ code_blockt java_string_library_preprocesst::make_copy_constructor_code(
17021722
// Assign string_expr to `this` object
17031723
symbol_exprt arg_this(params[0].get_identifier(), params[0].type());
17041724
code.add(
1705-
code_assign_string_expr_to_java_string(arg_this, string_expr, symbol_table),
1725+
code_assign_string_expr_to_java_string(
1726+
arg_this, string_expr, symbol_table, true),
17061727
loc);
17071728

17081729
return code;

jbmc/src/java_bytecode/java_string_library_preprocess.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,14 @@ class java_string_library_preprocesst:public messaget
265265
const exprt &lhs,
266266
const exprt &rhs_array,
267267
const exprt &rhs_length,
268-
const symbol_table_baset &symbol_table);
268+
const symbol_table_baset &symbol_table,
269+
bool is_constructor);
269270

270271
codet code_assign_string_expr_to_java_string(
271272
const exprt &lhs,
272273
const refined_string_exprt &rhs,
273-
const symbol_table_baset &symbol_table);
274+
const symbol_table_baset &symbol_table,
275+
bool is_constructor);
274276

275277
void code_assign_java_string_to_string_expr(
276278
const refined_string_exprt &lhs,
@@ -296,7 +298,7 @@ class java_string_library_preprocesst:public messaget
296298
const java_method_typet &type,
297299
const source_locationt &loc,
298300
symbol_table_baset &symbol_table,
299-
bool ignore_first_arg = true);
301+
bool is_constructor = true);
300302

301303
code_blockt make_assign_and_return_function_from_call(
302304
const irep_idt &function_name,

0 commit comments

Comments
 (0)