Skip to content

Commit c24de41

Browse files
Remove code that is now unreachable
To use the builtin format function, the java entry point is now CProverString.format, so we can remove the legacy code which was handling String.format directly.
1 parent 10924e1 commit c24de41

File tree

3 files changed

+22
-331
lines changed

3 files changed

+22
-331
lines changed

jbmc/src/java_bytecode/java_string_library_preprocess.cpp

Lines changed: 0 additions & 272 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,278 +1101,6 @@ code_blockt java_string_library_preprocesst::make_assign_function_from_call(
11011101
function_id, type, loc, symbol_table, false);
11021102
}
11031103

1104-
/// Adds to the code an assignment of the form
1105-
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1106-
/// type_name tmp_type_name
1107-
/// tmp_type_name = ((Classname*)arg_i)->value
1108-
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1109-
/// and returns `tmp_typename`.
1110-
/// In case the class corresponding to `type_name` is not available in
1111-
/// `symbol_table`, the variable is declared but not assigned.
1112-
/// Used to access the values of the arguments of `String.format`.
1113-
/// \param object: an expression representing a reference to an object
1114-
/// \param type_name: name of the corresponding primitive type, this can be
1115-
/// one of the following: ID_boolean, ID_char, ID_byte, ID_short, ID_int,
1116-
/// ID_long, ID_float, ID_double, ID_void
1117-
/// \param loc: a location in the source
1118-
/// \param function_id: the name of the function
1119-
/// \param symbol_table: the symbol table
1120-
/// \param code: code block to which we are adding some assignments
1121-
/// \return An expression containing a symbol `tmp_type_name` where `type_name`
1122-
/// is the given argument (ie. boolean, char etc.). Which represents the
1123-
/// primitive value contained in the given object.
1124-
optionalt<symbol_exprt>
1125-
java_string_library_preprocesst::get_primitive_value_of_object(
1126-
const exprt &object, irep_idt type_name, const source_locationt &loc,
1127-
const irep_idt &function_id, symbol_table_baset &symbol_table,
1128-
code_blockt &code) {
1129-
optionalt<struct_tag_typet> object_type;
1130-
1131-
typet value_type;
1132-
if (type_name == ID_boolean) {
1133-
value_type = java_boolean_type();
1134-
object_type = struct_tag_typet("java::java.lang.Boolean");
1135-
} else if (type_name == ID_char) {
1136-
value_type = java_char_type();
1137-
object_type = struct_tag_typet("java::java.lang.Character");
1138-
} else if (type_name == ID_byte) {
1139-
value_type = java_byte_type();
1140-
object_type = struct_tag_typet("java::java.lang.Byte");
1141-
} else if (type_name == ID_short) {
1142-
value_type = java_short_type();
1143-
object_type = struct_tag_typet("java::java.lang.Short");
1144-
} else if (type_name == ID_int) {
1145-
value_type = java_int_type();
1146-
object_type = struct_tag_typet("java::java.lang.Integer");
1147-
} else if (type_name == ID_long) {
1148-
value_type = java_long_type();
1149-
object_type = struct_tag_typet("java::java.lang.Long");
1150-
} else if (type_name == ID_float) {
1151-
value_type = java_float_type();
1152-
object_type = struct_tag_typet("java::java.lang.Float");
1153-
} else if (type_name == ID_double) {
1154-
value_type = java_double_type();
1155-
object_type = struct_tag_typet("java::java.lang.Double");
1156-
} else if (type_name == ID_void)
1157-
return {};
1158-
else
1159-
UNREACHABLE;
1160-
1161-
DATA_INVARIANT(object_type.has_value(), "must have symbol for primitive");
1162-
1163-
// declare tmp_type_name to hold the value
1164-
const std::string aux_name = "tmp_" + id2string(type_name);
1165-
const symbolt &symbol =
1166-
fresh_java_symbol(value_type, aux_name, loc, function_id, symbol_table);
1167-
const auto value = symbol.symbol_expr();
1168-
1169-
// Check that the type of the object is in the symbol table,
1170-
// otherwise there is no safe way of finding its value.
1171-
if (const auto maybe_symbol =
1172-
symbol_table.lookup(object_type->get_identifier())) {
1173-
const struct_typet &struct_type = to_struct_type(maybe_symbol->type);
1174-
// Check that the type has a value field
1175-
const struct_union_typet::componentt &value_comp =
1176-
struct_type.get_component("value");
1177-
if (!value_comp.is_nil()) {
1178-
const pointer_typet struct_pointer_type = pointer_type(struct_type);
1179-
dereference_exprt deref{typecast_exprt(object, struct_pointer_type),
1180-
struct_pointer_type.subtype()};
1181-
const member_exprt deref_value{std::move(deref), value_comp.get_name(),
1182-
value_comp.type()};
1183-
code.add(code_assignt(value, deref_value), loc);
1184-
return value;
1185-
}
1186-
}
1187-
1188-
warning() << object_type->get_identifier()
1189-
<< " not available to format function" << eom;
1190-
code.add(code_declt(value), loc);
1191-
return value;
1192-
}
1193-
1194-
/// Helper for format function. Returns the expression:
1195-
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1196-
/// *((void**)(argv->data)+index )
1197-
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1198-
/// which corresponds to the object at position `index` in `argv`.
1199-
/// \param argv: reference to an array of references
1200-
/// \param index: index of the desired object
1201-
/// \return An expression representing the object at position `index` of `argv`.
1202-
dereference_exprt
1203-
java_string_library_preprocesst::get_object_at_index(const exprt &argv,
1204-
std::size_t index) {
1205-
const dereference_exprt deref_objs{argv, argv.type().subtype()};
1206-
const pointer_typet empty_pointer = pointer_type(java_void_type());
1207-
const pointer_typet pointer_of_pointer = pointer_type(empty_pointer);
1208-
const member_exprt data_member{deref_objs, "data", pointer_of_pointer};
1209-
const plus_exprt data_pointer_plus_index{
1210-
data_member, from_integer(index, java_int_type()), data_member.type()};
1211-
return dereference_exprt{data_pointer_plus_index,
1212-
data_pointer_plus_index.type().subtype()};
1213-
}
1214-
1215-
/// Helper for format function. Adds code:
1216-
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1217-
/// string_expr arg_i_string_expr;
1218-
/// int tmp_int;
1219-
/// float tmp_float;
1220-
/// char tmp_char;
1221-
/// boolean tmp_boolean;
1222-
/// Object* arg_i=get_object_at_index(argv, index)
1223-
/// if(arg_i.@class_identifier=="java::java.lang.String")
1224-
/// {
1225-
/// arg_i_string_expr = (string_expr)((String*)arg_i_as_string)
1226-
/// }
1227-
/// tmp_int=((Integer)arg_i)->value
1228-
/// tmp_float=((Float)arg_i)->value
1229-
/// tmp_char=((Char)arg_i)->value
1230-
/// tmp_boolean=((Boolean)arg_i)->value
1231-
/// arg_i_struct = { string_expr=arg_i_string_expr;
1232-
/// integer=tmp_int; float=tmp_float; char=tmp_char; boolean=tmp_boolean}
1233-
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1234-
/// and returns `arg_i_struct`.
1235-
///
1236-
/// TODO: date_time and hash code are not implemented
1237-
/// \param argv: reference to an array of references
1238-
/// \param index: index of the desired argument
1239-
/// \param structured_type: type for arguments of the internal format function
1240-
/// \param loc: a location in the source
1241-
/// \param function_id: function the generated expression will be used in
1242-
/// \param symbol_table: the symbol table
1243-
/// \param code: code block to which we are adding some assignments
1244-
/// \return An expression of type `structured_type` representing the possible
1245-
/// values of the argument at position `index` of `argv`.
1246-
struct_exprt java_string_library_preprocesst::make_argument_for_format(
1247-
const exprt &argv, std::size_t index, const struct_typet &structured_type,
1248-
const source_locationt &loc, const irep_idt &function_id,
1249-
symbol_table_baset &symbol_table, code_blockt &code) {
1250-
// Declarations of the fields of arg_i_struct
1251-
// arg_i_struct is { arg_i_string_expr, tmp_int, tmp_char, ... }
1252-
struct_exprt arg_i_struct({}, structured_type);
1253-
std::list<exprt> field_exprs;
1254-
for (const auto &comp : structured_type.components()) {
1255-
const irep_idt &name = comp.get_name();
1256-
const typet &type = comp.type();
1257-
exprt field_expr;
1258-
if (name != "string_expr") {
1259-
std::string tmp_name = "tmp_" + id2string(name);
1260-
const symbolt &field_symbol =
1261-
fresh_java_symbol(type, tmp_name, loc, function_id, symbol_table);
1262-
auto field_symbol_expr = field_symbol.symbol_expr();
1263-
field_expr = field_symbol_expr;
1264-
code.add(code_declt(field_symbol_expr), loc);
1265-
} else
1266-
field_expr =
1267-
make_nondet_string_expr(loc, function_id, symbol_table, code);
1268-
1269-
field_exprs.push_back(field_expr);
1270-
arg_i_struct.copy_to_operands(field_expr);
1271-
}
1272-
1273-
// arg_i = argv[index]
1274-
const exprt obj = get_object_at_index(argv, index);
1275-
const symbolt &object_symbol = fresh_java_symbol(
1276-
obj.type(), "tmp_format_obj", loc, function_id, symbol_table);
1277-
const symbol_exprt arg_i = object_symbol.symbol_expr();
1278-
1279-
allocate_objectst allocate_objects(ID_java, loc, function_id, symbol_table);
1280-
1281-
code_blockt tmp;
1282-
allocate_objects.allocate_dynamic_object(tmp, arg_i, arg_i.type().subtype());
1283-
allocate_objects.declare_created_symbols(code);
1284-
code.append(tmp);
1285-
1286-
code.add(code_assignt(arg_i, obj), loc);
1287-
code.add(code_assumet(not_exprt(equal_exprt(
1288-
arg_i, null_pointer_exprt(to_pointer_type(arg_i.type()))))),
1289-
loc);
1290-
1291-
code_blockt code_not_null;
1292-
1293-
// Assigning all the fields of arg_i_struct
1294-
for (const auto &comp : structured_type.components()) {
1295-
const irep_idt &name = comp.get_name();
1296-
exprt field_expr = field_exprs.front();
1297-
field_exprs.pop_front();
1298-
1299-
if (name == "string_expr") {
1300-
const pointer_typet string_pointer =
1301-
java_reference_type(struct_tag_typet("java::java.lang.String"));
1302-
const typecast_exprt arg_i_as_string{arg_i, string_pointer};
1303-
code_assign_java_string_to_string_expr(to_string_expr(field_expr),
1304-
arg_i_as_string, loc, symbol_table,
1305-
code_not_null);
1306-
} else if (name == ID_int || name == ID_float || name == ID_char ||
1307-
name == ID_boolean) {
1308-
const auto value = get_primitive_value_of_object(
1309-
arg_i, name, loc, function_id, symbol_table, code_not_null);
1310-
if (value.has_value())
1311-
code_not_null.add(code_assignt(field_expr, *value), loc);
1312-
else
1313-
code_not_null.add(code_assignt(field_expr, nil_exprt()), loc);
1314-
} else {
1315-
// TODO: date_time and hash_code not implemented
1316-
}
1317-
}
1318-
1319-
code.add(code_not_null, loc);
1320-
return arg_i_struct;
1321-
}
1322-
1323-
/// Used to provide code for the Java String.format function.
1324-
///
1325-
/// TODO: date_time and hash code are not implemented, and we set a limit of
1326-
/// 10 arguments
1327-
/// \param type: type of the function call
1328-
/// \param loc: location in the program_invocation_name
1329-
/// \param function_id: function the generated code will be used in
1330-
/// \param symbol_table: symbol table
1331-
/// \return Code implementing the Java String.format function. Since the exact
1332-
/// class of the arguments is not known, we give as argument to the internal
1333-
// format function a structure containing the different possible types.
1334-
code_blockt java_string_library_preprocesst::make_string_format_code(
1335-
const java_method_typet &type, const source_locationt &loc,
1336-
const irep_idt &function_id, symbol_table_baset &symbol_table) {
1337-
PRECONDITION(type.parameters().size() == 2);
1338-
code_blockt code;
1339-
exprt::operandst args = process_parameters(type.parameters(), loc,
1340-
function_id, symbol_table, code);
1341-
INVARIANT(args.size() == 2, "String.format should have two arguments");
1342-
1343-
// The argument can be:
1344-
// a string, an integer, a floating point, a character, a boolean,
1345-
// an object of which we take the hash code, or a date/time
1346-
struct_typet structured_type({{"string_expr", refined_string_type},
1347-
{ID_int, java_int_type()},
1348-
{ID_float, java_float_type()},
1349-
{ID_char, java_char_type()},
1350-
{ID_boolean, java_boolean_type()},
1351-
// TODO: hash_code not implemented for now
1352-
{"hashcode", java_int_type()},
1353-
// TODO: date_time type not implemented for now
1354-
{"date_time", java_int_type()}});
1355-
structured_type.set_tag(CPROVER_PREFIX "string_formatter_variant");
1356-
1357-
// We will process arguments so that each is converted to a `struct_exprt`
1358-
// containing each possible type used in format specifiers.
1359-
std::vector<exprt> processed_args;
1360-
processed_args.push_back(args[0]);
1361-
for (std::size_t i = 0; i < MAX_FORMAT_ARGS; ++i)
1362-
processed_args.push_back(make_argument_for_format(
1363-
args[1], i, structured_type, loc, function_id, symbol_table, code));
1364-
1365-
const refined_string_exprt string_expr = string_expr_of_function(
1366-
ID_cprover_string_format_func, processed_args, loc, symbol_table, code);
1367-
const exprt java_string = allocate_fresh_string(
1368-
type.return_type(), loc, function_id, symbol_table, code);
1369-
code.add(code_assign_string_expr_to_java_string(java_string, string_expr,
1370-
symbol_table, true),
1371-
loc);
1372-
code.add(code_returnt(java_string), loc);
1373-
return code;
1374-
}
1375-
13761104
/// Used to provide our own implementation of the java.lang.Object.getClass()
13771105
/// function.
13781106
/// \param type: type of the function called

