Skip to content

Commit a1bc2a2

Browse files
Merge pull request diffblue#1606 from NlightNFotis/fotis_tg1157/pretty_printing
[TG-1157] New class for specialised generic class types.
2 parents edc75fa + cbb2eff commit a1bc2a2

File tree

5 files changed

+83
-32
lines changed

5 files changed

+83
-32
lines changed

src/java_bytecode/generate_java_generic_type.cpp

+21-15
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@
1414
#include <java_bytecode/java_types.h>
1515
#include <java_bytecode/java_utils.h>
1616

17+
/// Strip the package name from a java type, for the type to be
18+
/// pretty printed (java::java.lang.Integer -> Integer).
19+
/// \param fqn_java_type The java type we want to pretty print.
20+
/// \return The pretty printed type if there was a match of the
21+
// qualifiers, or the type as it was passed otherwise.
22+
static std::string pretty_print_java_type(const std::string &fqn_java_type)
23+
{
24+
const std::string java_lang("java::java.lang.");
25+
const std::string package_name(java_class_to_package(fqn_java_type) + ".");
26+
if(package_name == java_lang)
27+
return fqn_java_type.substr(java_lang.length());
28+
return fqn_java_type;
29+
}
30+
1731
generate_java_generic_typet::generate_java_generic_typet(
1832
message_handlert &message_handler):
1933
message_handler(message_handler)
@@ -73,8 +87,8 @@ symbolt generate_java_generic_typet::operator()(
7387
pre_modification_size==after_modification_size,
7488
"All components in the original class should be in the new class");
7589

76-
const java_class_typet &new_java_class = construct_specialised_generic_type(
77-
generic_class_definition, new_tag, replacement_components);
90+
const java_specialized_generic_class_typet new_java_class =
91+
construct_specialised_generic_type(new_tag, replacement_components);
7892
const type_symbolt &class_symbol =
7993
build_symbol_from_specialised_class(new_java_class);
8094

