Skip to content

Commit 1dd221d

Browse files
Thomas Kileysvorenova
Thomas Kiley
authored and
svorenova
committed
Correct handling of the java generic class signature
Previously the signature parsing would be confused into thinking that there were two generic parameters when there were two bounds on the first parameter. There exists TG-674 to make the conversion work correctly.
1 parent 33afe48 commit 1dd221d

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,23 @@ void java_bytecode_convert_classt::convert(const classt &c)
103103
<< " in parsed class "
104104
<< c.name << "\n";
105105
#endif
106-
for(auto t : java_generic_type_from_string(
107-
id2string(c.name),
108-
c.signature.value()))
106+
try
109107
{
110-
generic_class_type.generic_types()
111-
.push_back(to_java_generic_parameter(t));
108+
const std::vector<typet> &generic_types=java_generic_type_from_string(
109+
id2string(c.name),
110+
c.signature.value());
111+
for(const typet &t : generic_types)
112+
{
113+
generic_class_type.generic_types()
114+
.push_back(to_java_generic_parameter(t));
115+
}
116+
class_type=generic_class_type;
117+
}
118+
catch(unsupported_java_class_siganture_exceptiont)
119+
{
120+
// Do nothing: we don't support parsing for example double bounded or
121+
// two entry elements
112122
}
113-
114-
class_type=generic_class_type;
115123
}
116124

117125
class_type.set_tag(c.name);

src/java_bytecode/java_types.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,17 +512,20 @@ std::vector<typet> java_generic_type_from_string(
512512
const std::string &class_name,
513513
const std::string &src)
514514
{
515-
/// the class signature is of the form <TX:Bound_X;TY:Bound_Y;>base_class
515+
/// the class signature is of the form <TX:Bound_X;:BoundZ;TY:Bound_Y;>
516516
size_t signature_end=find_closing_delimiter(src, 0, '<', '>');
517517
INVARIANT(
518518
src[0]=='<' && signature_end!=std::string::npos,
519519
"Class signature has unexpected format");
520520
std::string signature(src.substr(1, signature_end-1));
521521

522+
if(signature.find(";:")!=std::string::npos)
523+
throw unsupported_java_class_siganture_exceptiont();
524+
522525
PRECONDITION(signature[signature.size()-1]==';');
523526

524527
std::vector<typet> types;
525-
size_t var_sep=signature.rfind(';');
528+
size_t var_sep=signature.find(';');
526529
while(var_sep!=std::string::npos)
527530
{
528531
size_t bound_sep=signature.find(':');

src/java_bytecode/java_types.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,16 @@ inline const typet &java_generics_class_type_bound(
350350
return gen_type.subtype();
351351
}
352352

353+
354+
/// An exception that is raised for unsupported class signature.
355+
/// Currently we do not parse multiple bounds.
356+
class unsupported_java_class_siganture_exceptiont:public std::logic_error
357+
{
358+
public:
359+
unsupported_java_class_siganture_exceptiont():
360+
std::logic_error(
361+
"Unsupported class signature: multiple bounds")
362+
{}
363+
};
364+
353365
#endif // CPROVER_JAVA_BYTECODE_JAVA_TYPES_H

unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,11 @@ SCENARIO(
253253
class_typet class_type=to_class_type(symbol_type);
254254
REQUIRE(class_type.is_class());
255255
java_class_typet java_class_type=to_java_class_type(class_type);
256-
REQUIRE(is_java_generics_class_type(java_class_type));
256+
REQUIRE_FALSE(is_java_generics_class_type(java_class_type));
257257

258+
// TODO (tkiley): Extend this unit test when bounds are correctly
259+
// parsed.
260+
#if 0
258261
java_generics_class_typet java_generics_class_type=
259262
to_java_generics_class_type(java_class_type);
260263
REQUIRE(java_generics_class_type.generic_types().size()==1);
@@ -271,9 +274,9 @@ SCENARIO(
271274
"java::generics$double_bound_element::T");
272275
THEN("Bound must be Number and dummyInterface")
273276
{
274-
// TODO (tkiley): Extend this unit test when bounds are correctly
275-
// parsed.
277+
276278
}
279+
#endif
277280
}
278281
}
279282
}
@@ -293,7 +296,7 @@ SCENARIO(
293296

294297
java_generics_class_typet java_generics_class_type=
295298
to_java_generics_class_type(java_class_type);
296-
//REQUIRE(java_generics_class_type.generic_types().size()==2);
299+
REQUIRE(java_generics_class_type.generic_types().size()==2);
297300

298301
auto generic_param_iterator=
299302
java_generics_class_type.generic_types().cbegin();
@@ -327,7 +330,7 @@ SCENARIO(
327330
generic_type_var.type_variable().get_identifier()==
328331
"java::generics$two_elements::V");
329332
REQUIRE(
330-
java_generics_class_type_var(0, java_generics_class_type)==
333+
java_generics_class_type_var(1, java_generics_class_type)==
331334
"java::generics$two_elements::V");
332335
}
333336
}

0 commit comments

Comments
 (0)