Skip to content

Commit 80eb6a6

Browse files
committed
TG-1877: Include array pointer types in needed classes
Lazy methods attempts a pointer graph walk starting from the main function's parameters to determine what classes may exist before the main function is entered; for example, starting at f(A a) implies that an A instance may exist, and if A itself has a B field that too might exist, and so on. However, until now this failed to account for array-typed parameters and fields. This commit amends gather_field_types to account for this special case. This also adds a test for the generic parameter case, which is not solved yet.
1 parent e2cda1a commit 80eb6a6

File tree

15 files changed

+129
-9
lines changed

15 files changed

+129
-9
lines changed
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
test.class
3+
--lazy-methods --verbosity 10 --function test.g
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
elaborate java::test\.f:\(\)I
7+
VERIFICATION SUCCESSFUL
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
public class test {
3+
4+
public int f() { return 1; }
5+
6+
public static void g(test[] args) {
7+
8+
if(args == null || args.length != 1 || args[0] == null)
9+
return;
10+
asserthere.doassert(args[0].f() == 1);
11+
12+
}
13+
14+
}
15+
16+
class asserthere {
17+
18+
// Used to avoid lazy-loading currently marking any class with an
19+
// $assertionsEnabled member (i.e. any class that asserts) as needed.
20+
public static void doassert(boolean condition) { assert(condition); }
21+
22+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
test.class
3+
--lazy-methods --verbosity 10 --function test.g
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
elaborate java::test\.f:\(\)I
7+
VERIFICATION SUCCESSFUL
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
public class test {
3+
4+
public int f() { return 1; }
5+
6+
public static void g(container c) {
7+
8+
if(c == null)
9+
return;
10+
test[] args = c.test_array;
11+
if(args == null || args.length != 1 || args[0] == null)
12+
return;
13+
asserthere.doassert(args[0].f() == 1);
14+
15+
}
16+
17+
}
18+
19+
class container {
20+
public test[] test_array;
21+
}
22+
23+
class asserthere {
24+
25+
// Used to avoid lazy-loading currently marking any class with an
26+
// $assertionsEnabled member (i.e. any class that asserts) as needed.
27+
public static void doassert(boolean condition) { assert(condition); }
28+
29+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
KNOWNBUG
2+
test.class
3+
--lazy-methods --verbosity 10 --function test.g
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
elaborate java::test\.f:\(\)I
7+
VERIFICATION SUCCESSFUL
8+
--
9+
--
10+
See https://diffblue.atlassian.net/browse/TG-1877
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
public class test {
3+
4+
public int f() { return 1; }
5+
6+
public static void g(container<test> c) {
7+
8+
if(c == null)
9+
return;
10+
test[] args = c.test_array;
11+
if(args == null || args.length != 1 || args[0] == null)
12+
return;
13+
asserthere.doassert(args[0].f() == 1);
14+
15+
}
16+
17+
}
18+
19+
class container<T> {
20+
public T[] test_array;
21+
}
22+
23+
class asserthere {
24+
25+
// Used to avoid lazy-loading currently marking any class with an
26+
// $assertionsEnabled member (i.e. any class that asserts) as needed.
27+
public static void doassert(boolean condition) { assert(condition); }
28+
29+
}

src/java_bytecode/ci_lazy_methods.cpp

+25-9
Original file line numberDiff line numberDiff line change
@@ -477,17 +477,33 @@ void ci_lazy_methodst::gather_field_types(
477477
ci_lazy_methods_neededt &needed_lazy_methods)
478478
{
479479
const auto &underlying_type=to_struct_type(ns.follow(class_type));
480-
for(const auto &field : underlying_type.components())
480+
if(is_java_array_tag(underlying_type.get_tag()))
481481
{
482-
if(field.type().id()==ID_struct || field.type().id()==ID_symbol)
483-
gather_field_types(field.type(), ns, needed_lazy_methods);
484-
else if(field.type().id()==ID_pointer)
482+
// If class_type is not a symbol this may be a reference array,
483+
// but we can't tell what type.
484+
if(class_type.id() == ID_symbol)
485485
{
486-
// Skip array primitive pointers, for example:
487-
if(field.type().subtype().id()!=ID_symbol)
488-
continue;
489-
initialize_all_needed_classes_from_pointer(
490-
to_pointer_type(field.type()), ns, needed_lazy_methods);
486+
const typet &element_type =
487+
java_array_element_type(to_symbol_type(class_type));
488+
if(element_type.id() == ID_pointer)
489+
{
490+
// This is a reference array -- mark its element type available.
491+
initialize_all_needed_classes_from_pointer(
492+
to_pointer_type(element_type), ns, needed_lazy_methods);
493+
}
494+
}
495+
}
496+
else
497+
{
498+
for(const auto &field : underlying_type.components())
499+
{
500+
if(field.type().id() == ID_struct || field.type().id() == ID_symbol)
501+
gather_field_types(field.type(), ns, needed_lazy_methods);
502+
else if(field.type().id() == ID_pointer)
503+
{
504+
initialize_all_needed_classes_from_pointer(
505+
to_pointer_type(field.type()), ns, needed_lazy_methods);
506+
}
491507
}
492508
}
493509
}

0 commit comments

Comments
 (0)