@@ -85,6 +85,58 @@ class java_bytecode_convert_classt:public messaget
85
85
static void add_array_types (symbol_tablet &symbol_table);
86
86
};
87
87
88
+ // / Auxiliary function to extract the generic superclass reference from the
89
+ // / class signature. If the superclass is not generic, it returns an empty
90
+ // / string.
91
+ // / \param signature Signature of the class
92
+ // / \return Reference of the generic superclass, or empty if the superclass
93
+ // / is not generic
94
+ static std::string
95
+ extract_generic_superclass_reference (const std::string &signature)
96
+ {
97
+ // skip the (potential) list of generic parameters at the beginning of the
98
+ // signature
99
+ const size_t start = signature.front () == ' <'
100
+ ? find_closing_delimiter (signature, 0 , ' <' , ' >' ) + 1
101
+ : 0 ;
102
+
103
+ // extract the superclass reference
104
+ const std::string superclass_ref = signature.substr (
105
+ start,
106
+ find_closing_semi_colon_for_reference_type (signature, start) - start + 1 );
107
+
108
+ // if the superclass is generic then the reference is of form
109
+ // Lsuperclass-name<generic-types>;
110
+ if (superclass_ref.substr (superclass_ref.length () - 2 ) == " >;" )
111
+ return superclass_ref;
112
+ else
113
+ return " " ;
114
+ }
115
+
116
+ // / Auxiliary function to extract the generic interface reference of an
117
+ // / interface with the specified name from the class signature. If the
118
+ // / interface is not generic, it returns an empty string.
119
+ // / \param signature Signature of the class
120
+ // / \param interface_name The interface name
121
+ // / \return Reference of the generic interface, or empty if the interface
122
+ // / is not generic
123
+ static std::string extract_generic_interface_reference (
124
+ const std::string &signature,
125
+ const std::string &interface_name)
126
+ {
127
+ if (signature.find (" L" + interface_name + " <" ) != std::string::npos)
128
+ {
129
+ const size_t start = signature.find (" L" + interface_name + " <" );
130
+ return signature.substr (
131
+ start,
132
+ find_closing_semi_colon_for_reference_type (signature, start) - start + 1 );
133
+ }
134
+ else
135
+ {
136
+ return " " ;
137
+ }
138
+ }
139
+
88
140
void java_bytecode_convert_classt::convert (const classt &c)
89
141
{
90
142
std::string qualified_classname=" java::" +id2string (c.name );
@@ -145,10 +197,28 @@ void java_bytecode_convert_classt::convert(const classt &c)
145
197
146
198
if (!c.extends .empty ())
147
199
{
148
- symbol_typet base (" java::" +id2string (c.extends ));
149
- class_type.add_base (base);
200
+ const symbol_typet base (" java::" + id2string (c.extends ));
201
+
202
+ // if the superclass is generic then the class has the superclass reference
203
+ // including the generic info in its signature
204
+ // e.g., signature for class 'A<T>' that extends
205
+ // 'Generic<Integer>' is '<T:Ljava/lang/Object;>LGeneric<LInteger;>;'
206
+ if (
207
+ c.signature .has_value () &&
208
+ !extract_generic_superclass_reference (c.signature .value ()).empty ())
209
+ {
210
+ const java_generic_symbol_typet gen_base (
211
+ base,
212
+ extract_generic_superclass_reference (c.signature .value ()),
213
+ qualified_classname);
214
+ class_type.add_base (gen_base);
215
+ }
216
+ else
217
+ {
218
+ class_type.add_base (base);
219
+ }
150
220
class_typet::componentt base_class_field;
151
- base_class_field.type ()=base ;
221
+ base_class_field.type () = class_type. bases (). at ( 0 ). type () ;
152
222
base_class_field.set_name (" @" +id2string (c.extends ));
153
223
base_class_field.set_base_name (" @" +id2string (c.extends ));
154
224
base_class_field.set_pretty_name (" @" +id2string (c.extends ));
@@ -158,8 +228,30 @@ void java_bytecode_convert_classt::convert(const classt &c)
158
228
// interfaces are recorded as bases
159
229
for (const auto &interface : c.implements )
160
230
{
161
- symbol_typet base (" java::" +id2string (interface));
162
- class_type.add_base (base);
231
+ const symbol_typet base (" java::" + id2string (interface));
232
+
233
+ // if the interface is generic then the class has the interface reference
234
+ // including the generic info in its signature
235
+ // e.g., signature for class 'A' that implements
236
+ // 'GenericInterface<Integer>' is 'Ljava/lang/Object;
237
+ // LGenericInterface<LInteger;>;'
238
+ if (
239
+ c.signature .has_value () &&
240
+ !extract_generic_interface_reference (
241
+ c.signature .value (), id2string (interface))
242
+ .empty ())
243
+ {
244
+ const java_generic_symbol_typet gen_base (
245
+ base,
246
+ extract_generic_interface_reference (
247
+ c.signature .value (), id2string (interface)),
248
+ qualified_classname);
249
+ class_type.add_base (gen_base);
250
+ }
251
+ else
252
+ {
253
+ class_type.add_base (base);
254
+ }
163
255
}
164
256
165
257
// produce class symbol
0 commit comments