@@ -248,6 +248,69 @@ const exprt java_bytecode_convert_methodt::variable(
248
248
}
249
249
}
250
250
251
+ // / Returns the member type for a method, based on signature or descriptor
252
+ // / \param descriptor
253
+ // / descriptor of the method
254
+ // / \param signature
255
+ // / signature of the method
256
+ // / \param class_name
257
+ // / string containing the name of the corresponding class
258
+ // / \param method_name
259
+ // / string containing the name of the method
260
+ // / \param message_handler
261
+ // / message handler to collect warnings
262
+ // / \return
263
+ // / the constructed member type
264
+ typet member_type_lazy (const std::string &descriptor,
265
+ const optionalt<std::string> &signature,
266
+ const std::string &class_name,
267
+ const std::string &method_name,
268
+ message_handlert &message_handler)
269
+ {
270
+ // In order to construct the method type, we can either use signature or
271
+ // descriptor. Since only signature contains the generics info, we want to
272
+ // use signature whenever possible. We revert to using descriptor if (1) the
273
+ // signature does not exist, (2) an unsupported generics are present or
274
+ // (3) in the special case when the number of parameters in the descriptor
275
+ // does not match the number of parameters in the signature - e.g. for
276
+ // certain types of inner classes and enums (see unit tests for examples).
277
+
278
+ messaget message (message_handler);
279
+
280
+ typet member_type_from_descriptor=java_type_from_string (descriptor);
281
+ INVARIANT (member_type_from_descriptor.id ()==ID_code, " Must be code type" );
282
+ if (signature.has_value ())
283
+ {
284
+ try
285
+ {
286
+ typet member_type_from_signature=java_type_from_string (
287
+ signature.value (),
288
+ class_name);
289
+ INVARIANT (member_type_from_signature.id ()==ID_code, " Must be code type" );
290
+ if (to_code_type (member_type_from_signature).parameters ().size ()==
291
+ to_code_type (member_type_from_descriptor).parameters ().size ())
292
+ {
293
+ return member_type_from_signature;
294
+ }
295
+ else
296
+ {
297
+ message.warning () << " method: " << class_name << " ." << method_name
298
+ << " \n signature: " << signature.value () << " \n descriptor: "
299
+ << descriptor << " \n different number of parameters, reverting to "
300
+ " descriptor" << message.eom ;
301
+ }
302
+ }
303
+ catch (unsupported_java_class_signature_exceptiont &e)
304
+ {
305
+ message.warning () << " method: " << class_name << " ." << method_name
306
+ << " \n could not parse signature: " << signature.value () << " \n "
307
+ << e.what () << " \n " << " reverting to descriptor: "
308
+ << descriptor << message.eom ;
309
+ }
310
+ }
311
+ return member_type_from_descriptor;
312
+ }
313
+
251
314
// / This creates a method symbol in the symtab, but doesn't actually perform
252
315
// / method conversion just yet. The caller should call
253
316
// / java_bytecode_convert_method later to give the symbol/method a body.
@@ -256,14 +319,22 @@ const exprt java_bytecode_convert_methodt::variable(
256
319
// / (e.g. "x.y.z.f:(I)")
257
320
// / `m`: parsed method object to convert
258
321
// / `symbol_table`: global symbol table (will be modified)
322
+ // / `message_handler`: message handler to collect warnings
259
323
void java_bytecode_convert_method_lazy (
260
324
const symbolt &class_symbol,
261
325
const irep_idt &method_identifier,
262
326
const java_bytecode_parse_treet::methodt &m,
263
- symbol_tablet &symbol_table)
327
+ symbol_tablet &symbol_table,
328
+ message_handlert &message_handler)
264
329
{
265
330
symbolt method_symbol;
266
- typet member_type=java_type_from_string (m.descriptor );
331
+
332
+ typet member_type=member_type_lazy (
333
+ m.descriptor ,
334
+ m.signature ,
335
+ id2string (class_symbol.name ),
336
+ id2string (m.base_name ),
337
+ message_handler);
267
338
268
339
method_symbol.name =method_identifier;
269
340
method_symbol.base_name =m.base_name ;
0 commit comments