Skip to content

Commit 1dfb5cd

Browse files
author
Matthias Güdemann
authored
Merge pull request #1871 from mgudemann/bugfix/superclass_references_for_implicit_generic
[TG-2585] Support implicitly generic superclasses
2 parents 71b32f4 + 25eb1a3 commit 1dfb5cd

12 files changed

+93
-2
lines changed

src/java_bytecode/java_bytecode_convert_class.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,10 @@ extract_generic_superclass_reference(const optionalt<std::string> &signature)
112112
signature.value().substr(start, (end - start) + 1);
113113

114114
// if the superclass is generic then the reference is of form
115-
// Lsuperclass-name<generic-types;>;
116-
if(has_suffix(superclass_ref, ">;"))
115+
// `Lsuperclass-name<generic-types;>;` if it is implicitly generic, then the
116+
// reference is of the form
117+
// `Lsuperclass-name<Tgeneric-types;>.Innerclass-Name`
118+
if(superclass_ref.find('<') != std::string::npos)
117119
return superclass_ref;
118120
}
119121
return {};
Binary file not shown.

unit/java_bytecode/java_bytecode_parse_generics/DerivedGenerics.java

+25
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public class DerivedGenerics {
1515
ExtendsAndImplementsSameInterface new14;
1616
ExtendsAndImplementsSameInterface2 new15;
1717
ExtendsAndImplementsSameInterfaceGeneric new16;
18+
GenericBase<?>.ExtendImplicit new17;
19+
GenericBase<?>.ExtendImplicitAndExplicit<?> new18;
20+
GenericBase2<?, ?>.ExtendImplicitAndExplicit new19;
1821
}
1922

2023
class DerivedGenericInst extends Generic<Interface_Implementation>
@@ -189,3 +192,25 @@ public Class<? extends Class> someMethod(){
189192
return null;
190193
}
191194
}
195+
196+
// This class exists to test that subclasses of implicit generic classes have a
197+
// base class entry which is a Java generic symbol.
198+
class GenericBase<T> {
199+
class ImplicitGeneric {
200+
}
201+
class ExtendImplicit extends ImplicitGeneric {
202+
}
203+
class ImplicitAndExplicitGeneric<S> {
204+
}
205+
class ExtendImplicitAndExplicit<S> extends ImplicitAndExplicitGeneric<S> {
206+
}
207+
}
208+
209+
// This class exists to test the subclasses of generic and implicitly generic
210+
// classes have a base class entry which is a Java generic symbol.
211+
class GenericBase2<T, S> {
212+
class ImplicitAndExplicitGeneric<S> {
213+
}
214+
class ExtendImplicitAndExplicit extends ImplicitAndExplicitGeneric<S> {
215+
}
216+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

unit/java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp

+64
Original file line numberDiff line numberDiff line change
@@ -559,4 +559,68 @@ SCENARIO(
559559

560560
// TODO: Check that specialised superclass is created. TG-1418, TG-1419
561561
}
562+
563+
THEN("There should be a symbol for the `ExtendImplicit` class")
564+
{
565+
std::string class_prefix = "java::GenericBase$ExtendImplicit";
566+
REQUIRE(new_symbol_table.has_symbol(class_prefix));
567+
568+
const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix);
569+
const class_typet &derived_class_type =
570+
require_type::require_java_implicitly_generic_class(derived_symbol.type);
571+
572+
THEN("The base for superclass is implicitly generic")
573+
{
574+
REQUIRE(derived_class_type.bases().size() == 1);
575+
const typet &base_type = derived_class_type.bases().at(0).type();
576+
require_type::require_java_generic_symbol_type(
577+
base_type,
578+
"java::GenericBase$ImplicitGeneric",
579+
{{require_type::type_argument_kindt::Var, "java::GenericBase::T"}});
580+
}
581+
}
582+
583+
THEN("There should be a symbol for the `ExtendImplicitAndExplicit` class")
584+
{
585+
std::string class_prefix = "java::GenericBase$ExtendImplicitAndExplicit";
586+
REQUIRE(new_symbol_table.has_symbol(class_prefix));
587+
588+
const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix);
589+
const class_typet &derived_class_type =
590+
require_type::require_java_implicitly_generic_class(derived_symbol.type);
591+
592+
THEN("The base for superclass is generic *and* implicitly generic")
593+
{
594+
REQUIRE(derived_class_type.bases().size() == 1);
595+
const typet &base_type = derived_class_type.bases().at(0).type();
596+
require_type::require_java_generic_symbol_type(
597+
base_type,
598+
"java::GenericBase$ImplicitAndExplicitGeneric",
599+
{{require_type::type_argument_kindt::Var, "java::GenericBase::T"},
600+
{require_type::type_argument_kindt::Var,
601+
"java::GenericBase$ExtendImplicitAndExplicit::S"}});
602+
}
603+
}
604+
605+
THEN("There should be a symbol for the `ExtendImplicitAndExplicit` class")
606+
{
607+
std::string class_prefix = "java::GenericBase2$ExtendImplicitAndExplicit";
608+
REQUIRE(new_symbol_table.has_symbol(class_prefix));
609+
610+
const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix);
611+
const class_typet &derived_class_type =
612+
require_type::require_java_implicitly_generic_class(derived_symbol.type);
613+
614+
THEN("The base for superclass is generic *and* implicitly generic")
615+
{
616+
REQUIRE(derived_class_type.bases().size() == 1);
617+
const typet &base_type = derived_class_type.bases().at(0).type();
618+
require_type::require_java_generic_symbol_type(
619+
base_type,
620+
"java::GenericBase2$ImplicitAndExplicitGeneric",
621+
{{require_type::type_argument_kindt::Var, "java::GenericBase2::T"},
622+
{require_type::type_argument_kindt::Var, "java::GenericBase2::S"},
623+
{require_type::type_argument_kindt::Var, "java::GenericBase2::S"}});
624+
}
625+
}
562626
}

0 commit comments

Comments
 (0)