Skip to content

Commit 0b17511

Browse files
author
Thomas Kiley
authored
Merge pull request diffblue#1955 from svorenova/bugfix_tg2842
[TG-2842] Specialization for mocked and unsupported generics
2 parents eb1ac7b + 076aa5a commit 0b17511

File tree

61 files changed

+596
-170
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+596
-170
lines changed

src/java_bytecode/generic_parameter_specialization_map_keys.cpp

+28-13
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,21 @@ const void generic_parameter_specialization_map_keyst::insert_pairs_for_pointer(
9999
pointer_type.subtype().get(ID_identifier) ==
100100
pointer_subtype_struct.get(ID_name));
101101

102-
const java_generic_typet &generic_pointer =
103-
to_java_generic_type(pointer_type);
104-
105-
// If the pointer points to an incomplete class, don't treat the generics
106-
if(!pointer_subtype_struct.get_bool(ID_incomplete_class))
102+
// If the pointer points to:
103+
// - an incomplete class or
104+
// - a class that is neither generic nor implicitly generic (this
105+
// may be due to unsupported class signature)
106+
// then ignore the generic types in the pointer and do not add any pairs.
107+
// TODO TG-1996 should decide how mocking and generics should work
108+
// together. Currently an incomplete class is never marked as generic. If
109+
// this changes in TG-1996 then the condition below should be updated.
110+
if(
111+
!pointer_subtype_struct.get_bool(ID_incomplete_class) &&
112+
(is_java_generic_class_type(pointer_subtype_struct) ||
113+
is_java_implicitly_generic_class_type(pointer_subtype_struct)))
107114
{
108-
PRECONDITION(
109-
is_java_generic_class_type(pointer_subtype_struct) ||
110-
is_java_implicitly_generic_class_type(pointer_subtype_struct));
115+
const java_generic_typet &generic_pointer =
116+
to_java_generic_type(pointer_type);
111117
const std::vector<java_generic_parametert> &generic_parameters =
112118
get_all_generic_parameters(pointer_subtype_struct);
113119

@@ -135,14 +141,23 @@ const void generic_parameter_specialization_map_keyst::insert_pairs_for_symbol(
135141
const symbol_typet &symbol_type,
136142
const typet &symbol_struct)
137143
{
138-
if(is_java_generic_symbol_type(symbol_type))
144+
// If the struct is:
145+
// - an incomplete class or
146+
// - a class that is neither generic nor implicitly generic (this
147+
// may be due to unsupported class signature)
148+
// then ignore the generic types in the symbol_type and do not add any pairs.
149+
// TODO TG-1996 should decide how mocking and generics should work
150+
// together. Currently an incomplete class is never marked as generic. If
151+
// this changes in TG-1996 then the condition below should be updated.
152+
if(
153+
is_java_generic_symbol_type(symbol_type) &&
154+
!symbol_struct.get_bool(ID_incomplete_class) &&
155+
(is_java_generic_class_type(symbol_struct) ||
156+
is_java_implicitly_generic_class_type(symbol_struct)))
139157
{
140-
java_generic_symbol_typet generic_symbol =
158+
const java_generic_symbol_typet &generic_symbol =
141159
to_java_generic_symbol_type(symbol_type);
142160

143-
PRECONDITION(
144-
is_java_generic_class_type(symbol_struct) ||
145-
is_java_implicitly_generic_class_type(symbol_struct));
146161
const std::vector<java_generic_parametert> &generic_parameters =
147162
get_all_generic_parameters(symbol_struct);
148163

src/java_bytecode/java_bytecode_convert_class.cpp

+15-11
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,12 @@ void java_bytecode_convert_classt::convert(const classt &c)
202202
}
203203
class_type=generic_class_type;
204204
}
205-
catch(unsupported_java_class_signature_exceptiont)
205+
catch(const unsupported_java_class_signature_exceptiont &e)
206206
{
207-
warning() << "we currently don't support parsing for example double "
208-
"bounded, recursive and wild card generics" << eom;
207+
warning() << "Class: " << c.name
208+
<< "\n could not parse signature: " << c.signature.value()
209+
<< "\n " << e.what() << "\n ignoring that the class is generic"
210+
<< eom;
209211
}
210212
}
211213

