Skip to content

[TG-2585] Support implicitly generic superclasses #1871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/java_bytecode/java_bytecode_convert_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ extract_generic_superclass_reference(const optionalt<std::string> &signature)
signature.value().substr(start, (end - start) + 1);

// if the superclass is generic then the reference is of form
// Lsuperclass-name<generic-types;>;
if(has_suffix(superclass_ref, ">;"))
// `Lsuperclass-name<generic-types;>;` if it is implicitly generic, then the
// reference is of the form
// `Lsuperclass-name<Tgeneric-types;>.Innerclass-Name`
if(superclass_ref.find('<') != std::string::npos)
return superclass_ref;
}
return {};
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class DerivedGenerics {
ExtendsAndImplementsSameInterface new14;
ExtendsAndImplementsSameInterface2 new15;
ExtendsAndImplementsSameInterfaceGeneric new16;
GenericBase<?>.ExtendImplicit new17;
GenericBase<?>.ExtendImplicitAndExplicit<?> new18;
GenericBase2<?, ?>.ExtendImplicitAndExplicit new19;
}

class DerivedGenericInst extends Generic<Interface_Implementation>
Expand Down Expand Up @@ -189,3 +192,25 @@ public Class<? extends Class> someMethod(){
return null;
}
}

// This class exists to test that subclasses of implicit generic classes have a
// base class entry which is a Java generic symbol.
class GenericBase<T> {
class ImplicitGeneric {
}
class ExtendImplicit extends ImplicitGeneric {
}
class ImplicitAndExplicitGeneric<S> {
}
class ExtendImplicitAndExplicit<S> extends ImplicitAndExplicitGeneric<S> {
}
}

// This class exists to test the subclasses of generic and implicitly generic
// classes have a base class entry which is a Java generic symbol.
class GenericBase2<T, S> {
class ImplicitAndExplicitGeneric<S> {
}
class ExtendImplicitAndExplicit extends ImplicitAndExplicitGeneric<S> {
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -559,4 +559,68 @@ SCENARIO(

// TODO: Check that specialised superclass is created. TG-1418, TG-1419
}

THEN("There should be a symbol for the `ExtendImplicit` class")
{
std::string class_prefix = "java::GenericBase$ExtendImplicit";
REQUIRE(new_symbol_table.has_symbol(class_prefix));

const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix);
const class_typet &derived_class_type =
require_type::require_java_implicitly_generic_class(derived_symbol.type);

THEN("The base for superclass is implicitly generic")
{
REQUIRE(derived_class_type.bases().size() == 1);
const typet &base_type = derived_class_type.bases().at(0).type();
require_type::require_java_generic_symbol_type(
base_type,
"java::GenericBase$ImplicitGeneric",
{{require_type::type_argument_kindt::Var, "java::GenericBase::T"}});
}
}

THEN("There should be a symbol for the `ExtendImplicitAndExplicit` class")
{
std::string class_prefix = "java::GenericBase$ExtendImplicitAndExplicit";
REQUIRE(new_symbol_table.has_symbol(class_prefix));

const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix);
const class_typet &derived_class_type =
require_type::require_java_implicitly_generic_class(derived_symbol.type);

THEN("The base for superclass is generic *and* implicitly generic")
{
REQUIRE(derived_class_type.bases().size() == 1);
const typet &base_type = derived_class_type.bases().at(0).type();
require_type::require_java_generic_symbol_type(
base_type,
"java::GenericBase$ImplicitAndExplicitGeneric",
{{require_type::type_argument_kindt::Var, "java::GenericBase::T"},
{require_type::type_argument_kindt::Var,
"java::GenericBase$ExtendImplicitAndExplicit::S"}});
}
}

THEN("There should be a symbol for the `ExtendImplicitAndExplicit` class")
{
std::string class_prefix = "java::GenericBase2$ExtendImplicitAndExplicit";
REQUIRE(new_symbol_table.has_symbol(class_prefix));

const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix);
const class_typet &derived_class_type =
require_type::require_java_implicitly_generic_class(derived_symbol.type);

THEN("The base for superclass is generic *and* implicitly generic")
{
REQUIRE(derived_class_type.bases().size() == 1);
const typet &base_type = derived_class_type.bases().at(0).type();
require_type::require_java_generic_symbol_type(
base_type,
"java::GenericBase2$ImplicitAndExplicitGeneric",
{{require_type::type_argument_kindt::Var, "java::GenericBase2::T"},
{require_type::type_argument_kindt::Var, "java::GenericBase2::S"},
{require_type::type_argument_kindt::Var, "java::GenericBase2::S"}});
}
}
}