@@ -196,14 +210,14 @@ irep_idt generate_java_generic_typet::build_generic_tag(
196210
.generic_type_arguments())
197211
{
198212
if(!first)
199-
new_tag_buffer << ",";
213+
new_tag_buffer << ", ";
200214
first=false;
201215

202216
INVARIANT(
203217
!is_java_generic_parameter(type_argument),
204218
"Only create full concretized generic types");
205219
const irep_idt &id(id2string(type_argument.subtype().get(ID_identifier)));
206-
new_tag_buffer << id2string(id);
220+
new_tag_buffer << pretty_print_java_type(id2string(id));
207221
if(is_java_array_tag(id))
208222
{
209223
const typet &element_type =
@@ -227,25 +241,17 @@ irep_idt generate_java_generic_typet::build_generic_tag(
227241
return new_tag_buffer.str();
228242
}
229243

230-
/// Build the specalised version of the specific class, with the specified
244+
/// Build the specialised version of the specific class, with the specified
231245
/// parameters and name.
232-
/// \param generic_class_definition: The generic class we are specialising
233246
/// \param new_tag: The new name for the class (like Generic<java::Float>)
234247
/// \param new_components: The specialised components
235248
/// \return The newly constructed class.
236-
java_class_typet
249+
java_specialized_generic_class_typet
237250
generate_java_generic_typet::construct_specialised_generic_type(
238-
const java_generic_class_typet &generic_class_definition,
239251
const irep_idt &new_tag,
240252
const struct_typet::componentst &new_components) const
241253
{
242-
java_class_typet specialised_class = generic_class_definition;
243-
// We are specialising the logic - so we don't want to be marked as generic
244-
specialised_class.set(ID_C_java_generics_class_type, false);
245-
specialised_class.set(ID_name, "java::" + id2string(new_tag));
246-
specialised_class.set(ID_base_name, new_tag);
247-
specialised_class.components() = new_components;
248-
return specialised_class;
254+
return java_specialized_generic_class_typet{new_tag, new_components};
249255
}
250256

251257
/// Construct the symbol to be moved into the symbol table

src/java_bytecode/generate_java_generic_type.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ class generate_java_generic_typet
3333
const java_generic_class_typet &replacement_type,
3434
const java_generic_typet &generic_reference) const;
3535

36-
java_class_typet construct_specialised_generic_type(
37-
const java_generic_class_typet &generic_class_definition,
36+
java_specialized_generic_class_typet construct_specialised_generic_type(
3837
const irep_idt &new_tag,
3938
const struct_typet::componentst &new_components) const;
4039

src/java_bytecode/java_types.h

+51
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,55 @@ void get_dependencies_from_generic_parameters(
374374
const typet &,
375375
std::set<irep_idt> &);
376376

377+
class java_specialized_generic_class_typet : public java_class_typet
378+
{
379+
public:
380+
/// Build the specialised version of the specific class, with the specified
381+
/// parameters and name.
382+
/// \param new_tag: The new name for the class (like Generic<java::Float>)
383+
/// \param new_components: The specialised components
384+
/// \return The newly constructed class.
385+
java_specialized_generic_class_typet(
386+
const irep_idt &new_tag,
387+
const struct_typet::componentst &new_components)
388+
{
389+
set(ID_C_specialized_generic_java_class, true);
390+
// We are specialising the logic - so we don't want to be marked as generic
391+
set(ID_C_java_generics_class_type, false);
392+
set(ID_name, "java::" + id2string(new_tag));
393+
set(ID_base_name, id2string(new_tag));
394+
components() = new_components;
395+
const std::string &class_tag = id2string(new_tag);
396+
set_tag(class_tag.substr(0, class_tag.find('<')));
397+
}
398+
};
399+
400+
inline bool is_java_specialized_generic_class_type(const typet &type)
401+
{
402+
return type.get_bool(ID_C_specialized_generic_java_class);
403+
}
404+
405+
inline bool is_java_specialized_generic_class_type(typet &type)
406+
{
407+
return type.get_bool(ID_C_specialized_generic_java_class);
408+
}
409+
410+
inline java_specialized_generic_class_typet
411+
to_java_specialized_generic_class_type(const typet &type)
412+
{
413+
INVARIANT(
414+
is_java_specialized_generic_class_type(type),
415+
"Tried to convert a type that was not a specialised generic java class");
416+
return static_cast<const java_specialized_generic_class_typet &>(type);
417+
}
418+
419+
inline java_specialized_generic_class_typet
420+
to_java_specialized_generic_class_type(typet &type)
421+
{
422+
INVARIANT(
423+
is_java_specialized_generic_class_type(type),
424+
"Tried to convert a type that was not a specialised generic java class");
425+
return static_cast<const java_specialized_generic_class_typet &>(type);
426+
}
427+
377428
#endif // CPROVER_JAVA_BYTECODE_JAVA_TYPES_H

src/util/irep_ids.def

+1
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ IREP_ID_ONE(integer_dereference)
830830
IREP_ID_TWO(C_java_generic_parameter, #java_generic_parameter)
831831
IREP_ID_TWO(C_java_generic_type, #java_generic_type)
832832
IREP_ID_TWO(C_java_generics_class_type, #java_generics_class_type)
833+
IREP_ID_TWO(C_specialized_generic_java_class, #specialized_generic_java_class)
833834
IREP_ID_TWO(generic_types, #generic_types)
834835
IREP_ID_TWO(type_variables, #type_variables)
835836
IREP_ID_ONE(havoc_object)

unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp

+9-15
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ SCENARIO(
4040
"generate_java_generic_type_from_file",
4141
"[core][java_bytecode][generate_java_generic_type]")
4242
{
43-
auto expected_symbol=
44-
"java::generic_two_fields$bound_element<java::java.lang.Integer>";
43+
auto expected_symbol = "java::generic_two_fields$bound_element<Integer>";
4544

4645
GIVEN("A generic java type with two generic fields and a concrete "
4746
"substitution")
@@ -56,8 +55,8 @@ SCENARIO(
5655
REQUIRE(new_symbol_table.has_symbol(expected_symbol));
5756
THEN("The class should contain two instantiated fields.")
5857
{
59-
const auto &class_symbol=new_symbol_table.lookup(
60-
"java::generic_two_fields$bound_element<java::java.lang.Integer>");
58+
const auto &class_symbol = new_symbol_table.lookup(
59+
"java::generic_two_fields$bound_element<Integer>");
6160
const typet &symbol_type=class_symbol->type;
6261

6362
REQUIRE(symbol_type.id()==ID_struct);
@@ -89,10 +88,8 @@ SCENARIO(
8988
"generate_java_generic_type_from_file_two_params",
9089
"[core][java_bytecode][generate_java_generic_type]")
9190
{
92-
auto expected_symbol=
93-
"java::generic_two_parameters$KeyValuePair"
94-
"<java::java.lang.String,"
95-
"java::java.lang.Integer>";
91+
auto expected_symbol =
92+
"java::generic_two_parameters$KeyValuePair<String, Integer>";
9693

9794
GIVEN("A generic java type with two generic parameters, like a Hashtable")
9895
{
@@ -133,10 +130,8 @@ SCENARIO(
133130
// After we have loaded the class and converted the generics,
134131
// the presence of these two symbols in the symbol table is
135132
// proof enough that we did the work we needed to do correctly.
136-
auto first_expected_symbol=
137-
"java::generic_two_instances$element<java::java.lang.Boolean>";
138-
auto second_expected_symbol=
139-
"java::generic_two_instances$element<java::java.lang.Integer>";
133+
auto first_expected_symbol = "java::generic_two_instances$element<Boolean>";
134+
auto second_expected_symbol = "java::generic_two_instances$element<Integer>";
140135

141136
GIVEN("A generic java type with a field that refers to another generic with"
142137
" an uninstantiated parameter.")
@@ -284,9 +279,8 @@ SCENARIO(
284279
"There should be a specialised version of the class in the symbol "
285280
"table")
286281
{
287-
const irep_idt specialised_class_name = id2string(harness_class) + "$" +
288-
id2string(inner_class) +
289-
"<java::java.lang.Float>";
282+
const irep_idt specialised_class_name =
283+
id2string(harness_class) + "$" + id2string(inner_class) + "<Float>";
290284
REQUIRE(new_symbol_table.has_symbol(specialised_class_name));
291285

292286
const symbolt test_class_symbol =

0 commit comments

Comments
 (0)