@@ -253,11 +255,12 @@ void java_bytecode_convert_classt::convert(const classt &c)
253255
base, superclass_ref.value(), qualified_classname);
254256
class_type.add_base(generic_base);
255257
}
256-
catch(unsupported_java_class_signature_exceptiont)
258+
catch(const unsupported_java_class_signature_exceptiont &e)
257259
{
258-
debug() << "unsupported generic superclass signature "
259-
<< id2string(*superclass_ref)
260-
<< " falling back on using the descriptor" << eom;
260+
warning() << "Superclass: " << c.extends << " of class: " << c.name
261+
<< "\n could not parse signature: " << superclass_ref.value()
262+
<< "\n " << e.what()
263+
<< "\n ignoring that the superclass is generic" << eom;
261264
class_type.add_base(base);
262265
}
263266
}
@@ -292,11 +295,12 @@ void java_bytecode_convert_classt::convert(const classt &c)
292295
base, interface_ref.value(), qualified_classname);
293296
class_type.add_base(generic_base);
294297
}
295-
catch(unsupported_java_class_signature_exceptiont)
298+
catch(const unsupported_java_class_signature_exceptiont &e)
296299
{
297-
debug() << "unsupported generic interface signature "
298-
<< id2string(*interface_ref)
299-
<< " falling back on using the descriptor" << eom;
300+
warning() << "Interface: " << interface << " of class: " << c.name
301+
<< "\n could not parse signature: " << interface_ref.value()
302+
<< "\n " << e.what()
303+
<< "\n ignoring that the interface is generic" << eom;
300304
class_type.add_base(base);
301305
}
302306
}

src/java_bytecode/java_bytecode_convert_method.cpp

+12-9
Original file line numberDiff line numberDiff line change
@@ -286,18 +286,21 @@ code_typet member_type_lazy(
286286
}
287287
else
288288
{
289-
message.warning() << "method: " << class_name << "." << method_name
290-
<< "\n signature: " << signature.value() << "\n descriptor: "
291-
<< descriptor << "\n different number of parameters, reverting to "
292-
"descriptor" << message.eom;
289+
message.warning() << "Method: " << class_name << "." << method_name
290+
<< "\n signature: " << signature.value()
291+
<< "\n descriptor: " << descriptor
292+
<< "\n different number of parameters, reverting to "
293+
"descriptor"
294+
<< message.eom;
293295
}
294296
}
295-
catch(unsupported_java_class_signature_exceptiont &e)
297+
catch(const unsupported_java_class_signature_exceptiont &e)
296298
{
297-
message.warning() << "method: " << class_name << "." << method_name
298-
<< "\n could not parse signature: " << signature.value() << "\n "
299-
<< e.what() << "\n" << " reverting to descriptor: "
300-
<< descriptor << message.eom;
299+
message.warning() << "Method: " << class_name << "." << method_name
300+
<< "\n could not parse signature: " << signature.value()
301+
<< "\n " << e.what() << "\n"
302+
<< " reverting to descriptor: " << descriptor
303+
<< message.eom;
301304
}
302305
}
303306
return to_code_type(member_type_from_descriptor);

unit/goto-programs/goto_program_generics/GenericBases.java