jbmc/src/java_bytecode/java_string_library_preprocess.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,6 @@ class java_string_library_preprocesst:public messaget
151151
const irep_idt &function_id,
152152
symbol_table_baset &symbol_table);
153153

154-
code_blockt make_string_format_code(const java_method_typet &type,
155-
const source_locationt &loc,
156-
const irep_idt &function_id,
157-
symbol_table_baset &symbol_table);
158-
159154
code_blockt make_copy_string_code(
160155
const java_method_typet &type,
161156
const source_locationt &loc,
@@ -312,20 +307,6 @@ class java_string_library_preprocesst:public messaget
312307
const java_method_typet &type,
313308
const source_locationt &loc,
314309
symbol_table_baset &symbol_table);
315-
316-
struct_exprt make_argument_for_format(const exprt &argv, std::size_t index,
317-
const struct_typet &structured_type,
318-
const source_locationt &loc,
319-
const irep_idt &function_id,
320-
symbol_table_baset &symbol_table,
321-
code_blockt &code);
322-
323-
optionalt<symbol_exprt> get_primitive_value_of_object(
324-
const exprt &object, irep_idt type_name, const source_locationt &loc,
325-
const irep_idt &function_id, symbol_table_baset &symbol_table,
326-
code_blockt &code);
327-
328-
dereference_exprt get_object_at_index(const exprt &argv, std::size_t index);
329310
};
330311

