From 90a823011bde5b2ee130cbe8df02ebd1edf8d879 Mon Sep 17 00:00:00 2001 From: svorenova Date: Thu, 7 Dec 2017 11:21:46 +0000 Subject: [PATCH 1/3] Adding specialisation for implicitly generic classes --- .../generate_java_generic_type.cpp | 234 ++++++++++++++---- .../generate_java_generic_type.h | 2 +- src/java_bytecode/java_types.h | 20 +- unit/testing-utils/generic_utils.cpp | 4 +- 4 files changed, 206 insertions(+), 54 deletions(-) diff --git a/src/java_bytecode/generate_java_generic_type.cpp b/src/java_bytecode/generate_java_generic_type.cpp index 56733460bae..77cd26f8092 100644 --- a/src/java_bytecode/generate_java_generic_type.cpp +++ b/src/java_bytecode/generate_java_generic_type.cpp @@ -36,16 +36,17 @@ symbolt generate_java_generic_typet::operator()( INVARIANT( pointer_subtype.id()==ID_struct, "Only pointers to classes in java"); INVARIANT( - is_java_generic_class_type(pointer_subtype), + is_java_generic_class_type(pointer_subtype) || + is_java_implicitly_generic_class_type(pointer_subtype), "Generic references type must be a generic class"); - const java_generic_class_typet &generic_class_definition = - to_java_generic_class_type(to_java_class_type(pointer_subtype)); + const java_class_typet &class_definition = + to_java_class_type(pointer_subtype); const irep_idt generic_name = - build_generic_name(existing_generic_type, generic_class_definition); + build_generic_name(existing_generic_type, class_definition); struct_union_typet::componentst replacement_components = - generic_class_definition.components(); + class_definition.components(); // Small auxiliary function, to perform the inplace // modification of the generic fields. @@ -53,7 +54,7 @@ symbolt generate_java_generic_typet::operator()( [&](struct_union_typet::componentt &component) { component.type() = substitute_type( - component.type(), generic_class_definition, existing_generic_type); + component.type(), class_definition, existing_generic_type); return component; }; @@ -66,8 +67,7 @@ symbolt generate_java_generic_typet::operator()( replacement_components.end(), replace_type_for_generic_field); - std::size_t after_modification_size = - generic_class_definition.components().size(); + std::size_t after_modification_size = class_definition.components().size(); INVARIANT( pre_modification_size==after_modification_size, @@ -75,7 +75,7 @@ symbolt generate_java_generic_typet::operator()( const java_specialized_generic_class_typet new_java_class{ generic_name, - generic_class_definition.get_tag(), + class_definition.get_tag(), replacement_components, existing_generic_type.generic_type_arguments()}; @@ -110,7 +110,7 @@ symbolt generate_java_generic_typet::operator()( /// there are none to replace, the original type. typet generate_java_generic_typet::substitute_type( const typet ¶meter_type, - const java_generic_class_typet &generic_class, + const java_class_typet &class_definition, const java_generic_typet &generic_reference) const { if(is_java_generic_parameter(parameter_type)) @@ -119,8 +119,28 @@ typet generate_java_generic_typet::substitute_type( .type_variable() .get_identifier(); - optionalt results = - java_generics_get_index_for_subtype(generic_class, component_identifier); + // see if it is a generic parameter introduced by this class + optionalt results; + if(is_java_generic_class_type(class_definition)) + { + const java_generic_class_typet &generic_class = + to_java_generic_class_type(class_definition); + + results = java_generics_get_index_for_subtype( + generic_class.generic_types(), component_identifier); + } + // see if it is an implicit generic parameter introduced by an outer class + if(!results.has_value()) + { + INVARIANT( + is_java_implicitly_generic_class_type(class_definition), + "The parameter must either be a generic type or implicit generic type"); + const java_implicitly_generic_class_typet &implicitly_generic_class = + to_java_implicitly_generic_class_type(class_definition); + results = java_generics_get_index_for_subtype( + implicitly_generic_class.implicit_generic_types(), + component_identifier); + } INVARIANT(results.has_value(), "generic component type not found"); return generic_reference.generic_type_arguments()[*results]; @@ -142,7 +162,7 @@ typet generate_java_generic_typet::substitute_type( [&](const reference_typet &generic_param) -> reference_typet { const typet &replacement_type = - substitute_type(generic_param, generic_class, generic_reference); + substitute_type(generic_param, class_definition, generic_reference); // This code will be simplified when references aren't considered to // be generic parameters @@ -172,8 +192,8 @@ typet generate_java_generic_typet::substitute_type( const typet &array_element_type = java_array_element_type(array_subtype); - const typet &new_array_type = - substitute_type(array_element_type, generic_class, generic_reference); + const typet &new_array_type = substitute_type( + array_element_type, class_definition, generic_reference); typet replacement_array_type = java_array_type('a'); replacement_array_type.subtype().set(ID_C_element_type, new_array_type); @@ -184,51 +204,173 @@ typet generate_java_generic_typet::substitute_type( return parameter_type; } -/// Build a unique tag for the generic to be instantiated. +/// Creates a name for an argument that is an array, e.g., for an array of +/// Integers it returns a string `array[reference]of_java::java.lang.Integer` +/// \param id argument of type array +/// \param generic_argument_p array reference type +/// \return name as a string +static irep_idt build_name_for_array_argument( + const irep_idt &id, + const reference_typet &generic_argument_p) +{ + PRECONDITION(is_java_array_tag(id)); + std::ostringstream name_buffer; + name_buffer << pretty_print_java_type(id2string(id)); + const typet &element_type = + java_array_element_type(to_symbol_type(generic_argument_p.subtype())); + + // If this is an array of references then we will specialize its + // identifier using the type of the objects in the array. Else, there + // can be a problem with the same symbols for different instantiations + // using arrays with different types. + if(element_type.id() == ID_pointer) + { + const symbol_typet element_symbol = to_symbol_type(element_type.subtype()); + name_buffer << "of_" + id2string(element_symbol.get_identifier()); + } + return name_buffer.str(); +} + +/// Build a generic name for a generic class, from given generic arguments. +/// For example, given a class `Class` with two generic type parameters +/// `java::Class::T` and `java::Class::U`, and two arguments +/// `java::java.lang.Integer` and `java::Outer$Inner`, the returned string is +/// ``. +/// \param generic_argument_p iterator over generic arguments +/// \param generic_type_p iterator over generic types, starts with types for +/// the given class, may continue with generic types of its inner classes +/// \param generic_types_end end of the vector of generic types +/// \param class_name name of the class for which the tag is being built +/// \return name as a string of the form `<*, *, ..., *>` +static irep_idt build_generic_name_for_class_arguments( + std::vector::const_iterator &generic_argument_p, + std::vector::const_iterator &generic_type_p, + const std::vector::const_iterator &generic_types_end, + const std::string &class_name) +{ + std::ostringstream name_buffer; + bool first = true; + std::string parameter_class_name = + (*generic_type_p).get_parameter_class_name(); + PRECONDITION(parameter_class_name == class_name); + + while(parameter_class_name == class_name) + { + if(first) + { + name_buffer << "<"; + first = false; + } + else + { + name_buffer << ", "; + } + + const irep_idt &id( + id2string((*generic_argument_p).subtype().get(ID_identifier))); + if(is_java_array_tag(id)) + { + name_buffer << build_name_for_array_argument(id, *generic_argument_p); + } + else + { + name_buffer << id2string(id); + } + + ++generic_argument_p; + ++generic_type_p; + if(generic_type_p != generic_types_end) + { + parameter_class_name = (*generic_type_p).get_parameter_class_name(); + } + else + { + break; + } + } + name_buffer << ">"; + return name_buffer.str(); +} + +/// Build a unique name for the generic to be instantiated. /// \param existing_generic_type The type we want to concretise /// \param original_class -/// \return A tag for the new generic we want a unique tag for. +/// \return A name for the new generic we want a unique name for. irep_idt generate_java_generic_typet::build_generic_name( const java_generic_typet &existing_generic_type, const java_class_typet &original_class) const { - std::ostringstream new_tag_buffer; - new_tag_buffer << original_class.get_tag(); - new_tag_buffer << "<"; - bool first=true; - for(const typet &type_argument : existing_generic_type - .generic_type_arguments()) + std::ostringstream generic_name_buffer; + const std::string &original_class_name = original_class.get_tag().c_str(); + auto generic_argument_p = + existing_generic_type.generic_type_arguments().begin(); + + // if the original class is implicitly generic, add tags for all generic + // outer classes + // NOTE here we assume that the implicit generic types are ordered from the + // outermost outer class inwards, this is currently guaranteed by the way + // this vector is constructed in + // java_bytecode_convert_class:mark_java_implicitly_generic_class_type + if(is_java_implicitly_generic_class_type(original_class)) { - if(!first) - new_tag_buffer << ", "; - first=false; + const java_implicitly_generic_class_typet + &implicitly_generic_original_class = + to_java_implicitly_generic_class_type(original_class); INVARIANT( - !is_java_generic_parameter(type_argument), - "Only create full concretized generic types"); - const irep_idt &id(id2string(type_argument.subtype().get(ID_identifier))); - new_tag_buffer << pretty_print_java_type(id2string(id)); - if(is_java_array_tag(id)) + existing_generic_type.generic_type_arguments().size() >= + implicitly_generic_original_class.implicit_generic_types().size(), + "All implicit generic types must be concretised"); + auto implicit_generic_type_p = + implicitly_generic_original_class.implicit_generic_types().begin(); + const auto &implicit_generic_types_end = + implicitly_generic_original_class.implicit_generic_types().end(); + std::string current_outer_class_name; + + while(implicit_generic_type_p != implicit_generic_types_end) { - const typet &element_type = - java_array_element_type(to_symbol_type(type_argument.subtype())); - - // If this is an array of references then we will specialize its - // identifier using the type of the objects in the array. Else, there can - // be a problem with the same symbols for different instantiations using - // arrays with different types. - if(element_type.id() == ID_pointer) - { - const symbol_typet element_symbol = - to_symbol_type(element_type.subtype()); - new_tag_buffer << "of_" << id2string(element_symbol.get_identifier()); - } + current_outer_class_name = + (*implicit_generic_type_p).get_parameter_class_name(); + generic_name_buffer << current_outer_class_name; + generic_name_buffer << build_generic_name_for_class_arguments( + generic_argument_p, + implicit_generic_type_p, + implicit_generic_types_end, + current_outer_class_name); } + generic_name_buffer << original_class_name.substr( + current_outer_class_name.length(), std::string::npos); + } + else + { + generic_name_buffer << original_class_name; } - new_tag_buffer << ">"; + // if the original class is generic, add tag for the class itself + if(is_java_generic_class_type(original_class)) + { + const java_generic_class_typet &generic_original_class = + to_java_generic_class_type(original_class); - return new_tag_buffer.str(); + INVARIANT( + std::distance( + generic_argument_p, + existing_generic_type.generic_type_arguments().end()) == + static_cast(generic_original_class.generic_types().size()), + "All generic types must be concretised"); + auto generic_type_p = generic_original_class.generic_types().begin(); + + generic_name_buffer << build_generic_name_for_class_arguments( + generic_argument_p, + generic_type_p, + generic_original_class.generic_types().end(), + original_class_name); + } + + INVARIANT( + generic_argument_p == existing_generic_type.generic_type_arguments().end(), + "All type arguments must have been added to the name"); + return generic_name_buffer.str(); } /// Construct the symbol to be moved into the symbol table diff --git a/src/java_bytecode/generate_java_generic_type.h b/src/java_bytecode/generate_java_generic_type.h index 3e93faf0896..d8648639ba4 100644 --- a/src/java_bytecode/generate_java_generic_type.h +++ b/src/java_bytecode/generate_java_generic_type.h @@ -29,7 +29,7 @@ class generate_java_generic_typet typet substitute_type( const typet ¶meter_type, - const java_generic_class_typet &replacement_type, + const java_class_typet &replacement_type, const java_generic_typet &generic_reference) const; type_symbolt build_symbol_from_specialised_class( diff --git a/src/java_bytecode/java_types.h b/src/java_bytecode/java_types.h index 9e617323067..0f0b15ed0dd 100644 --- a/src/java_bytecode/java_types.h +++ b/src/java_bytecode/java_types.h @@ -116,6 +116,17 @@ class java_generic_parametert:public reference_typet return const_cast(type_variables().front()); } + const std::string get_parameter_class_name() const + { + const std::string ¶meter_name = + type_variable().get_identifier().c_str(); + PRECONDITION(has_prefix(parameter_name, "java::")); + int prefix_length = std::string("java::").length(); + const std::string name = parameter_name.substr( + prefix_length, parameter_name.rfind("::") - prefix_length); + return name; + } + private: typedef std::vector type_variablest; const type_variablest &type_variables() const @@ -410,21 +421,18 @@ inline typet java_type_from_string_with_exception( /// \param identifier The string identifier of the type of the component. /// \return Optional with the size if the identifier was found. inline const optionalt java_generics_get_index_for_subtype( - const java_generic_class_typet &t, + const std::vector &gen_types, const irep_idt &identifier) { - const std::vector &gen_types= - t.generic_types(); - const auto iter = std::find_if( gen_types.cbegin(), gen_types.cend(), [&identifier](const java_generic_parametert &ref) { - return ref.type_variable().get_identifier()==identifier; + return ref.type_variable().get_identifier() == identifier; }); - if(iter==gen_types.cend()) + if(iter == gen_types.cend()) { return {}; } diff --git a/unit/testing-utils/generic_utils.cpp b/unit/testing-utils/generic_utils.cpp index e15276e7bd2..e641e2d9bf5 100644 --- a/unit/testing-utils/generic_utils.cpp +++ b/unit/testing-utils/generic_utils.cpp @@ -32,7 +32,9 @@ void generic_utils::specialise_generic( namespacet ns(new_symbol_table); const typet &class_type = ns.follow(example_type.subtype()); - REQUIRE(is_java_generic_class_type(class_type)); + REQUIRE( + (is_java_generic_class_type(class_type) || + is_java_implicitly_generic_class_type(class_type))); // Generate the specialised version. ui_message_handlert message_handler; From 9617a41a105eb7ee48940ca5a19a3237c8238bce Mon Sep 17 00:00:00 2001 From: svorenova Date: Tue, 28 Nov 2017 18:26:02 +0000 Subject: [PATCH 2/3] Moving a utility function to utility function file --- .../generate_java_generic_type.cpp | 38 ++++--------------- unit/testing-utils/generic_utils.cpp | 18 +++++++++ unit/testing-utils/generic_utils.h | 5 +++ 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp b/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp index f4b8625ceec..ee9178bfb9e 100644 --- a/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp +++ b/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp @@ -7,38 +7,14 @@ \*******************************************************************/ -#include -#include - #include #include #include - -#include +#include #include -#include -#include #include -/// Helper function to specalise a generic class from a named component of a -/// named class -/// \param class_name: The name of the class that has a generic component. -/// \param component_name: The name of the generic component -/// \param new_symbol_table: The symbol table to use. -void specialise_generic_from_component( - const irep_idt &class_name, - const irep_idt &component_name, - symbol_tablet &new_symbol_table) -{ - const symbolt &harness_symbol = new_symbol_table.lookup_ref(class_name); - const struct_typet::componentt &harness_component = - require_type::require_component( - to_struct_type(harness_symbol.type), component_name); - generic_utils::specialise_generic( - to_java_generic_type(harness_component.type()), new_symbol_table); -} - SCENARIO( "generate_java_generic_type_from_file", "[core][java_bytecode][generate_java_generic_type]") @@ -52,7 +28,7 @@ SCENARIO( load_java_class("generic_two_fields", "./java_bytecode/generate_concrete_generic_type"); - specialise_generic_from_component( + generic_utils::specialise_generic_from_component( "java::generic_two_fields", "belem", new_symbol_table); REQUIRE(new_symbol_table.has_symbol(expected_symbol)); @@ -100,7 +76,7 @@ SCENARIO( load_java_class("generic_two_parameters", "./java_bytecode/generate_concrete_generic_type"); - specialise_generic_from_component( + generic_utils::specialise_generic_from_component( "java::generic_two_parameters", "bomb", new_symbol_table); REQUIRE(new_symbol_table.has_symbol( @@ -143,9 +119,9 @@ SCENARIO( load_java_class("generic_two_instances", "./java_bytecode/generate_concrete_generic_type"); - specialise_generic_from_component( + generic_utils::specialise_generic_from_component( "java::generic_two_instances", "bool_element", new_symbol_table); - specialise_generic_from_component( + generic_utils::specialise_generic_from_component( "java::generic_two_instances", "int_element", new_symbol_table); REQUIRE(new_symbol_table.has_symbol(first_expected_symbol)); @@ -276,7 +252,7 @@ SCENARIO( WHEN("We specialise that class from a reference to it") { - specialise_generic_from_component( + generic_utils::specialise_generic_from_component( harness_class, "genericArrayField", new_symbol_table); THEN( "There should be a specialised version of the class in the symbol " @@ -326,7 +302,7 @@ SCENARIO( WHEN( "We specialise the class with an array we should have appropriate types") { - specialise_generic_from_component( + generic_utils::specialise_generic_from_component( harness_class, "genericArrayArrayField", new_symbol_table); THEN( "There should be a specialised version of the class in the symbol " diff --git a/unit/testing-utils/generic_utils.cpp b/unit/testing-utils/generic_utils.cpp index e641e2d9bf5..caa3f8db341 100644 --- a/unit/testing-utils/generic_utils.cpp +++ b/unit/testing-utils/generic_utils.cpp @@ -42,3 +42,21 @@ void generic_utils::specialise_generic( instantiate_generic_type( to_java_generic_type(example_type), new_symbol_table); } + +/// Helper function to specialise a generic class from a named component of a +/// named class +/// \param class_name: The name of the class that has a generic component. +/// \param component_name: The name of the generic component +/// \param new_symbol_table: The symbol table to use. +void generic_utils::specialise_generic_from_component( + const irep_idt &class_name, + const irep_idt &component_name, + symbol_tablet &new_symbol_table) +{ + const symbolt &harness_symbol = new_symbol_table.lookup_ref(class_name); + const struct_typet::componentt &harness_component = + require_type::require_component( + to_struct_type(harness_symbol.type), component_name); + generic_utils::specialise_generic( + to_java_generic_type(harness_component.type()), new_symbol_table); +} diff --git a/unit/testing-utils/generic_utils.h b/unit/testing-utils/generic_utils.h index 4bfc70fb4be..e0d36d7beb7 100644 --- a/unit/testing-utils/generic_utils.h +++ b/unit/testing-utils/generic_utils.h @@ -21,6 +21,11 @@ namespace generic_utils void specialise_generic( const java_generic_typet &example_type, symbol_tablet &new_symbol_table); + +void specialise_generic_from_component( + const irep_idt &class_name, + const irep_idt &component_name, + symbol_tablet &new_symbol_table); } #endif // CPROVER_TESTING_UTILS_GENERIC_UTILS_H From 2fd93004673e1ae7c48e5691a40ad64d4010a95c Mon Sep 17 00:00:00 2001 From: svorenova Date: Tue, 28 Nov 2017 18:27:11 +0000 Subject: [PATCH 3/3] Adding a unit test for specialisation of implicitly generic classes --- .../generate_java_generic_type.cpp | 25 +- .../generate_outer_inner.cpp | 598 ++++++++++++++++++ ...uter_inner$GenericOuter$GenericInner.class | Bin 0 -> 751 bytes ..._inner$GenericOuter$Inner$InnerInner.class | Bin 0 -> 825 bytes ...neric_outer_inner$GenericOuter$Inner.class | Bin 0 -> 826 bytes .../generic_outer_inner$GenericOuter.class | Bin 0 -> 1060 bytes ...Outer$GenericInner$GenericInnerInner.class | Bin 0 -> 929 bytes ..._inner$Outer$GenericInner$InnerInner.class | Bin 0 -> 818 bytes ...neric_outer_inner$Outer$GenericInner.class | Bin 0 -> 1031 bytes ..._inner$Outer$Inner$GenericInnerInner.class | Bin 0 -> 848 bytes ...c_outer_inner$Outer$Inner$InnerInner.class | Bin 0 -> 769 bytes .../generic_outer_inner$Outer$Inner.class | Bin 0 -> 605 bytes ...uter$TwoParamGenericInner$InnerInner.class | Bin 0 -> 904 bytes ...ter_inner$Outer$TwoParamGenericInner.class | Bin 0 -> 911 bytes .../generic_outer_inner$Outer.class | Bin 0 -> 654 bytes .../generic_outer_inner.class | Bin 0 -> 3112 bytes .../generic_outer_inner.java | 82 +++ 17 files changed, 694 insertions(+), 11 deletions(-) create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generate_outer_inner.cpp create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$GenericInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$Inner$InnerInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$Inner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner$GenericInnerInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner$InnerInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner$GenericInnerInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner$InnerInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$TwoParamGenericInner$InnerInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$TwoParamGenericInner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner.class create mode 100644 unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner.java diff --git a/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp b/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp index ee9178bfb9e..8155bdf3ef7 100644 --- a/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp +++ b/unit/java_bytecode/generate_concrete_generic_type/generate_java_generic_type.cpp @@ -19,7 +19,8 @@ SCENARIO( "generate_java_generic_type_from_file", "[core][java_bytecode][generate_java_generic_type]") { - auto expected_symbol = "java::generic_two_fields$bound_element"; + auto expected_symbol = + "java::generic_two_fields$bound_element"; GIVEN("A generic java type with two generic fields and a concrete " "substitution") @@ -35,7 +36,7 @@ SCENARIO( THEN("The class should contain two instantiated fields.") { const auto &class_symbol = new_symbol_table.lookup( - "java::generic_two_fields$bound_element"); + "java::generic_two_fields$bound_element"); const typet &symbol_type=class_symbol->type; REQUIRE(symbol_type.id()==ID_struct); @@ -68,7 +69,8 @@ SCENARIO( "[core][java_bytecode][generate_java_generic_type]") { auto expected_symbol = - "java::generic_two_parameters$KeyValuePair"; + "java::generic_two_parameters$KeyValuePair"; GIVEN("A generic java type with two generic parameters, like a Hashtable") { @@ -109,8 +111,10 @@ SCENARIO( // After we have loaded the class and converted the generics, // the presence of these two symbols in the symbol table is // proof enough that we did the work we needed to do correctly. - auto first_expected_symbol = "java::generic_two_instances$element"; - auto second_expected_symbol = "java::generic_two_instances$element"; + auto first_expected_symbol = + "java::generic_two_instances$element"; + auto second_expected_symbol = + "java::generic_two_instances$element"; GIVEN("A generic java type with a field that refers to another generic with" " an uninstantiated parameter.") @@ -204,8 +208,7 @@ SCENARIO( { const irep_idt test_class_integer = "java::generic_field_array_instantiation$generic"; + "of_java::java.lang.Integer>"; const irep_idt test_class_int = "java::generic_field_array_instantiation$generic"; @@ -258,8 +261,9 @@ SCENARIO( "There should be a specialised version of the class in the symbol " "table") { - const irep_idt specialised_class_name = - id2string(harness_class) + "$" + id2string(inner_class) + ""; + const irep_idt specialised_class_name = id2string(harness_class) + "$" + + id2string(inner_class) + + ""; REQUIRE(new_symbol_table.has_symbol(specialised_class_name)); const symbolt test_class_symbol = @@ -309,8 +313,7 @@ SCENARIO( "table") { const std::string specialised_string = - ""; + ""; const irep_idt specialised_class_name = id2string(harness_class) + "$" + id2string(inner_class) + specialised_string; diff --git a/unit/java_bytecode/generate_concrete_generic_type/generate_outer_inner.cpp b/unit/java_bytecode/generate_concrete_generic_type/generate_outer_inner.cpp new file mode 100644 index 00000000000..d6c8b271d38 --- /dev/null +++ b/unit/java_bytecode/generate_concrete_generic_type/generate_outer_inner.cpp @@ -0,0 +1,598 @@ +/*******************************************************************\ + + Module: Unit tests for generating new type with generic parameters + substitued for concrete types + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include +#include + +SCENARIO("generate_outer_inner", "[core][java_bytecode][generate_outer_inner]") +{ + WHEN("Loading a class with generic and non-generic inner classes") + { + symbol_tablet new_symbol_table = load_java_class( + "generic_outer_inner", "./java_bytecode/generate_concrete_generic_type"); + const std::string &class_prefix = "java::generic_outer_inner"; + + WHEN("Its field t1 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t1", new_symbol_table); + const std::string &expected_prefix = + class_prefix + "$GenericOuter"; + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), + symbol_typet("java::generic_outer_inner$GenericOuter$Inner")); + require_type::require_java_generic_type( + field.type(), + {{require_type::type_argument_kindt::Inst, + "java::java.lang.Integer"}}); + } + + THEN("It has field f3 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f3"); + require_type::require_pointer( + field.type(), + symbol_typet( + "java::generic_outer_inner$GenericOuter$GenericInner")); + require_type::require_java_generic_type( + field.type(), + {{require_type::type_argument_kindt::Inst, + "java::java.lang.Integer"}, + {require_type::type_argument_kindt::Inst, + "java::java.lang.String"}}); + } + + THEN("It has field this$0 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$0"); + require_type::require_pointer( + field.type(), symbol_typet("java::generic_outer_inner")); + } + } + } + + WHEN("Its field t2 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t2", new_symbol_table); + const std::string &expected_prefix = + class_prefix + "$GenericOuter$Inner"; + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field this$1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$1"); + // TODO should be java generic type - TG-1826 + } + } + } + + WHEN("Its field t2a is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t2a", new_symbol_table); + const std::string &expected_prefix = + class_prefix + + "$GenericOuter$Inner"; + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + const symbol_typet &field_array = + to_symbol_type(field.type().subtype()); + REQUIRE(field_array.get_identifier() == "java::array[reference]"); + require_type::require_pointer( + java_array_element_type(field_array), + symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field this$1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$1"); + // TODO should be java generic type - TG-1826 + } + } + } + + WHEN("Its field t3 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t3", new_symbol_table); + const std::string &expected_prefix = + class_prefix + "$GenericOuter$Inner$InnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.String")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + // TODO should be java generic type - TG-1826 + } + } + } + + WHEN("Its field t3a is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t3a", new_symbol_table); + const std::string &expected_prefix = class_prefix + + "$GenericOuter$Inner$" + "InnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + const symbol_typet &field_array = + to_symbol_type(field.type().subtype()); + REQUIRE(field_array.get_identifier() == "java::array[reference]"); + require_type::require_pointer( + java_array_element_type(field_array), + symbol_typet("java::java.lang.String")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + // TODO should be java generic type - TG-1826 + } + } + } + + // TODO add test for field t4 once TG-1633 is done + + WHEN("Its field t5 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t5", new_symbol_table); + const std::string &expected_prefix = + class_prefix + + "$Outer$Inner$GenericInnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + require_type::require_pointer( + field.type(), symbol_typet(class_prefix + "$Outer$Inner")); + } + } + } + + WHEN("Its field t6 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t6", new_symbol_table); + const std::string &expected_prefix = + class_prefix + "$Outer$GenericInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), + symbol_typet( + "java::generic_outer_inner$Outer$" + "GenericInner$GenericInnerInner")); + require_type::require_java_generic_type( + field.type(), + {{require_type::type_argument_kindt::Inst, + "java::java.lang.Integer"}, + {require_type::type_argument_kindt::Inst, + "java::java.lang.String"}}); + } + + THEN("It has field this$1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$1"); + require_type::require_pointer( + field.type(), symbol_typet(class_prefix + "$Outer")); + } + } + } + + WHEN("Its field t7 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t7", new_symbol_table); + const std::string &expected_prefix = + class_prefix + + "$Outer$GenericInner$InnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + // TODO should be java generic type - TG-1826 + } + } + } + + WHEN("Its field t7a is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t7a", new_symbol_table); + const std::string &expected_prefix = + class_prefix + + "$Outer$GenericInner$InnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + const symbol_typet &field_array = + to_symbol_type(field.type().subtype()); + REQUIRE(field_array.get_identifier() == "java::array[reference]"); + require_type::require_pointer( + java_array_element_type(field_array), + symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + // TODO should be java generic type - TG-1826 + } + } + } + + // TODO add test for field t8 once TG-1633 is done + + WHEN("Its field t9 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t9", new_symbol_table); + const std::string &expected_prefix = class_prefix + + "$Outer$TwoParamGenericInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.String")); + } + + THEN("It has field this$1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$1"); + require_type::require_pointer( + field.type(), symbol_typet(class_prefix + "$Outer")); + } + } + } + + WHEN("Its field t10 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t10", new_symbol_table); + const std::string &expected_prefix = class_prefix + + "$Outer$TwoParamGenericInner$InnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), symbol_typet("java::java.lang.String")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + // TODO should be java generic type - TG-1826 + } + } + } + + WHEN("Its field t10a is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t10a", new_symbol_table); + const std::string &expected_prefix = + class_prefix + + "$Outer$TwoParamGenericInner$InnerInner"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + const symbol_typet &field_array = + to_symbol_type(field.type().subtype()); + REQUIRE(field_array.get_identifier() == "java::array[reference]"); + require_type::require_pointer( + java_array_element_type(field_array), + symbol_typet("java::java.lang.Integer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + const symbol_typet &field_array = + to_symbol_type(field.type().subtype()); + REQUIRE(field_array.get_identifier() == "java::array[reference]"); + require_type::require_pointer( + java_array_element_type(field_array), + symbol_typet("java::java.lang.String")); + } + + THEN("It has field this$2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$2"); + // TODO should be java generic type - TG-1826 + } + } + } + + WHEN("Its field t11 is specialised") + { + generic_utils::specialise_generic_from_component( + class_prefix, "t11", new_symbol_table); + const std::string &expected_prefix = + class_prefix + "$GenericOuter"; + + THEN("The corresponding specialised class symbol is created") + { + REQUIRE(new_symbol_table.has_symbol(expected_prefix)); + const symbolt &expected_symbol = + new_symbol_table.lookup_ref(expected_prefix); + + const struct_typet class_struct = to_struct_type(expected_symbol.type); + REQUIRE(is_java_specialized_generic_class_type(class_struct)); + + THEN("It has field f1 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f1"); + require_type::require_pointer( + field.type(), symbol_typet("java::generic_outer_inner$Outer")); + } + + THEN("It has field f2 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), + symbol_typet("java::generic_outer_inner$GenericOuter$Inner")); + require_type::require_java_generic_type( + field.type(), + {{require_type::type_argument_kindt::Inst, + "java::generic_outer_inner$Outer"}}); + } + + THEN("It has field f3 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f3"); + require_type::require_pointer( + field.type(), + symbol_typet( + "java::generic_outer_inner$GenericOuter$GenericInner")); + require_type::require_java_generic_type( + field.type(), + {{require_type::type_argument_kindt::Inst, + "java::generic_outer_inner$Outer"}, + {require_type::type_argument_kindt::Inst, + "java::java.lang.String"}}); + } + + THEN("It has field this$0 of correct type") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "this$0"); + require_type::require_pointer( + field.type(), symbol_typet(class_prefix)); + } + } + } + } +} diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$GenericInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$GenericInner.class new file mode 100644 index 0000000000000000000000000000000000000000..1d9fe54995c41473bf2672c2c508fc9c4aef8038 GIT binary patch literal 751 zcmah{TT22#6#m9FH*M2R%j_;;U`9&NOS$+W6v2{#mseSBu#s(z-8JZE^$CA%6;fCsBpD literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$Inner$InnerInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$Inner$InnerInner.class new file mode 100644 index 0000000000000000000000000000000000000000..8f6d49bec1f34eac75ae7bf452a6d39aa5d135e8 GIT binary patch literal 825 zcma)4T}uK%6g}6qHaE*n%f8FX!W0y%hamAqC<3V<@l{rvY{b@BcY}Ub4-xdx59mil zcXkyl1bf&!=iEK_&Y3&&_5JY)-~{^-XxK0i#-@%f9ovM^eUT8acC2Ts(6#J#;kwxo zE%%HNxs`3(ay>^7v|5cb)9!=pr;l{(5TX~t7LIIPd#-SpUfN76U8~<0eI2`mDL+HV zRNH~F(NoffRKoOVb=p^|{v~Nkw@k?WyXde^2v>S{>@ilAwz%>ho5HDC%`Ru+)n3c$ z)-6XWK1hbuAqa-Q>A>UhKRpIchjx>{+rK;ww>X{HuEg^!=lw=O9QHJBd!Ex0=TiA! z88f-Ox~V84h(%#yk5C*V8Z+Jz>jd-fb?ZnIQj(W#>AhA1zzKfZdj?bMmF~b%DyA?%1lFoqpAj1Epki-DlB1{8SDLS jJVnM)UuW>YRc0Zq`Ei}|V63q=g;~aPjOKaO7$t!pJm=Uv literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$Inner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$GenericOuter$Inner.class new file mode 100644 index 0000000000000000000000000000000000000000..bc9fa9be68599fa59170c15aa5018d24295ef73d GIT binary patch literal 826 zcmah|O;5r=5Pj2vm5Ne95%CKZ6){3E-ZWlJG$ce!AYM(u1=nCPrI`4$JQx!X{s4cJ zakhm-4M`6>GjIC#?dx>=_5JY);23)`=vX%q!G?jHflUM3g!rX!ge%+ip(k91Rfpku z&mIiKfDrYefjq(VOFs~_PKA)HJ=o87xo11wa=rB++TIBv){tGt_J*z?=*=c~w9XMB z^^03|Jkb>{KbrFHeTeWUrDS+)Cvl|J#~kpGrr1XM~+XIDP+y5IOJPv5iDc zI^t^h*b;8jZuPj6to7S=@5Xke!lPzHnIVL0=lvnDq4Zywm#4ARVW_`T9?e;4EMzwN zL$@t1q%xP8Fp83zbR6?Y#*xAfVRr)Q&%6SY1nd7dGO$a?g>5HP!YIKBK^$ERy`aXP zny?c&zI+kBhdQqr#6g(lO2Zt-1T4U^)ax-KUMVbaUgYYUIT~lPc<=@)zC(Luq$AC7 z%I8M0#C1AgA%kT`%=gs@S+3P-s*}MAXAP@Vbl_=_4GLKqj{(V zZof~DGkPkhcgKrlr&E*dRGVD2JT=R{C zZ;-}!IA4ie+~jlBa$Ve_U0$%TjoU=zTQ$KQ+NKKQ*~VS2Zd_3n_lO+qPzTg=c|E`i OZI9L^uI87J2mSyT+8eO| literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner$GenericInnerInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner$GenericInnerInner.class new file mode 100644 index 0000000000000000000000000000000000000000..be2037c6c8873fa2b5d6a371fdbff5143c1e6b41 GIT binary patch literal 929 zcma)4T}vB56g_u0y3M*ZF>3s3)z)aEf>QB8G~~rnDTG=`^i?)-j3eo$Y&L>F%LfsB z@CW##if7gciHVShnK}2&xp(f|d!PP4JObE7J_#F3E)rOF@WsJbfpzg+kSSgH*Zy|H z59-^;)hktt4g|@vt_Ob94wb;JRLEEtI|iN*jz*WdmD_QU6O0_UBNYm~UqPV4!-n5# zsg{FPGDnJxuEiIEe5w9opEZrgnKt@d?49dYn)n4B=%^^z9NKC9RFF7qo-^H4NeAk8 z`)^f+6~EdblPNW8e&f^+wXr*7!hAw7(fxKO)%_t;?a4d#W%AkH$8P?;KKNtEs0Eh0 zxYd_dfu%1pe!g(B-`}xfKP7O>&30H*KeZ{s?11ubna+C{!-R(n)&zS4L<4%%|8YV3 z?G!oqCYXCSpkVFYyPo)*y1Z%c>AyKFa|Hs2>p3LA zoFe)|t;N&b*t~;m+{3!1Wn-GVi3Y4A%RT#|!VKnUQ6EPW%oBUD&gI<#ExVJ!Cw!)5 XVG-jz=gE6m!AIg0Q94$pFbg~bq+9Y< literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner$InnerInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner$InnerInner.class new file mode 100644 index 0000000000000000000000000000000000000000..36972ebe360552e5d277b3381c4a95fbadf1d6e8 GIT binary patch literal 818 zcma)4+e*Vg5IvKm#>Q%6tMz`5Qd>~GJP3*}1w{xdSo&Jhy4IDLN}39OmJcHM;0O3o z;%uzgN`*e`?wQ#$vu9`K_vL0U$ z@^0hXt~OOfRVuy{M?2k2mH$WvGCC#{2M*e-5R6junl+|f8Hn@teNBXAujaES<2LJ_ zU-3ez?2gk=pCDMVypG1b0W~_mK`b}doBrwH=ZS*>(;abDkGFbqT35|>SQjT!>7VXX zxh>VH6p~1%U}KH2(}&cjyj{`>_TP4!a0oO1W+H6-d)L!Mo|L?5NwyCi%RGDr&!NUE zfgupg*c!HN^&iH>%f>jL8Ag}PR9vf2d;t|+p*^#uBg?yr1{_TAp8IBD5>sq3KhDPG iW1Nb47T?XVrC~PS=hzR%I&+sX!g!R?7@s<$9PkBgpw)>0 literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$GenericInner.class new file mode 100644 index 0000000000000000000000000000000000000000..2368c6b18abecb67f59d4a944659ca6a37f03e96 GIT binary patch literal 1031 zcma)5T}vB56g@W|u5Pz&G;RE9)yAk%sUq}2OvsC1DTG=`@KrYHG>*iLY&JrFmJcHI zp+BHMs`Sic#Vk$4hnaiN-E+^}xp(K!-(SB0e8Tn&(pYto!J2~)4vG#+g6!!aQlY^6 z5(Fwd?)v?{>Jxregt~2`4mJd{qmekgDR8Z8H$m#hf#9g#8Rnk%jP$uS!XVbvx*dA} literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner$GenericInnerInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner$GenericInnerInner.class new file mode 100644 index 0000000000000000000000000000000000000000..af00787fbf9d3d4f96a81cbe376b29082d8ff9f1 GIT binary patch literal 848 zcmb7CT~8WO5Iw_(E8A5UsI+J+erye;i3IIK(-K}x+L(~qM8d0C@QRnvrCF9H{aJlz zOnmSM_@j*HE;MNi#Ps3bJ0EAx%$=FL`zW?2? z4*Z~3J?->WH~JvRoatWRN8?ZllC2gkOVO1cd50Eu1?kgqq(Xsn5(Fwd9{8h?8d=z* zC$*dhZihot*Ha`dHl7b!j|6| z(2{EoyZ)fe<^VP-31G;1jU6+g3?0Y zWYFB7vYB3f4i4K~$rQIU!IQ=k1XipqyRP{NW#Ms=<(s4Qg-C<7D{p>5D%VK-q?SaU zw}}Q`;3@CI1ch}xqegtp#=cQ@Vw_E1ky>(^aRZyw5{!5FZqROH2Tv%kP+EDn literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner$InnerInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$Inner$InnerInner.class new file mode 100644 index 0000000000000000000000000000000000000000..d481c3322f3bff43511df16204c9f774d4c4ed36 GIT binary patch literal 769 zcmah{T}uK%6g}5fH#f^o%d#)EHZTjN=q>Rj2m+}<@l{qEY{b@B*Px%(Lj*na1Nu?X zol&7e>0$4jd+(VuXYb7C*ZT*6GaSTVVB10%J0^BbWC@`lAS7!&_sK2yU9VfdY4=1Y zI48vFvg^6Q$QJ~o(cnrnxR*oc)I^>Txfun*C&aHjPxu#ocQ_P76MNjz6+*t&72J}Y z)<98PQV|`!&CwL4SdpF#ssyL-FZ-}b2wx2D*iND*J#jsHXbZpLw)pnkDwNK{jRCrj`l2#bUshCwCjQozcl*;kOjOmor zHN+7^A`Tn-gyIa+&k_DGOR)c5q6vqPnJYoa&h3qb`Qi&|?5P<%sT*8U+oUc2FAv7VgFnC@ zWt?rj31-uoH#2YE&hGZ>`{NV9CEDA_p=LtIfq}Y#hJh9#KUpOrB3QRUAfln~#<7Sw zorVSu3FVRCiuBSAnY>MT?`GpSUZRP%~y*D{dFfN?) z5K3bih`ZJETtpA<+~-VX9D1%lbt9?b-=wa#C!B5;b<#n31oJ*zMV`2kO02$S*o&q6 z;#$~&Wub^8LVFDp+1Z0sZSH`X#uXY}`ua~*Xt)is?s z;g{6;QOUN|;0p0q#4h_1qX9HtfZ08N19jh_y>g_%W?M+PO_UkeG8QVRa>V>pjX1l< Xk%oO3?3=t>o^64#LR;+BzhnYGaG94H literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$TwoParamGenericInner$InnerInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$TwoParamGenericInner$InnerInner.class new file mode 100644 index 0000000000000000000000000000000000000000..d7e166e8c9a1e2daac85d364a32f9b75b6417a10 GIT binary patch literal 904 zcmb7DT~8BH5IwV7Si7uJ3sgQt0apb~3IZ<%!b=m3NdqL*zLMK|sh5;pvfXO@Sv(LD z9{2(LDC4;cL@2c{FLw4Z2!+xSY4bF^k*lW;iwZhGOGhc|+uy?&|_LGUGtbW-c8 zUQhQtgo5$L&v;)Y>g2QLjcI2Ag4KHG#y*T~=Ap59Va5{XW!QRKCNk-^V104Wa8@jnTS^^lty8rIUtgb?GVBnzyj1b+71+c$3xST_8d%;#4gmicvh zSE@E3?G^{Y0c=+v(EA5*KWXb7V_TZc`M6a(-vA?c9-xf3f=@X?|CzwOZUm)&m&L<7 z!PKLSg6gApx%1|dE!wG#<)mSbD_r0&-P0t+b_MsQ^pweIMF_1 z9cq91!#QO60?rvN7Za40&Hg79%F0a?USNtA<1;qFG;xr{`MjH<<=|x|XYq`Bnp^=E P@RWFzs6_1&O#*)aQ*G|r literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$TwoParamGenericInner.class b/unit/java_bytecode/generate_concrete_generic_type/generic_outer_inner$Outer$TwoParamGenericInner.class new file mode 100644 index 0000000000000000000000000000000000000000..8ce274e530ce1ce6d4ea37986fefaa410410220d GIT binary patch literal 911 zcmb7DT~8B16g_vhWuaCnE!G0chb&kj0U9fnc_E88%gxmmg@A06dPez_1h{kHogTjHof50cu_yCeO6TdQ|{~M-;!_s zQ>(_2a1?cF)@sM^?oY6tg4OTScppdMFzV`kW81ByjC0H0P98HT=261BU@L_*nt5v5 zg2LbT>*0l9Zmf*p?bx%_6#m^ePqdJZ0OpS}|p3I*FQ zQQ<0Kmi95dCb6Y**ed=VR#)#Mt3XrsqwBGZen9;&n2vN)k#@a<%YqT-JE>mi|QE z+DgWX*jjTYUPKDJ*h?XeijGr4F@jqu5=_On9N|t|{qamr0zz{mUW@7^;cWAQ?w^(u z%A3J;-(z*vxNHQ63SW7gZ=Xz49Zz{Y(lFWXv)6{kA7C^t-a(BIXm1>8$nZZIvKF%J p7giK<$aBPes79PEaHQdYX`srrVmL&CeVx56w(8LtYkQ_`6<)!*flGd}nO z{85fyE)5&IZQ6(K?)mmR-z7QO?VrEDegjy+=Lmv$E8(4lf`s=B;lqZZ=nT=krYZVv zRj${Sx`YF=qp(_k&U&2=5QvN0< zs_@2F_#s#eKl?Mm#i87XL_sJDIpczkc20tSo~2_LTI z;`EvD&Crxhv$8W^hOkFRd{z|R!Ke@bKTEZuWPQCLfy?X4_JI@kk|6h=45@cTZ@&)bivUFduH)6n8 zmvF+c*=0yX=!aLO=x{JnN0>+%&(WLWA@gor^APkW?@ z>gP^1uGXNDT#|6ckm)gnS30F0* zrQ|K4hqYy0d3{@|rW#p>;M_dvH?&*3peuBsplZrN| z3>jb5I>VSK2k9bGtTptqvZtB>#w)G2c-*{(qj-r|3?qVlhQaHL`ml7VlnsUnfn&^S zh+#^!m-GCmnDuk9rNfZy&XH3Z!=f+8DaN@4CPn`C3FLSPtKd9Z4-y7pi#ErbzC&={ z(bM93`;t8z9yqmfign;T5D^yiRxn z85eI6-sW(Y@DA7C3-V;<7e(VP?IkP>gcp8-{UAdCuW9TfGwAn*#;COpV-GoNf8QGO z + { + class Inner { + T f1; + Integer f2; + + class InnerInner { + T f1; + } + } + + class GenericInner + { + + } + + T f1; + Inner f2; + GenericInner f3; + } + + class Outer + { + class Inner + { + class GenericInnerInner + { + T f1; + } + } + + class GenericInner + { + class InnerInner + { + T f1; + } + + class GenericInnerInner + { + T f1; + U f2; + } + + GenericInnerInner f1; + } + + class TwoParamGenericInner + { + class InnerInner + { + U f1; + V f2; + } + + U f1; + V f2; + } + } + + GenericOuter t1; + GenericOuter.Inner t2; + GenericOuter.Inner t2a; + GenericOuter.Inner.InnerInner t3; + GenericOuter.Inner.InnerInner t3a; + GenericOuter.GenericInner t4; + + Outer.Inner.GenericInnerInner t5; + Outer.GenericInner t6; + Outer.GenericInner.InnerInner t7; + Outer.GenericInner.InnerInner t7a; + Outer.GenericInner.GenericInnerInner t8; + + Outer.TwoParamGenericInner t9; + Outer.TwoParamGenericInner.InnerInner t10; + Outer.TwoParamGenericInner.InnerInner t10a; + + GenericOuter t11; +} +