Skip to content

Commit d5740b3

Browse files
authored
Merge pull request #4161 from smowton/smowton/fix/object-factory-keep-struct-tags
Java object factory: retain tagged types
2 parents 795cf7f + 328bc04 commit d5740b3

22 files changed

+305
-28
lines changed

jbmc/src/java_bytecode/java_object_factory.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,11 @@ void java_object_factoryt::gen_pointer_target_init(
249249
PRECONDITION(expr.type().id() == ID_pointer);
250250
PRECONDITION(update_in_place != update_in_placet::MAY_UPDATE_IN_PLACE);
251251

252-
if(target_type.id() == ID_struct)
252+
const typet &followed_target_type = ns.follow(target_type);
253+
254+
if(followed_target_type.id() == ID_struct)
253255
{
254-
const auto &target_class_type = to_java_class_type(target_type);
256+
const auto &target_class_type = to_java_class_type(followed_target_type);
255257
if(has_prefix(id2string(target_class_type.get_tag()), "java::array["))
256258
{
257259
gen_nondet_array_init(
@@ -565,10 +567,11 @@ void java_object_factoryt::gen_nondet_pointer_init(
565567
// When we visit for 2nd time a type AND the maximum depth is exceeded, we set
566568
// the pointer to NULL instead of recursively initializing the struct to which
567569
// it points.
568-
const typet &subtype=ns.follow(pointer_type.subtype());
569-
if(subtype.id()==ID_struct)
570+
const typet &subtype = pointer_type.subtype();
571+
const typet &followed_subtype = ns.follow(subtype);
572+
if(followed_subtype.id() == ID_struct)
570573
{
571-
const struct_typet &struct_type=to_struct_type(subtype);
574+
const struct_typet &struct_type = to_struct_type(followed_subtype);
572575
const irep_idt &struct_tag=struct_type.get_tag();
573576

574577
// If this is a recursive type of some kind AND the depth is exceeded, set
@@ -604,7 +607,9 @@ void java_object_factoryt::gen_nondet_pointer_init(
604607
// decide to do this for all types, we should do it here.
605608
// Note also that this logic is mirrored in
606609
// ci_lazy_methodst::initialize_instantiated_classes.
607-
if(const auto class_type = type_try_dynamic_cast<java_class_typet>(subtype))
610+
if(
611+
const auto class_type =
612+
type_try_dynamic_cast<java_class_typet>(followed_subtype))
608613
{
609614
if(class_type->get_base("java::java.lang.Enum") && !must_be_null)
610615
{
@@ -1024,8 +1029,8 @@ void java_object_factoryt::gen_nondet_init(
10241029
update_in_placet update_in_place,
10251030
const source_locationt &location)
10261031
{
1027-
const typet &type = override_type.has_value() ? ns.follow(*override_type)
1028-
: ns.follow(expr.type());
1032+
const typet &type = override_type.has_value() ? *override_type : expr.type();
1033+
const typet &followed_type = ns.follow(type);
10291034

10301035
if(type.id()==ID_pointer)
10311036
{
@@ -1049,9 +1054,9 @@ void java_object_factoryt::gen_nondet_init(
10491054
update_in_place,
10501055
location);
10511056
}
1052-
else if(type.id()==ID_struct)
1057+
else if(followed_type.id() == ID_struct)
10531058
{
1054-
const struct_typet struct_type=to_struct_type(type);
1059+
const struct_typet struct_type = to_struct_type(followed_type);
10551060

10561061
// If we are about to initialize a generic class (as a superclass object
10571062
// for a different object), add its concrete types to the map and delete

jbmc/unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ SRC += java_bytecode/ci_lazy_methods/lazy_load_lambdas.cpp \
4444
java_bytecode/java_bytecode_parser/parse_java_class.cpp \
4545
java_bytecode/java_bytecode_parser/parse_java_field.cpp \
4646
java_bytecode/java_object_factory/gen_nondet_string_init.cpp \
47+
java_bytecode/java_object_factory/struct_tag_types.cpp \
4748
java_bytecode/java_replace_nondet/replace_nondet.cpp \
4849
java_bytecode/java_string_library_preprocess/convert_exprt_to_string_exprt.cpp \
4950
java_bytecode/java_types/erase_type_arguments.cpp \

jbmc/unit/java-testing-utils/require_goto_statements.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ const irep_idt &require_goto_statements::require_struct_component_assignment(
315315
const std::vector<codet> &entry_point_instructions,
316316
const symbol_tablet &symbol_table)
317317
{
318+
namespacet ns(symbol_table);
319+
318320
// First we need to find the assignments to the component belonging to
319321
// the structure_name object
320322
const auto &component_assignments =
@@ -361,14 +363,13 @@ const irep_idt &require_goto_statements::require_struct_component_assignment(
361363
// After we have found the declaration of the final assignment's
362364
// right hand side, then we want to identify that the type
363365
// is the one we expect, e.g.:
364-
// struct java.lang.Integer { __CPROVER_string @class_identifier; }
365-
// tmp_object_factory$2;
366+
// struct java.lang.Integer tmp_object_factory$2;
366367
const auto &component_declaration =
367368
require_goto_statements::require_declaration_of_name(
368369
component_tmp_name, entry_point_instructions);
369-
REQUIRE(component_declaration.symbol().type().id() == ID_struct);
370+
REQUIRE(component_declaration.symbol().type().id() == ID_struct_tag);
370371
const auto &component_struct =
371-
to_struct_type(component_declaration.symbol().type());
372+
ns.follow_tag(to_struct_tag_type(component_declaration.symbol().type()));
372373
REQUIRE(component_struct.get(ID_name) == component_type_name);
373374

374375
return component_tmp_name;

jbmc/unit/java_bytecode/goto_program_generics/generic_parameters_test.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,9 @@ SCENARIO(
316316

317317
// Trace the assignments back to the declaration of the generic type
318318
// and verify that it is what we expect.
319-
const auto &tmp_object_struct =
320-
to_struct_type(tmp_object_declaration.symbol().type());
321-
REQUIRE(tmp_object_struct.get_tag() == "Wrapper");
319+
const auto &tmp_object_struct_tag =
320+
to_struct_tag_type(tmp_object_declaration.symbol().type());
321+
REQUIRE(tmp_object_struct_tag.get_identifier() == "java::Wrapper");
322322

323323
THEN("Object 'v' has field 'field' of type IWrapper")
324324
{
@@ -366,9 +366,9 @@ SCENARIO(
366366

367367
// Trace the assignments back to the declaration of the generic type
368368
// and verify that it is what we expect.
369-
const auto &tmp_object_struct =
370-
to_struct_type(tmp_object_declaration.symbol().type());
371-
REQUIRE(tmp_object_struct.get_tag() == "Wrapper");
369+
const auto &tmp_object_struct_tag =
370+
to_struct_tag_type(tmp_object_declaration.symbol().type());
371+
REQUIRE(tmp_object_struct_tag.get_identifier() == "java::Wrapper");
372372

373373
THEN(
374374
"Object 'v' has field 'field' of type Object (upper bound of the "
@@ -416,11 +416,11 @@ SCENARIO(
416416

417417
// Trace the assignments back to the declaration of the generic type
418418
// and verify that it is what we expect.
419-
const auto &tmp_object_struct =
420-
to_struct_type(tmp_object_declaration.symbol().type());
419+
const auto &tmp_object_struct_tag =
420+
to_struct_tag_type(tmp_object_declaration.symbol().type());
421421
REQUIRE(
422-
tmp_object_struct.get_tag() ==
423-
"GenericFields$GenericInnerOuter$Outer");
422+
tmp_object_struct_tag.get_identifier() ==
423+
"java::GenericFields$GenericInnerOuter$Outer");
424424

425425
THEN("Object 'v' has field 'field' of type InnerClass")
426426
{
@@ -481,11 +481,11 @@ SCENARIO(
481481

482482
// Trace the assignments back to the declaration of the generic type
483483
// and verify that it is what we expect.
484-
const auto &tmp_object_struct =
485-
to_struct_type(tmp_object_declaration.symbol().type());
484+
const auto &tmp_object_struct_tag =
485+
to_struct_tag_type(tmp_object_declaration.symbol().type());
486486
REQUIRE(
487-
tmp_object_struct.get_tag() ==
488-
"GenericFields$GenericRewriteParameter$A");
487+
tmp_object_struct_tag.get_identifier() ==
488+
"java::GenericFields$GenericRewriteParameter$A");
489489

490490
THEN("Object 'v' has field 'value' of type Integer")
491491
{
264 Bytes
Binary file not shown.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
public class A {
3+
4+
public B b;
5+
public C c;
6+
7+
}
8+
9+
class B { }
10+
11+
class C { }
228 Bytes
Binary file not shown.
228 Bytes
Binary file not shown.
235 Bytes
Binary file not shown.
849 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
public class HasArray {
3+
4+
public D[] ds;
5+
6+
}
7+
8+
class D { }
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
public class HasEnum {
3+
4+
public E e;
5+
6+
}
7+
8+
enum E { x, y, z }
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
public class HasGeneric {
3+
4+
public Generic<String> s;
5+
public Generic<Integer> t;
6+
public OtherGeneric<String> u;
7+
8+
}
9+
10+
class Generic<T> {
11+
T t;
12+
}
13+
14+
class OtherGeneric<T> {
15+
Generic<T> gen;
16+
}
Binary file not shown.
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
public class Root {
3+
4+
// This one isn't used in the tests; it just references other classes
5+
// to get them loaded.
6+
7+
A a;
8+
HasArray ha;
9+
HasEnum he;
10+
HasGeneric hg;
11+
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
java_bytecode
22
java_object_factory
3+
java-testing-utils
34
langapi # should go away
45
testing-utils
56
util

0 commit comments

Comments
 (0)