331312
exprt make_nondet_infinite_char_array(

src/solvers/strings/string_constraint_generator_format.cpp

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -239,17 +239,6 @@ static std::vector<format_elementt> parse_format_string(std::string s)
239239
return al;
240240
}
241241

242-
/// Helper for add_axioms_for_format_specifier
243-
/// \param expr: a structured expression
244-
/// \param component_name: name of the desired component
245-
/// \return Expression in the component of `expr` named `component_name`.
246-
static exprt get_component_in_struct(const struct_exprt &expr,
247-
irep_idt component_name) {
248-
const struct_typet &type = to_struct_type(expr.type());
249-
std::size_t number = type.component_number(component_name);
250-
return expr.operands()[number];
251-
}
252-
253242
/// Parse `s` and add axioms ensuring the output corresponds to the output of
254243
/// String.format. Assumes the argument is a structured expression which
255244
/// contains the fields: string expr, int, float, char, boolean, hashcode,
@@ -447,6 +436,9 @@ std::pair<exprt, string_constraintst> add_axioms_for_format(
447436
if(fe.is_format_specifier())
448437
{
449438
const format_specifiert &fs = fe.get_format_specifier();
439+
std::function<exprt(const irep_idt &)> get_arg =
440+
[](const irep_idt &) -> exprt { UNREACHABLE; };
441+
450442
if(
451443
fs.conversion != format_specifiert::PERCENT_SIGN &&
452444
fs.conversion != format_specifiert::LINE_SEPARATOR)
@@ -470,36 +462,26 @@ std::pair<exprt, string_constraintst> add_axioms_for_format(
470462
arg = to_struct_expr(args[fs.index - 1]);
471463
}
472464

473-
std::function<exprt(const irep_idt &)> get_arg;
474-
if(is_refined_string_type(arg.type()))
475-
{
476-
const array_string_exprt string_arg =
477-
get_string_expr(array_pool, arg);
478-
get_arg = [string_arg](const irep_idt &id) {
479-
return format_arg_from_string(string_arg, id);
480-
};
481-
}
482-
else
483-
{
484-
INVARIANT(
485-
arg.id() == ID_struct,
486-
"format argument should be a string or a struct");
487-
get_arg = [&](const irep_idt &id) {
488-
return get_component_in_struct(to_struct_expr(arg), id);
489-
};
490-
}
491-
auto result = add_axioms_for_format_specifier(
492-
fresh_symbol,
493-
fs,
494-
get_arg,
495-
index_type,
496-
char_type,
497-
array_pool,
498-
message,
499-
ns);
500-
merge(constraints, std::move(result.second));
501-
intermediary_strings.push_back(result.first);
465+
INVARIANT(
466+
is_refined_string_type(arg.type()),
467+
"arguments of format should be strings");
468+
const array_string_exprt string_arg = get_string_expr(array_pool, arg);
469+
get_arg = [string_arg](const irep_idt &id) {
470+
return format_arg_from_string(string_arg, id);
471+
};
502472
}
473+
474+
auto result = add_axioms_for_format_specifier(
475+
fresh_symbol,
476+
fs,
477+
get_arg,
478+
index_type,
479+
char_type,
480+
array_pool,
481+
message,
482+
ns);
483+
merge(constraints, std::move(result.second));
484+
intermediary_strings.push_back(result.first);
503485
}
504486
else
505487
{

0 commit comments

Comments
 (0)