+18-24
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,3 @@
1-
// Helper classes
2-
class Wrapper<T> {
3-
public T field;
4-
}
5-
6-
class IntWrapper {
7-
public int i;
8-
}
9-
10-
class TwoWrapper<K, V> {
11-
public K first;
12-
public V second;
13-
}
14-
15-
interface InterfaceWrapper<T> {
16-
public T method(T t);
17-
}
18-
191
// A class extending a generic class instantiated with a standard library class
202
class SuperclassInst extends Wrapper<Integer> {
213
public void foo() {
@@ -24,14 +6,14 @@ public void foo() {
246
}
257

268
// A class extending a generic class instantiated with a user-defined class
27-
class SuperclassInst2 extends Wrapper<IntWrapper> {
9+
class SuperclassInst2 extends Wrapper<IWrapper> {
2810
public void foo() {
2911
this.field.i = 5;
3012
}
3113
}
3214

3315
// A class extending an instantiated nested generic class
34-
class SuperclassInst3 extends Wrapper<Wrapper<IntWrapper>> {
16+
class SuperclassInst3 extends Wrapper<Wrapper<IWrapper>> {
3517
public void foo() {
3618
this.field.field.i = 5;
3719
}
@@ -54,7 +36,7 @@ public void foo() {
5436

5537
// A generic class extending a generic class with both instantiated and
5638
// uninstantiated parameters
57-
class SuperclassMixed<U> extends TwoWrapper<U,IntWrapper> {
39+
class SuperclassMixed<U> extends PairWrapper<U,IWrapper> {
5840
public void foo(U value) {
5941
this.first = value;
6042
this.second.i = 5;
@@ -99,7 +81,7 @@ public void foo(U value) {
9981
}
10082
public Inner inner;
10183

102-
class InnerGen<T> extends TwoWrapper<U,T> {
84+
class InnerGen<T> extends PairWrapper<U,T> {
10385
public void foo(U uvalue, T tvalue) {
10486
this.first = uvalue;
10587
this.second = tvalue;
@@ -113,11 +95,23 @@ class InnerThree extends Inner {
11395
}
11496
class SuperclassInnerUninstTest
11597
{
116-
SuperclassInnerUninst<IntWrapper> f;
98+
SuperclassInnerUninst<IWrapper> f;
11799
public void foo() {
118-
IntWrapper x = new IntWrapper();
100+
IWrapper x = new IWrapper(0);
119101
f.inner.foo(x);
120102
f.inner_gen.foo(x,true);
121103
f.inner_three.foo(x);
122104
}
123105
}
106+
107+
class SuperclassUnsupported extends UnsupportedWrapper1<SuperclassUnsupported> {
108+
public void foo() {
109+
this.field = new SuperclassUnsupported();
110+
}
111+
}
112+
113+
class SuperclassOpaque extends OpaqueWrapper<IWrapper> {
114+
public void foo() {
115+
this.field.i = 5;
116+
}
117+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

unit/goto-programs/goto_program_generics/GenericFields.java

+40-24
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,25 @@
1-
class SimpleWrapper<T> {
2-
public T field;
3-
public T[] array_field;
4-
5-
public int int_field;
6-
}
7-
8-
class IWrapper {
9-
public int i;
10-
}
11-
12-
class PairWrapper<K, V> {
13-
public K key;
14-
public V value;
15-
}
16-
171
public class GenericFields
182
{
193
IWrapper field;
204
class SimpleGenericField {
21-
SimpleWrapper<IWrapper> field_input;
5+
Wrapper<IWrapper> field_input;
226
public void foo() {
237
field_input.field.i = 5;
248
field_input.array_field = new IWrapper[2];
259
}
2610
}
2711

2812
class MultipleGenericFields {
29-
SimpleWrapper<IWrapper> field_input1;
30-
SimpleWrapper<IWrapper> field_input2;
13+
Wrapper<IWrapper> field_input1;
14+
Wrapper<IWrapper> field_input2;
3115
public void foo() {
3216
field_input1.field.i = 10;
3317
field_input2.field.i = 20;
3418
}
3519
}
3620

3721
class NestedGenericFields {
38-
SimpleWrapper<SimpleWrapper<IWrapper>> field_input1;
22+
Wrapper<Wrapper<IWrapper>> field_input1;
3923
public void foo() {
4024
field_input1.field.field.i = 30;
4125
}
@@ -44,19 +28,19 @@ public void foo() {
4428
class PairGenericField {
4529
PairWrapper<IWrapper, IWrapper> field_input;
4630
public void foo() {
47-
field_input.key.i = 40;
48-
field_input.value.i = 50;
31+
field_input.first.i = 40;
32+
field_input.second.i = 50;
4933
}
5034
}
5135

5236
class GenericMethodParameter {
53-
public void foo(SimpleWrapper<IWrapper> v) {
37+
public void foo(Wrapper<IWrapper> v) {
5438
v.field.i = 20;
5539
}
5640
}
5741

5842
class GenericMethodUninstantiatedParameter {
59-
public <T> void foo_unspec(SimpleWrapper<T> v) {
43+
public <T> void foo_unspec(Wrapper<T> v) {
6044
v.int_field=10;
6145
}
6246
}
@@ -96,3 +80,35 @@ public void foo(A<Integer> v) {
9680
}
9781
}
9882
}
83+
84+
// class that implements two generic interfaces
85+
class InterfacesImplementation implements InterfaceWrapper<IWrapper>,
86+
InterfacePairWrapper<IWrapper, IWrapper> {
87+
public IWrapper method(IWrapper t) {
88+
return t;
89+
}
90+
public IWrapper method(IWrapper t, IWrapper tt) {
91+
if (t.i>0)
92+
{
93+
return t;
94+
}
95+
else
96+
{
97+
return tt;
98+
}
99+
}
100+
}
101+
class GenericFieldUnsupported {
102+
public UnsupportedWrapper2<InterfacesImplementation> f;
103+
public void foo() {
104+
f.field.method(new IWrapper(0));
105+
f.field.method(new IWrapper(0), new IWrapper(2));
106+
}
107+
}
108+
109+
class GenericFieldOpaque {
110+
public OpaqueWrapper<IWrapper> f;
111+
public void foo() {
112+
f.field.i = 0;
113+
}
114+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// int wrapper
2+
class IWrapper {
3+
public int i;
4+
public IWrapper(int ii) {
5+
i = ii;
6+
}
7+
}
8+
9+
// simple generic class
10+
class Wrapper<T> {
11+
public T field;
12+
public T[] array_field;
13+
public int int_field;
14+
}
15+
16+
// generic class with two parameters
17+
class PairWrapper<K, V> {
18+
public K first;
19+
public V second;
20+
}
21+
22+
// simple generic interface
23+
interface InterfaceWrapper<T> {
24+
public T method(T t);
25+
}
26+
27+
// generic interface with two parameters
28+
interface InterfacePairWrapper<K, V> {
29+
public K method(K k, V v);
30+
}
31+
32+
// generic class with unsupported signature - generic bound
33+
class UnsupportedWrapper1<T extends UnsupportedWrapper1<T>> {
34+
public T field;
35+
}
36+
37+
// generic class with unsupported signature - multiple bounds
38+
class UnsupportedWrapper2<T extends InterfaceWrapper & InterfacePairWrapper>
39+
{
40+
public T field;
41+
}
42+
43+
// generic opaque class, make sure the .class file is not available
44+
class OpaqueWrapper<T> {
45+
public T field;
46+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)