From 37b1ed6b43cc356af5cb359fa9bfc52936304f25 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 23 Feb 2018 17:53:14 +0000 Subject: [PATCH 1/7] Adding utiltiy functions required for unit tests --- unit/testing-utils/require_parse_tree.cpp | 117 ++++++++++++++++++++++ unit/testing-utils/require_parse_tree.h | 60 +++++++++++ 2 files changed, 177 insertions(+) create mode 100644 unit/testing-utils/require_parse_tree.cpp create mode 100644 unit/testing-utils/require_parse_tree.h diff --git a/unit/testing-utils/require_parse_tree.cpp b/unit/testing-utils/require_parse_tree.cpp new file mode 100644 index 00000000000..500e173a55b --- /dev/null +++ b/unit/testing-utils/require_parse_tree.cpp @@ -0,0 +1,117 @@ +/*******************************************************************\ + + Module: Unit test utilities + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include "require_parse_tree.h" + +/// Find in the parsed class a specific entry within the +/// lambda_method_handle_map with a matching descriptor. Will fail if no +/// matching lambda entry found. +/// \param parsed_class: the class to inspect +/// \param descriptor: the descriptor the lambda method should have +/// \param entry_index: the number to skip (i.e. if multiple entries with the +/// same descriptor +/// \return +require_parse_tree::lambda_method_handlet +require_parse_tree::require_lambda_entry_for_descriptor( + const java_bytecode_parse_treet::classt &parsed_class, + std::string descriptor, + const size_t entry_index) +{ + REQUIRE(entry_index < parsed_class.lambda_method_handle_map.size()); + typedef java_bytecode_parse_treet::classt::lambda_method_handle_mapt:: + value_type lambda_method_entryt; + + int matches_found = 0; + + const auto matching_lambda_entry = std::find_if( + parsed_class.lambda_method_handle_map.begin(), + parsed_class.lambda_method_handle_map.end(), + [&descriptor, &matches_found, &entry_index]( + const lambda_method_entryt &entry) { + if(entry.second.method_type == descriptor) + { + ++matches_found; + return matches_found == entry_index + 1; + } + return false; + }); + + INFO("Looking for descriptor: " << descriptor); + std::ostringstream found_entries; + for(const auto entry : parsed_class.lambda_method_handle_map) + { + found_entries << id2string(entry.first.first) << ": " + << id2string(entry.second.method_type) << std::endl; + } + INFO("Found descriptors:\n" << found_entries.str()); + + REQUIRE(matching_lambda_entry != parsed_class.lambda_method_handle_map.end()); + + return matching_lambda_entry->second; +} + +/// Finds a specific method in the parsed class with a matching name. +/// \param parsed_class: The class +/// \param method_name: The name of the method to look for +/// \return The methodt structure with the corresponding name +const require_parse_tree::methodt require_parse_tree::require_method( + const java_bytecode_parse_treet::classt &parsed_class, + const irep_idt &method_name) +{ + const auto method = std::find_if( + parsed_class.methods.begin(), + parsed_class.methods.end(), + [&method_name](const java_bytecode_parse_treet::methodt &method) { + return method.name == method_name; + }); + + INFO("Looking for method: " << method_name); + std::ostringstream found_methods; + for(const auto entry : parsed_class.methods) + { + found_methods << id2string(entry.name) << std::endl; + } + INFO("Found methods:\n" << found_methods.str()); + + REQUIRE(method != parsed_class.methods.end()); + + return *method; +} + +/// Verify whether a given methods instructions match an expectation +/// \param expected_instructions: The expected instructions for a given method +/// \param instructions: The instructions of a method +void require_parse_tree::require_instructions_match_expectation( + const expected_instructionst &expected_instructions, + const java_bytecode_parse_treet::methodt::instructionst instructions) +{ + REQUIRE(instructions.size() == expected_instructions.size()); + auto actual_instruction_it = instructions.begin(); + for(const auto expected_instruction : expected_instructions) + { + expected_instruction.require_instructions_equal(*actual_instruction_it); + ++actual_instruction_it; + } +} + +/// Check whether a given instruction matches an expectation of the instruction +/// \param actual_instruction: The instruction to check +void require_parse_tree::expected_instructiont::require_instructions_equal( + java_bytecode_parse_treet::instructiont actual_instruction) const +{ + REQUIRE(actual_instruction.statement == instruction_mnemoic); + REQUIRE(actual_instruction.args.size() == instruction_arguments.size()); + auto actual_arg_it = actual_instruction.args.begin(); + for(const exprt &expected_arg : actual_instruction.args) + { + INFO("Expected argument" << expected_arg.pretty()); + INFO("Actual argument" << actual_arg_it->pretty()); + REQUIRE(*actual_arg_it == expected_arg); + ++actual_arg_it; + } +} diff --git a/unit/testing-utils/require_parse_tree.h b/unit/testing-utils/require_parse_tree.h new file mode 100644 index 00000000000..bdf932b75cd --- /dev/null +++ b/unit/testing-utils/require_parse_tree.h @@ -0,0 +1,60 @@ +/*******************************************************************\ + + Module: Unit test utilities + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +/// \file +/// Utilties for inspecting java_parse_treet + +#ifndef CPROVER_TESTING_UTILS_REQUIRE_PARSE_TREE_H +#define CPROVER_TESTING_UTILS_REQUIRE_PARSE_TREE_H + +#include +#include "catch.hpp" + +// NOLINTNEXTLINE(readability/namespace) +namespace require_parse_tree +{ +typedef java_bytecode_parse_treet::classt::lambda_method_handlet + lambda_method_handlet; + +lambda_method_handlet require_lambda_entry_for_descriptor( + const java_bytecode_parse_treet::classt &parsed_class, + std::string descriptor, + const size_t entry_index = 0); + +typedef java_bytecode_parse_treet::methodt methodt; + +const methodt require_method( + const java_bytecode_parse_treet::classt &parsed_class, + const irep_idt &method_name); + +struct expected_instructiont +{ + expected_instructiont( + const irep_idt &instruction_mnemoic, + const std::vector &instruction_arguments) + : instruction_mnemoic(instruction_mnemoic), + instruction_arguments(instruction_arguments) + { + } + + void require_instructions_equal( + java_bytecode_parse_treet::instructiont actual_instruction) const; + +private: + const irep_idt instruction_mnemoic; + const std::vector instruction_arguments; +}; + +typedef std::vector expected_instructionst; + +void require_instructions_match_expectation( + const expected_instructionst &expected_instructions, + const java_bytecode_parse_treet::methodt::instructionst instructions); +} + +#endif //CPROVER_TESTING_UTILS_REQUIRE_PARSE_TREE_H From c020687adc2e2c59bfe9e0cbbb8f412ea63f44c6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 23 Feb 2018 18:01:48 +0000 Subject: [PATCH 2/7] Adding tests for static lambdas --- ...ava_bytecode_parse_lambda_method_table.cpp | 278 ++++++++++++++++++ .../ArrayParameterLambda.class | Bin 0 -> 257 bytes .../lambda_examples/DummyGeneric.class | Bin 0 -> 441 bytes .../lambda_examples/LambdaInterfaces.java | 39 +++ .../lambda_examples/ParameterLambda.class | Bin 0 -> 246 bytes .../ReturningLambdaPrimitive.class | Bin 0 -> 142 bytes .../ReturningLambdaPrimitiveArray.class | Bin 0 -> 148 bytes .../ReturningLambdaReference.class | Bin 0 -> 159 bytes .../ReturningLambdaReferenceArray.class | Bin 0 -> 165 bytes .../ReturningLambdaSpecalisedGeneric.class | Bin 0 -> 223 bytes ...eturningLambdaSpecalisedGenericArray.class | Bin 0 -> 230 bytes .../lambda_examples/SimpleLambda.class | Bin 0 -> 130 bytes .../lambda_examples/StaticLambdas.class | Bin 0 -> 4245 bytes .../lambda_examples/StaticLambdas.java | 37 +++ 14 files changed, 354 insertions(+) create mode 100644 unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ArrayParameterLambda.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/DummyGeneric.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/LambdaInterfaces.java create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ParameterLambda.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitive.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaPrimitiveArray.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReference.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaReferenceArray.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGeneric.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/ReturningLambdaSpecalisedGenericArray.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/SimpleLambda.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.java diff --git a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp new file mode 100644 index 00000000000..91fc9c18df2 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp @@ -0,0 +1,278 @@ +/*******************************************************************\ + + Module: Unit tests for parsing generic classes + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +typedef java_bytecode_parse_treet::classt::lambda_method_handlet + lambda_method_handlet; + +SCENARIO( + "lambda_method_handle_map with static lambdas", + "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") +{ + null_message_handlert message_handler; + GIVEN("A class with a static lambda variables") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + "StaticLambdas.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); + + // Simple lambdas + THEN( + "There should be an entry for the lambda that has no parameters or " + "returns and the method it references should have an appropriate " + "descriptor") + { + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, "()V"); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()V"); + } + + // Parameter lambdas + THEN( + "There should be an entry for the lambda that takes parameters and the " + "method it references should have an appropriate descriptor") + { + std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that takes array parameters " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Return lambdas + THEN( + "There should be an entry for the lambda that returns a primitive and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Array returning lambdas + THEN( + "There should be an entry for the lambda that returns an array of " + "primitives and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()[I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "reference types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "specialised generic types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Capturing lamdbas + THEN( + "There should be an entry for the lambda that returns a primitive and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + + const typet primitive_type = java_int_type(); + + fieldref_exprt fieldref{ + primitive_type, "staticPrimitive", "java::StaticLambdas"}; + + std::vector + expected_instructions{{"getstatic", {fieldref}}, {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::java.lang.Object"}); + + fieldref_exprt fieldref{dummy_generic_reference_type, + "staticReference", + "java::StaticLambdas"}; + + std::vector + expected_instructions{{"getstatic", {fieldref}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::DummyGeneric"}); + + fieldref_exprt fieldref{dummy_generic_reference_type, + "staticSpecalisedGeneric", + "java::StaticLambdas"}; + + std::vector + expected_instructions{{"getstatic", {fieldref}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ArrayParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ArrayParameterLambda.class new file mode 100644 index 0000000000000000000000000000000000000000..56886405324c913f2c575d1c43883475ceb96bdf GIT binary patch literal 257 zcmX^0Z`VEs1_l!bZgvJvb_Om+26oqq)a25VR7M7MjcCtkpRB~PME#t^ymWp4q^#8B z66^(-3?hz2MTwOGiA9OIsU@jJ5J^S`0d$A5 gF)%PPFabRWq*)jlm>F1rd{!WjiGdBsVh6K00L$J+;Q#;t literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/DummyGeneric.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/DummyGeneric.class new file mode 100644 index 0000000000000000000000000000000000000000..afbff9f82d17273772666e3ff3a8b8ecad8262cb GIT binary patch literal 441 zcmZXQy-ve06orrTOG9W&3T0&s40K_FC=vp}62XwDyOWsWDnBSqkos6mNDMpx4~4i1 zMIv;t?>(Q7ua5os_5K0i97h&Z9GEyXF=fynrN~kSCs^_qKFfHqm_5Wxk<^zAgHSFC zUN@CsP@{;5;mJbQK1ugv&Y)eFDV>c1S%~{4k3|*nI3wZ&Wx}&LuVkw?P^+KhieVVs zGfUcff&aBzXHcl=+gj3OM_0;piY6=5t>2OB63Bw_2{Q>V6W7u*rna*pbMLN W`^SJi3`vc8WK2rgjNXUSsmV7GwqRfY literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/LambdaInterfaces.java b/unit/java_bytecode/java_bytecode_parser/lambda_examples/LambdaInterfaces.java new file mode 100644 index 00000000000..388d8230df6 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parser/lambda_examples/LambdaInterfaces.java @@ -0,0 +1,39 @@ +interface SimpleLambda { + public void Execute(); +} + +interface ParameterLambda { + public void Execute(int primitive, Object reference, DummyGeneric specalisedGeneric); +} + +interface ArrayParameterLambda { + public void Execute(int[] primitive, Object[] reference, DummyGeneric[] specalisedGeneric); +} + +interface ReturningLambdaPrimitive { + public int Execute(); +} + +interface ReturningLambdaReference { + public Object Execute(); +} + +interface ReturningLambdaSpecalisedGeneric { + public DummyGeneric Execute(); +} + +interface ReturningLambdaPrimitiveArray { + public int[] Execute(); +} + +interface ReturningLambdaReferenceArray { + public Object[] Execute(); +} + +interface ReturningLambdaSpecalisedGenericArray { + public DummyGeneric[] Execute(); +} + +class DummyGeneric { + T field; +} diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/ParameterLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/ParameterLambda.class new file mode 100644 index 0000000000000000000000000000000000000000..9d52eef3aa72bdb9061f76c21c3831047587bba9 GIT binary patch literal 246 zcmX^0Z`VEs1_l!bZgvJvb_Om+26oqq)a25VR7M6B4Nsq}#Ii*FoW#6zegCAa)Z`Lt zAD7bH+)DSx1DnGYoL^d$ zoa&aD12jk|xFoS8GubCGHz_5tSP$e3Mh58YI0&uW^rl?)N03~qQpu@1_6Wx{z+M> j$t7$I42%p+Kpy~U7DfhU1{NTn706>^U<0z)!7L5{4Q@U2 literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/SimpleLambda.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/SimpleLambda.class new file mode 100644 index 0000000000000000000000000000000000000000..ff1dae8ba4be47077bef82c1f7362bd259030c0e GIT binary patch literal 130 zcmX^0Z`VEs1_l!bPId-%b_Nbc26oqq)a25VR7M774b3n{2Cm@z(xT*4x6B-%kWg?* zVo7GQPhxITN@B5IR$^HqBLh!xW^O@FDnyWxK>#GGpOcuEuJ50em6}|_#=yYHzy!1f TNV5QqWnclZ7+8TM69XFnp>Z7o literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.class new file mode 100644 index 0000000000000000000000000000000000000000..a5d959f57812675dfa7d5f851dfec18ef5028547 GIT binary patch literal 4245 zcmbVP340sW6+NRk9$T7NvYed|lHk;K(!@!~ibH@H0;Wm`wi{^E0AqRLOd?BSG!B@3 z-`6hC7ASky6o@H{R0un?DP?V0TK45{@Nw=NX>83n@%LeWZ|-^ToqOMXZ|=SGbnx5K z0RSuUO%yHIU5_7NPYf9h3d+WiLtfB%F*qm)a$^|6UP0%_Z~=w|T^PefxLD97FNHC;Qs)v*U{*WPPs(7OE5ZfmFISlKj3 zld0Y2Ub8)8W(V3&@7ryq-3|>iJmsFel{PbW!RkN7%36+{*3ghTX=re8xZEeTzQ-QO zn(mN8TSr$-t{-E$E9+VVmea9;8b-k$%xA2WIoQ{4ip8EWea^@7reh9PrW;dRrE9sC z;|-CKFdfGnR^t`g^wf#|SQU4gW6`;+e-0Ie*{NP-&jG z5)FpVt)jmmxM+w;JF^2GtBqAG92Kb_@(SFff~ec_>ZQDvzm=tyWQ6^G^o z_Tz1()69E8Q=ax62~4*f+MfWkcD6Zs<++B7-*gYz3Jktf9N7S_n?q#XMKkQrWRRcPszp^;-k zBP%qtv~KSjXXSv)@>=TiqZKJ4F4Q}t#i(f<8{B&#T!-QT(;=t$YMNWS!iQ0Ph~iP; z82Ps9)~7S&Sc>-KhMcsu$ySk56&y?DpbeaiO$L@>xsFE-JSLqLI7Y|g(yzH{jdJFMdJd?mCilP`OC14T% zUGTFB>>z$l@PP!niJuqzLIPWfUljaO0$Ye*7W_&AXA!?D__YMK5x*|@9|`ml|5NZm zf`75S!S-(rQ>xC6?ghh?ABM3X0uB1f7g*^bS8_P;31B{{;u0F3*?owbt|2((*Bch@ zfL5rIX*e=Ksjj-=dEdJ7lT|gKA6i23qIeT;MR@~w+p8;M&!a=e-_g*-N)p(&ntGR8 zD|4Lqk?1c8CxbJJ2ALjaNDqj`xgK>%e!lT3w zHME5-hE^X{_(+cJfAaXhj*ks|f-em0lq~I+?EINz<#x%&pGp?~M6&Np$+{m)w)IGs zoguTQ%j{-s(Xe1NZtd*e+#ajl`&KZ?%$;W1%{jxo!tlOQ>FM}NLv1RT+cT7BjCW;u zlj_Wvg@VQJ%^R&_Dpc8?m#(Lp+5U`GX!aC4#?X3Phj)yzBUOsM!+GobO?pcnUU%$g zth{WenaT9nuEhfOH6uNAKI832!`#F3FrTlih4D#>!IBrC0wEV4?nzADMmswAtbk}Rl7vZgA@vPv1}S}gK>p2A)`rA9e< z(bLfO6GU(-pS5aGLl?2(5pWuQ#9lp8zVb7?#LHiP1d$>pX&6C`u4zR~t|6?|1nL6o zim2Cc<_Mxi#1t@!n4&;K5pe|)MKmgqETTz)sTHkh6|L!>miVbDKUZT4@eCf?Of+E@ z=3+LF`3N529B%qZepBYs>!Z-i7q9~hm?}r}S5I>yD$!3Has+eK{(zbh%y`_l?43Xp znM{^2b7qj4B$K%nX3p9du-Ql^Q?bmPU0yw+1ue$OW8O~4YaowFJ|S-kd8`N%@(l7= zJ|^VF$YZSu@@j(njgrU0ROU&DPLdM|23x%fwt3zp&c-<;$!k6rCZB@(kVb^YSn4J+ zRu?cP3FjGG>>FF6jInr@jm=V=vS(g+c|o8vyas&QBgz0^mKbYz0+ABqjk2c1NTRGQ zG43eqN{l_qXo>MhX_PQeWJ8IuNSP=x9x0P0#w6v`5}HL$D`BC?>7!A;f;kBOLayU~ zf*ClIKac0}*KsSymoWp@qJdYbI5VP=?=8t#XyP&MqD}-hKBtV*=}++`K4XsD%>ISc zyoH=waT}YUJMeQhLBGVW*aY2$U$Y7NE$(I$bT59#Cg^@Vz$WM+Jj^EO_xJ;wpu6xV MU-!?x?q6{4cZk;x7ytkO literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.java b/unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.java new file mode 100644 index 00000000000..697b2209f47 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parser/lambda_examples/StaticLambdas.java @@ -0,0 +1,37 @@ +public class StaticLambdas { + + static int staticPrimitive; + static Object staticReference; + static DummyGeneric staticSpecalisedGeneric; + + static SimpleLambda simpleLambda = () -> { /*NOP*/ }; + static ParameterLambda paramLambda = (int primitive, Object reference, DummyGeneric specalisedGeneric) -> {}; + static ArrayParameterLambda arrayParamLambda = (int[] primitive, Object[] reference, DummyGeneric[] specalisedGeneric) -> {}; + static ReturningLambdaPrimitive returnPrimitiveLambda = () -> { return 1; }; + static ReturningLambdaReference returnReferenceLambda = () -> { return null; }; + static ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambda = () -> { return null; }; + static ReturningLambdaPrimitiveArray returnPrimitiveArrayLambda = () -> { return null; }; + static ReturningLambdaReferenceArray returnReferenceArrayLambda = () -> { return null; }; + static ReturningLambdaSpecalisedGenericArray returningSpecalisedGenericArrayLambda = () -> { return null; }; + + static ReturningLambdaPrimitive returnPrimitiveLambdaCapture = () -> { return staticPrimitive; }; + static ReturningLambdaReference returnReferenceLambdaCapture = () -> { return staticReference; }; + static ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambdaCapture = () -> { return staticSpecalisedGeneric; }; + + + public static void testMethod() { + simpleLambda.Execute(); + paramLambda.Execute(4, null, null); + arrayParamLambda.Execute(null, null, null); + returnPrimitiveLambda.Execute(); + returnReferenceLambda.Execute(); + returningSpecalisedGenericLambda.Execute(); + returnPrimitiveArrayLambda.Execute(); + returnReferenceArrayLambda.Execute(); + returningSpecalisedGenericArrayLambda.Execute(); + + returnPrimitiveLambdaCapture.Execute(); + returnReferenceLambdaCapture.Execute(); + returningSpecalisedGenericLambdaCapture.Execute(); + } +} From c327c8642c1d48958e9280103edf173259c8f1fc Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 23 Feb 2018 18:03:37 +0000 Subject: [PATCH 3/7] Adding tests for local lambdas --- ...ava_bytecode_parse_lambda_method_table.cpp | 249 ++++++++++++++++++ .../lambda_examples/LocalLambdas.class | Bin 0 -> 4350 bytes .../lambda_examples/LocalLambdas.java | 59 +++++ 3 files changed, 308 insertions(+) create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.java diff --git a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp index 91fc9c18df2..a8e2fa6adab 100644 --- a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp +++ b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp @@ -276,3 +276,252 @@ SCENARIO( } } } +SCENARIO( + "lambda_method_handle_map with local lambdas", + "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") +{ + null_message_handlert message_handler; + GIVEN("A method with local lambdas") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + "LocalLambdas.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); + + // Simple lambdas + THEN( + "There should be an entry for the lambda that has no parameters or " + "returns and the method it references should have an appropriate " + "descriptor") + { + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, "()V"); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()V"); + } + + // Parameter lambdas + THEN( + "There should be an entry for the lambda that takes parameters and the " + "method it references should have an appropriate descriptor") + { + std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that takes array parameters " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Return lambdas + THEN( + "There should be an entry for the lambda that returns a primitive and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Array returning lambdas + THEN( + "There should be an entry for the lambda that returns an array of " + "primitives and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()[I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "reference types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "specialised generic types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Capturing lamdbas + THEN( + "There should be an entry for the lambda that returns a primitive " + "local variable and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + // Note here the descriptor of the implementation is different - the + // implementation requries the input to be passed in + REQUIRE(id2string(lambda_method.descriptor) == "(I)I"); + + std::vector + expected_instructions{{"iload_0", {}}, {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "local variable and the method it references should have an " + "appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE( + id2string(lambda_method.descriptor) == + "(Ljava/lang/Object;)Ljava/lang/Object;"); + + std::vector + expected_instructions{{"aload_0", {}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type local variable and the method it references should have " + "an appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE( + id2string(lambda_method.descriptor) == + "(LDummyGeneric;)LDummyGeneric;"); + + // since just returning the parameter, nothing to put on the stack + std::vector + expected_instructions{{"aload_0", {}}, {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.class new file mode 100644 index 0000000000000000000000000000000000000000..28f9f1d7990979df4b7781ce71c69559b98854de GIT binary patch literal 4350 zcmbVP`F9)D75+w+J+?Hq6`6!sY)Npi9FjN-gdm5c;Dn$?&Snz`Vd+?&B$LRJ7>z>= zEn8b!Xjxh)`@Sz>UnL+cWocRe7=GvUyED>QGvmbP)IOSf=iTqFbKjje-~C!U4&Xfe z9K%9flO#W$gaRXp2o5IEg2PEfQB0y0*C){iI|&sxB+-r=ljy+jlZfHwB;vR=j@xj1 z9Dl^0;`lS}h~qE#YaDmtt~maNzsGSm?up}G+!x0`@J|)@t9U>`+Xk~}+8Y(LqzCpW zhz^$~31us)UWxakg<4pf!TwJ)6w=i@K4#N#UiA8u^4G-c(DOHG-t^O{HKN~w;9 zUZhyhOG+iXVq1E7#IO&RCMw-+_*Vick_RxheEe-gg2+pq=W4d!$+vb za4KpF)GbGi{FKe2Nw4{4y&yhT(8KlMkQdP>3Kml2%#qpTpK^FmzWYRTTx=Yl72^$? zA;EkmJrS}Knr9C7a|MgT*uW4LqhHJl^c=gxQGj167zkSod7n}Ew}LY`FHWBKR|;0n zI*kI=@&a_r=BmqVL!9cFCINp@=7-#+`~Ec@oT( zN{6S)tbMk~lh$xSuT%`4?tW-~>UDeWD7s89P85tvpQ||3Gy_L%i>H?66`$f5U#0(_ z&~-a7g zFKM?pXxjLGCE1L#+3n|G3MDKEQ=Ij*L^{hiN;4PicP%V~OHp+U#T5 z+fc<)+K$lwyXdFy7RGXno|X}n!V5ST%NgflT3$iFZA3go->X>XLEK00YnZ`0eps!g z_YTH;J0n=fj5gyY#<89y&!NIdR?@>54l|xrEc?~SV~Dz4*uZ$C0o+I~LL?EBjms73 zp5>&{J&|Q^$+f9e*ujj9?}@sx zUI#;&Y`x|L+8NV6u0_~_-;u^B{SSV?f4SkV<^7Fp#_Ndr9d!PL%VUB+;r8PIf5MqK r#Gh~lO!6mO31$9-v)J&K!%cCMPC49BOyj7-ncNr+-9LD`x1jVttGFb^ literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.java b/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.java new file mode 100644 index 00000000000..181662018ee --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parser/lambda_examples/LocalLambdas.java @@ -0,0 +1,59 @@ +public class LocalLambdas { + public static void test() { + int localPrimitive = 5; + Object localReference = null; + DummyGeneric localSpecalisedGeneric = null; + + // Declare some local lambdas + SimpleLambda simpleLambda = () -> { /*NOP*/ }; + + ParameterLambda paramLambda = + (int primitive, Object reference, DummyGeneric specalisedGeneric) -> {}; + ArrayParameterLambda arrayParamLambda = + (int[] primitive, Object[] reference, DummyGeneric[] specalisedGeneric) -> {}; + + ReturningLambdaPrimitive returnPrimitiveLambda = () -> { + return 1; + }; + ReturningLambdaReference returnReferenceLambda = () -> { + return null; + }; + ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambda = () -> { + return null; + }; + + ReturningLambdaPrimitiveArray returnPrimitiveArrayLambda = () -> { + return null; + }; + ReturningLambdaReferenceArray returnReferenceArrayLambda = () -> { + return null; + }; + ReturningLambdaSpecalisedGenericArray returningSpecalisedGenericArrayLambda = () -> { + return null; + }; + + ReturningLambdaPrimitive returnPrimitiveLambdaCapture = () -> { + return localPrimitive; + }; + ReturningLambdaReference returnReferenceLambdaCapture = () -> { + return localReference; + }; + ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambdaCapture = () -> { + return localSpecalisedGeneric; + }; + + simpleLambda.Execute(); + paramLambda.Execute(4, null, null); + arrayParamLambda.Execute(null, null, null); + returnPrimitiveLambda.Execute(); + returnReferenceLambda.Execute(); + returningSpecalisedGenericLambda.Execute(); + returnPrimitiveArrayLambda.Execute(); + returnReferenceArrayLambda.Execute(); + returningSpecalisedGenericArrayLambda.Execute(); + + returnPrimitiveLambdaCapture.Execute(); + returnReferenceLambdaCapture.Execute(); + returningSpecalisedGenericLambdaCapture.Execute(); + } +} From bcaa1fc1f10f12b873b02c2cdb73620ba9d921b0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 23 Feb 2018 18:05:20 +0000 Subject: [PATCH 4/7] Adding tests for lambdas as member variables --- ...ava_bytecode_parse_lambda_method_table.cpp | 272 ++++++++++++++++++ .../lambda_examples/MemberLambdas.class | Bin 0 -> 4426 bytes .../lambda_examples/MemberLambdas.java | 38 +++ 3 files changed, 310 insertions(+) create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/MemberLambdas.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/MemberLambdas.java diff --git a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp index a8e2fa6adab..ef68d918bd3 100644 --- a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp +++ b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp @@ -525,3 +525,275 @@ SCENARIO( } } } +SCENARIO( + "lambda_method_handle_map with member lambdas", + "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") +{ + null_message_handlert message_handler; + GIVEN("A class that has lambdas as member variables") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + "MemberLambdas.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 12); + + // Simple lambdas + THEN( + "There should be an entry for the lambda that has no parameters or " + "returns and the method it references should have an appropriate " + "descriptor") + { + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, "()V"); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()V"); + } + + // Parameter lambdas + THEN( + "There should be an entry for the lambda that takes parameters and the " + "method it references should have an appropriate descriptor") + { + std::string descriptor = "(ILjava/lang/Object;LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that takes array parameters " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "([I[Ljava/lang/Object;[LDummyGeneric;)V"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Return lambdas + THEN( + "There should be an entry for the lambda that returns a primitive and " + "the method it references should have an appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "and the method it references should have an appropriate descriptor") + { + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Array returning lambdas + THEN( + "There should be an entry for the lambda that returns an array of " + "primitives and the method it references should have an appropriate " + "descriptor") + { + std::string descriptor = "()[I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "reference types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + THEN( + "There should be an entry for the lambda that returns an array of " + "specialised generic types and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()[LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == descriptor); + } + + // Capturing lamdbas + THEN( + "There should be an entry for the lambda that returns a primitive " + "local variable and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + // Note here the descriptor of the implementation is different - the + // implementation requries the input to be passed in + REQUIRE(id2string(lambda_method.descriptor) == "()I"); + REQUIRE_FALSE(lambda_method.is_static); + + const fieldref_exprt primitive_fieldref{ + java_int_type(), "memberPrimitive", "java::MemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {primitive_fieldref}}, + {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "local variable and the method it references should have an " + "appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()Ljava/lang/Object;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::java.lang.Object"}); + + const fieldref_exprt reference_fieldref{dummy_generic_reference_type, + "memberReference", + "java::MemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type local variable and the method it references should have " + "an appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor, 1); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()LDummyGeneric;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::DummyGeneric"}); + + const fieldref_exprt generic_reference_fieldref{ + dummy_generic_reference_type, + "memberSpecalisedGeneric", + "java::MemberLambdas"}; + + // since just returning the parameter, nothing to put on the stack + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {generic_reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/MemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/MemberLambdas.class new file mode 100644 index 0000000000000000000000000000000000000000..04984e527203b6e1d6e172f4fe6b4261397dc893 GIT binary patch literal 4426 zcmbVPiGLhr8Ga_$G`nBAn+?4}@1|sv0-+RIN@^7XfxtGzq=ZVTI!UJKw0k)_DGgLD z2#A1!Cx-&wCn_ivwjkaYBHno4H-7{_pZA;1WOruM_%pv>=6$~Rd(ZE9X7>44PCW55@5?9*N^od^nDe;G=PT z3?Gl<6Zm8tpTei(_zXTP9-ouPWAgaCi7%M=qJc!t&P~|vi0kAW&pB!vFopu{sD03O z?ffLQsmx*PsMVLX^3#3SOdPf+y?z5LeCM&EJ!xf~l09{Wowr?Q(!kQpWiz?lY-LQ- z)-h)~Z+SB=V{NLL+*K8MDDToDignHkj+PJY@~1r|(DaSE1cL8rii zPV4aCrIsc8}q!CNT=?qn@8=H%;E*v2!Tbs?h2bG=Pz1EEGn-}h)CQ^5}kVq?Y z1+5PCtA-3A)dJ>v$N1`1O=lZlLzw})rsF6^}? zviigqc&f)O*O75W+2kE^N@Bf7UmHJkiR%&b?2@;~_6`-M476qSq3z1sH+F5^%7d8h zsX6kruQ55#z!@~DbHh|sq@B8C-p*>}MF!f_J^RDqt4((Bpo+;N;kR=wXcmfpVQsn# zYKPluhvysUPVXP8lPXl8EPQKmo^u)`ZL2#^Hyw3iu+vhMX%eB(wH0ykyV66^)@#>G z%Bfy4?ni8_Fyl_zgN{B5HM@PTETqEa805}gS}1rW&$WvF-j@2@~Iz(RUOs#SV_X zE2Hlz3}7cm-igH#o{Fc z9n^=3U#5O#U?rzCx73^ewSm=~A6++5`mDFE+oG^A(8`;W%ykI|Cb{wjpAc zpuewc7$o)yQw;xLpeGtJl6~Icj|R4+L);aqKB!1n{ipxMC8$li{Mo>^MYBYzBq^%u zEhfu`c8)ArZ$r7&3+-ccDyWn%;*eLQA_HqeCc)C^I->JI^ve9^kbfkFwlnb;g}>sT z3I{Q$Fa=xT1{_e>k5Pr|F{1D~3@coReG1oNTwzRZ)@x<<8kyaLVFMfIZ<3QgS~z0& z`EMr@lXcLV^a}1QKbrW3G&eHwZv!ovLgC0vk!wGc=eOHH)+&{3zTsX-SCM8Vo=V{xJeOZJ)tVZ|y|YF8|C{tvp5C|m^;tM# zl^`Y{PM`#|5iAvuAV>;mC*ZG}lj!IrIz!MhLCXcL5VTUzswbGY0ax<59c_H_Q-Z%{ z+L&lLf5EI{o-}{8Y-O5@sU2XJ4A<{kwBrqo@1O%i^iqEPxC&S67@45Aml#iaJKp;w z8q4T3K+tR&Mj2-|2___7t#NA^YYbdRZM=-NK58ptosSY_toKoS85?}mQN~6eEem{C z1iq_$-*AsB*x5=f!z!MLPVWDi+}qXMw>9i#EpO;L9N^3}HsVd#gqzV-)#Gu$$7F+C zU3Mn>*GDNmHnZ?ej}!O{+M<=!3)CDq^YYhm?g~4nsxr?zlRoM=Z+ memberSpecalisedGeneric; + + SimpleLambda simpleLambda = () -> { /*NOP*/ }; + ParameterLambda paramLambda = (int primitive, Object reference, DummyGeneric specalisedGeneric) -> {}; + ArrayParameterLambda arrayParamLambda = (int[] primitive, Object[] reference, DummyGeneric[] specalisedGeneric) -> {}; + ReturningLambdaPrimitive returnPrimitiveLambda = () -> { return 1; }; + ReturningLambdaReference returnReferenceLambda = () -> { return null; }; + ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambda = () -> { return null; }; + ReturningLambdaPrimitiveArray returnPrimitiveArrayLambda = () -> { return null; }; + ReturningLambdaReferenceArray returnReferenceArrayLambda = () -> { return null; }; + ReturningLambdaSpecalisedGenericArray returningSpecalisedGenericArrayLambda = () -> { return null; }; + + ReturningLambdaPrimitive returnPrimitiveLambdaCapture = () -> { return memberPrimitive; }; + ReturningLambdaReference returnReferenceLambdaCapture = () -> { return memberReference; }; + ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambdaCapture = () -> { return memberSpecalisedGeneric; }; + + + public void testMethod() { + simpleLambda.Execute(); + paramLambda.Execute(4, null, null); + arrayParamLambda.Execute(null, null, null); + returnPrimitiveLambda.Execute(); + returnReferenceLambda.Execute(); + returningSpecalisedGenericLambda.Execute(); + returnPrimitiveArrayLambda.Execute(); + returnReferenceArrayLambda.Execute(); + returningSpecalisedGenericArrayLambda.Execute(); + + returnPrimitiveLambdaCapture.Execute(); + returnReferenceLambdaCapture.Execute(); + returningSpecalisedGenericLambdaCapture.Execute(); + } +} + From 4094b7d5ab99531edfc4d011249c531db8286f08 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 23 Feb 2018 18:06:56 +0000 Subject: [PATCH 5/7] Adding tests for inner classes that capture outer class variables --- ...ava_bytecode_parse_lambda_method_table.cpp | 136 ++++++++++++++++++ .../OuterMemberLambdas$Inner.class | Bin 0 -> 2097 bytes .../lambda_examples/OuterMemberLambdas.class | Bin 0 -> 534 bytes .../lambda_examples/OuterMemberLambdas.java | 22 +++ 4 files changed, 158 insertions(+) create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas$Inner.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.class create mode 100644 unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.java diff --git a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp index ef68d918bd3..d1484f098a3 100644 --- a/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp +++ b/unit/java_bytecode/java_bytecode_parser/java_bytecode_parse_lambda_method_table.cpp @@ -797,3 +797,139 @@ SCENARIO( } } } +SCENARIO( + "lambda_method_handle_map with member lambdas capturing outer class " + "variables", + "[core][java_bytecode][java_bytecode_parse_lambda_method_handle]") +{ + null_message_handlert message_handler; + GIVEN( + "An inner class with member variables as lambdas that capture outer " + "variables") + { + java_bytecode_parse_treet parse_tree; + java_bytecode_parse( + "./java_bytecode/java_bytecode_parser/lambda_examples/" + "OuterMemberLambdas$Inner.class", + parse_tree, + message_handler); + WHEN("Parsing that class") + { + REQUIRE(parse_tree.loading_successful); + const java_bytecode_parse_treet::classt parsed_class = + parse_tree.parsed_class; + REQUIRE(parsed_class.attribute_bootstrapmethods_read); + REQUIRE(parsed_class.lambda_method_handle_map.size() == 3); + + // Field ref for getting the outer class + const reference_typet outer_class_reference_type = + java_reference_type(symbol_typet{"java::OuterMemberLambdas"}); + const fieldref_exprt outer_fieldref{ + outer_class_reference_type, "this$0", "java::OuterMemberLambdas$Inner"}; + + THEN( + "There should be an entry for the lambda that returns a primitive " + "local variable and the method it references should have an " + "appropriate descriptor") + { + std::string descriptor = "()I"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + // Note here the descriptor of the implementation is different - the + // implementation requries the input to be passed in + REQUIRE(id2string(lambda_method.descriptor) == "()I"); + REQUIRE_FALSE(lambda_method.is_static); + + const fieldref_exprt primitive_fieldref{ + java_int_type(), "memberPrimitive", "java::OuterMemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {outer_fieldref}}, + {"getfield", {primitive_fieldref}}, + {"ireturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a reference type " + "local variable and the method it references should have an " + "appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()Ljava/lang/Object;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const auto lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()Ljava/lang/Object;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::java.lang.Object"}); + + const fieldref_exprt reference_fieldref{dummy_generic_reference_type, + "memberReference", + "java::OuterMemberLambdas"}; + + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {outer_fieldref}}, + {"getfield", {reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + THEN( + "There should be an entry for the lambda that returns a specialised " + "generic type local variable and the method it references should have " + "an appropriate descriptor") + { + // Since it is a local variable, the corresponding method takes the + // captured variable as an input + std::string descriptor = "()LDummyGeneric;"; + const lambda_method_handlet &lambda_entry = + require_parse_tree::require_lambda_entry_for_descriptor( + parsed_class, descriptor); + + const irep_idt &lambda_impl_name = lambda_entry.lambda_method_name; + + const java_bytecode_parse_treet::methodt &lambda_method = + require_parse_tree::require_method(parsed_class, lambda_impl_name); + REQUIRE(id2string(lambda_method.descriptor) == "()LDummyGeneric;"); + REQUIRE_FALSE(lambda_method.is_static); + + const reference_typet dummy_generic_reference_type = + java_reference_type(symbol_typet{"java::DummyGeneric"}); + + const fieldref_exprt generic_reference_fieldref{ + dummy_generic_reference_type, + "memberSpecalisedGeneric", + "java::OuterMemberLambdas"}; + + // since just returning the parameter, nothing to put on the stack + std::vector + expected_instructions{{"aload_0", {}}, // load this of stack + {"getfield", {outer_fieldref}}, + {"getfield", {generic_reference_fieldref}}, + {"areturn", {}}}; + + require_parse_tree::require_instructions_match_expectation( + expected_instructions, lambda_method.instructions); + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas$Inner.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas$Inner.class new file mode 100644 index 0000000000000000000000000000000000000000..19b99a9819035be8bf129ff731207e69df859ded GIT binary patch literal 2097 zcmbVN?Q+vb6g_JkE4EcE93Ua3kOqg?h7w3=OB4YDBfDX^Z^sJ+Z(1>iEavnb$v4hB9dQn9F} z9~U9;sggb`B84xMw3NqHe3{2GzRKfke3QjB)Kqs}bvHEJ)No7Sq$~ZtYu|URuH{?1 zvTk;pZL??l8bj)3ww*Ql=H5z}Sk-m<9A;taVJ!lT=S9kdy)w#**`;=dVhC z$7u^3Dl2Zi6QsRl%U?>10!Fz~zuxb5_o9ptG;DE++oZ))bJtwxnD+Ly)>X^V$19Mc|Q;Ibm$8cQ3eKo0Qc%a644eM&0)6medfrmOa@kqyGd@C?D z8dsPwh7;dt4&UMX9Bcds0qw@Gvc(f;{U@Dll=Moxh7QVD`T6lJ(FcXB&`$)G--bJ> zey9HHnlUr6r2)CXOl)byGmCdLuPlOYa6J;t56A1S5Sk8=7Ly7uG8?2-K&)u^NypD< z=_sS3<1FTNlrSeSdvKtZz3V)a3*kj&wV7LH%Xi#8fqeI1rh(_1sXNZIeox?4c_@O& zL0G7_O}pKZUMaL(8ZvA6ENF}b3Vog;{>MJzt7nYAB_~pa`oH`i0Yq6 zRjV&?2zY_ClE##jQIe*l@jqyr!b$eUfJ;M`{|V&q0rG4hSKtq)7?b*y1721IW^pEB zeaKO8?R51y()-8?Jff7@M=q4c_mQU*Co@QMgqteT`9wgbhi*bLBc+NgqF9V5#_3o* zhyFY1!oV{DCJZ*jj}P#y)MWg7alG0v5XZCJlktati}7bi@l1O)usVksj_N%x@WDP! gk0#n^^4Km=KSR3(wu`vLrliaGgiT3T@Hwvh10;_G_W%F@ literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.class b/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.class new file mode 100644 index 0000000000000000000000000000000000000000..da380075695df966c7d51116df4e833865b11d0a GIT binary patch literal 534 zcmZWm%T5A85UkxIAnJ)v%4gImM0Sret;ik z>>Y_wIZQuls=B9pK0e>x0i0vMh%A~8b{yn`qxiuB=>MR1^gxER&uGn^%DHR>Qcqd~Z%TgL7HE8nhfn0oKt(jZBJQDlfwFs%gyHid zXKG=nCR)ac;aZ1(E<3*}_jODYGVLxaRysKn_Hvvk%HDyZ_{%hv+c z|H}|)F7uA;s&Rk}{{`%Eu*wloK+*a&lpwIqaRz0MctBLyZZOiaIgmeng?O=)8rv0y c!Do|gDrN%e*kYf-wzUoBfE)1A7|TO^0gN$!B>(^b literal 0 HcmV?d00001 diff --git a/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.java b/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.java new file mode 100644 index 00000000000..e1255c0ae20 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parser/lambda_examples/OuterMemberLambdas.java @@ -0,0 +1,22 @@ +public class OuterMemberLambdas { + + int memberPrimitive; + Object memberReference; + DummyGeneric memberSpecalisedGeneric; + + public class Inner { + + ReturningLambdaPrimitive returnPrimitiveLambdaCapture = () -> { return memberPrimitive; }; + ReturningLambdaReference returnReferenceLambdaCapture = () -> { return memberReference; }; + ReturningLambdaSpecalisedGeneric returningSpecalisedGenericLambdaCapture = () -> { return memberSpecalisedGeneric; }; + + + public void testMethod() { + + returnPrimitiveLambdaCapture.Execute(); + returnReferenceLambdaCapture.Execute(); + returningSpecalisedGenericLambdaCapture.Execute(); + } + } +} + From eb67d31a204fb4b991579fc64cbf928d935727f6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 26 Feb 2018 14:48:45 +0000 Subject: [PATCH 6/7] Addressed review comments (squash with utils commit) --- unit/testing-utils/require_parse_tree.cpp | 4 ++-- unit/testing-utils/require_parse_tree.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/unit/testing-utils/require_parse_tree.cpp b/unit/testing-utils/require_parse_tree.cpp index 500e173a55b..70922d4b55a 100644 --- a/unit/testing-utils/require_parse_tree.cpp +++ b/unit/testing-utils/require_parse_tree.cpp @@ -19,14 +19,14 @@ require_parse_tree::lambda_method_handlet require_parse_tree::require_lambda_entry_for_descriptor( const java_bytecode_parse_treet::classt &parsed_class, - std::string descriptor, + const std::string &descriptor, const size_t entry_index) { REQUIRE(entry_index < parsed_class.lambda_method_handle_map.size()); typedef java_bytecode_parse_treet::classt::lambda_method_handle_mapt:: value_type lambda_method_entryt; - int matches_found = 0; + size_t matches_found = 0; const auto matching_lambda_entry = std::find_if( parsed_class.lambda_method_handle_map.begin(), diff --git a/unit/testing-utils/require_parse_tree.h b/unit/testing-utils/require_parse_tree.h index bdf932b75cd..35b3ab195d2 100644 --- a/unit/testing-utils/require_parse_tree.h +++ b/unit/testing-utils/require_parse_tree.h @@ -23,7 +23,7 @@ typedef java_bytecode_parse_treet::classt::lambda_method_handlet lambda_method_handlet require_lambda_entry_for_descriptor( const java_bytecode_parse_treet::classt &parsed_class, - std::string descriptor, + const std::string &descriptor, const size_t entry_index = 0); typedef java_bytecode_parse_treet::methodt methodt; From 406fc00cdaa2ab7d10e53a6a5ff9a98647a1e329 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 26 Feb 2018 14:48:58 +0000 Subject: [PATCH 7/7] Adding exprt required for tests (will go away when rebased) --- src/java_bytecode/java_bytecode_parse_tree.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/java_bytecode/java_bytecode_parse_tree.h b/src/java_bytecode/java_bytecode_parse_tree.h index 7be01209f47..ca98235a51a 100644 --- a/src/java_bytecode/java_bytecode_parse_tree.h +++ b/src/java_bytecode/java_bytecode_parse_tree.h @@ -247,4 +247,18 @@ class java_bytecode_parse_treet } }; +class fieldref_exprt : public exprt +{ +public: + fieldref_exprt( + const typet &type, + const irep_idt &component_name, + const irep_idt &class_name) + : exprt(ID_empty_string, type) + { + set(ID_class, class_name); + set(ID_component_name, component_name); + } +}; + #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_PARSE_TREE_H