Skip to content

Commit e74e1d8

Browse files
author
Thomas Kiley
authored
Merge pull request #1489 from svorenova/tg-865
Resolving signature/descriptor missmatch
2 parents 62675bb + 09431fd commit e74e1d8

14 files changed

+276
-56
lines changed

src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ void java_bytecode_convert_classt::convert(const classt &c)
203203
*class_symbol,
204204
method_identifier,
205205
method,
206-
symbol_table);
206+
symbol_table,
207+
get_message_handler());
207208
lazy_methods[method_identifier]=std::make_pair(class_symbol, &method);
208209
}
209210

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,69 @@ const exprt java_bytecode_convert_methodt::variable(
248248
}
249249
}
250250

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+
251314
/// This creates a method symbol in the symtab, but doesn't actually perform
252315
/// method conversion just yet. The caller should call
253316
/// java_bytecode_convert_method later to give the symbol/method a body.
@@ -256,14 +319,22 @@ const exprt java_bytecode_convert_methodt::variable(
256319
/// (e.g. "x.y.z.f:(I)")
257320
/// `m`: parsed method object to convert
258321
/// `symbol_table`: global symbol table (will be modified)
322+
/// `message_handler`: message handler to collect warnings
259323
void java_bytecode_convert_method_lazy(
260324
const symbolt &class_symbol,
261325
const irep_idt &method_identifier,
262326
const java_bytecode_parse_treet::methodt &m,
263-
symbol_tablet &symbol_table)
327+
symbol_tablet &symbol_table,
328+
message_handlert &message_handler)
264329
{
265330
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);
267338

268339
method_symbol.name=method_identifier;
269340
method_symbol.base_name=m.base_name;

src/java_bytecode/java_bytecode_convert_method.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ void java_bytecode_convert_method_lazy(
5353
const symbolt &class_symbol,
5454
const irep_idt &method_identifier,
5555
const java_bytecode_parse_treet::methodt &,
56-
symbol_tablet &symbol_table);
56+
symbol_tablet &symbol_table,
57+
message_handlert &);
5758

5859
#endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_H
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public abstract class AbstractGenericClass<T>
2+
{
3+
4+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public class Outer<T>
2+
{
3+
private class Inner
4+
{
5+
private final AbstractGenericClass<T> u;
6+
7+
Inner (AbstractGenericClass<T> t)
8+
{
9+
this.u = t;
10+
}
11+
}
12+
13+
private enum InnerEnum
14+
{
15+
16+
}
17+
}

unit/java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <java_bytecode/java_bytecode_language.h>
1818
#include <iostream>
1919
#include <testing-utils/load_java_class.h>
20+
#include <testing-utils/require_symbol.h>
2021

2122
SCENARIO(
2223
"java_bytecode_parse_derived_generic_class",
@@ -33,12 +34,8 @@ SCENARIO(
3334
REQUIRE(new_symbol_table.has_symbol(class_prefix));
3435

3536
const symbolt &derived_symbol=new_symbol_table.lookup_ref(class_prefix);
36-
REQUIRE(derived_symbol.is_type);
37-
const typet &derived_type=derived_symbol.type;
38-
REQUIRE(derived_type.id()==ID_struct);
39-
const class_typet &class_type=to_class_type(derived_type);
40-
REQUIRE(class_type.is_class());
41-
REQUIRE_FALSE(class_type.get_bool(ID_incomplete_class));
37+
const class_typet &derived_class_type=
38+
require_symbol::require_complete_class(derived_symbol);
4239

4340
// TODO(tkiley): Currently we do not support extracting information
4441
// about the base classes generic information.

0 commit comments

Comments
 (0)