diff --git a/jbmc/regression/CMakeLists.txt b/jbmc/regression/CMakeLists.txt index 487dd801c66..65da4bee9a9 100644 --- a/jbmc/regression/CMakeLists.txt +++ b/jbmc/regression/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(janalyzer-taint) add_subdirectory(jbmc-concurrency) add_subdirectory(jbmc-inheritance) add_subdirectory(jbmc-cover) +add_subdirectory(jbmc-generics) diff --git a/jbmc/regression/Makefile b/jbmc/regression/Makefile index 7e607532891..0d85532780a 100644 --- a/jbmc/regression/Makefile +++ b/jbmc/regression/Makefile @@ -9,6 +9,7 @@ DIRS = janalzyer-taint \ jbmc-strings \ jdiff \ string-smoke-tests \ + jbmc-generics \ # Empty last line # Tests under goto-gcc cannot be run on Windows, so appveyor.yml unlinks diff --git a/jbmc/regression/jbmc-generics/CMakeLists.txt b/jbmc/regression/jbmc-generics/CMakeLists.txt new file mode 100644 index 00000000000..fa345944621 --- /dev/null +++ b/jbmc/regression/jbmc-generics/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test_pl_tests( + "$" +) + +add_test_pl_profile( + "jbmc-symex-driven-lazy-loading" + "$ --symex-driven-lazy-loading" + "-C;-X;symex-driven-lazy-loading-expected-failure;-s;symex-driven-loading" + "CORE" +) diff --git a/jbmc/regression/jbmc-generics/Makefile b/jbmc/regression/jbmc-generics/Makefile new file mode 100644 index 00000000000..81024778e07 --- /dev/null +++ b/jbmc/regression/jbmc-generics/Makefile @@ -0,0 +1,36 @@ +default: tests.log + +include ../../src/config.inc + +test: + @../$(CPROVER_DIR)/regression/test.pl -p -c ../../../src/jbmc/jbmc + @../$(CPROVER_DIR)/regression/test.pl -p -c "../../../src/jbmc/jbmc --symex-driven-lazy-loading" -X symex-driven-lazy-loading-expected-failure -s symex-driven-loading + +tests.log: ../$(CPROVER_DIR)/regression/test.pl + @../$(CPROVER_DIR)/regression/test.pl -p -c ../../../src/jbmc/jbmc + @../$(CPROVER_DIR)/regression/test.pl -p -c "../../../src/jbmc/jbmc --symex-driven-lazy-loading" -X symex-driven-lazy-loading-expected-failure -s symex-driven-loading + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.java" "$$dir/*.out"; \ + fi; \ + done; + +clean: + find -name '*.out' -execdir $(RM) '{}' \; + find -name '*.gb' -execdir $(RM) '{}' \; + $(RM) tests.log + +%.class: %.java ../../src/org.cprover.jar + javac -g -cp ../../src/org.cprover.jar:. $< + +nondet_java_files := $(shell find . -name "Nondet*.java") +nondet_class_files := $(patsubst %.java, %.class, $(nondet_java_files)) + +.PHONY: nondet-class-files +nondet-class-files: $(nondet_class_files) + +.PHONY: clean-nondet-class-files +clean-nondet-class-files: + -rm $(nondet_class_files) diff --git a/jbmc/regression/jbmc-generics/type_erasure/BWrapper.class b/jbmc/regression/jbmc-generics/type_erasure/BWrapper.class new file mode 100644 index 00000000000..2fbcfaf51ec Binary files /dev/null and b/jbmc/regression/jbmc-generics/type_erasure/BWrapper.class differ diff --git a/jbmc/regression/jbmc-generics/type_erasure/Gen.class b/jbmc/regression/jbmc-generics/type_erasure/Gen.class new file mode 100644 index 00000000000..e1b49e488fd Binary files /dev/null and b/jbmc/regression/jbmc-generics/type_erasure/Gen.class differ diff --git a/jbmc/regression/jbmc-generics/type_erasure/IWrapper.class b/jbmc/regression/jbmc-generics/type_erasure/IWrapper.class new file mode 100644 index 00000000000..49cd865379d Binary files /dev/null and b/jbmc/regression/jbmc-generics/type_erasure/IWrapper.class differ diff --git a/jbmc/regression/jbmc-generics/type_erasure/TestClass.class b/jbmc/regression/jbmc-generics/type_erasure/TestClass.class new file mode 100644 index 00000000000..3d24d025188 Binary files /dev/null and b/jbmc/regression/jbmc-generics/type_erasure/TestClass.class differ diff --git a/jbmc/regression/jbmc-generics/type_erasure/TestClass.java b/jbmc/regression/jbmc-generics/type_erasure/TestClass.java new file mode 100644 index 00000000000..a698eb6aec5 --- /dev/null +++ b/jbmc/regression/jbmc-generics/type_erasure/TestClass.java @@ -0,0 +1,34 @@ +class Gen { + public T t; +} + +class IWrapper { + public int i; +} + +class BWrapper { + public boolean b; +} + +class TestClass { + static void testFunction() { + Gen a = new Gen<>(); + Gen b = a; + assert(b == a); + Gen c; + c = b; + assert(c == b); + assert(c.equals(a)); + } + + static void testFunctionWithInput(Gen a, Gen b, Gen c) { + if(a != null && b != null && c != null && + a.t != null && b.t != null && c.t != null) + { + b = a; + assert(b == a); + a = c; + assert(a == c); + } + } +} diff --git a/jbmc/regression/jbmc-generics/type_erasure/test.desc b/jbmc/regression/jbmc-generics/type_erasure/test.desc new file mode 100644 index 00000000000..97346d61f0c --- /dev/null +++ b/jbmc/regression/jbmc-generics/type_erasure/test.desc @@ -0,0 +1,6 @@ +CORE +TestClass.class +--function TestClass.testFunction --classpath ../../../src/java_bytecode/library/core-models.jar:. +EXIT=0 +SIGNAL=0 +VERIFICATION SUCCESSFUL diff --git a/jbmc/regression/jbmc-generics/type_erasure/test_function_input.desc b/jbmc/regression/jbmc-generics/type_erasure/test_function_input.desc new file mode 100644 index 00000000000..61b04394178 --- /dev/null +++ b/jbmc/regression/jbmc-generics/type_erasure/test_function_input.desc @@ -0,0 +1,10 @@ +CORE +TestClass.class +--function TestClass.testFunctionWithInput +EXIT=0 +SIGNAL=0 +VERIFICATION SUCCESSFUL +-- +-- +Adding the core models causes a exception in convert_struct relating to the +`monitorCount` component. See diffblue/cbmc#2307 diff --git a/jbmc/unit/java_bytecode/goto_program_generics/BWrapper.class b/jbmc/unit/java_bytecode/goto_program_generics/BWrapper.class new file mode 100644 index 00000000000..879bbc45300 Binary files /dev/null and b/jbmc/unit/java_bytecode/goto_program_generics/BWrapper.class differ diff --git a/jbmc/unit/java_bytecode/goto_program_generics/GenericFields$MultipleGenericFields.class b/jbmc/unit/java_bytecode/goto_program_generics/GenericFields$MultipleGenericFields.class index c7fbb48fb8d..f66f5b82b6b 100644 Binary files a/jbmc/unit/java_bytecode/goto_program_generics/GenericFields$MultipleGenericFields.class and b/jbmc/unit/java_bytecode/goto_program_generics/GenericFields$MultipleGenericFields.class differ diff --git a/jbmc/unit/java_bytecode/goto_program_generics/GenericFields.java b/jbmc/unit/java_bytecode/goto_program_generics/GenericFields.java index b83152c95b4..92f1f848513 100644 --- a/jbmc/unit/java_bytecode/goto_program_generics/GenericFields.java +++ b/jbmc/unit/java_bytecode/goto_program_generics/GenericFields.java @@ -11,10 +11,10 @@ public void foo() { class MultipleGenericFields { Wrapper field_input1; - Wrapper field_input2; + Wrapper field_input2; public void foo() { field_input1.field.i = 10; - field_input2.field.i = 20; + field_input2.field.b = true; } } diff --git a/jbmc/unit/java_bytecode/goto_program_generics/GenericHelper.java b/jbmc/unit/java_bytecode/goto_program_generics/GenericHelper.java index fb7c9e73e0d..332c68a6cb6 100644 --- a/jbmc/unit/java_bytecode/goto_program_generics/GenericHelper.java +++ b/jbmc/unit/java_bytecode/goto_program_generics/GenericHelper.java @@ -6,6 +6,14 @@ public IWrapper(int ii) { } } +// boolean wrapper +class BWrapper { + public boolean b; + public BWrapper(boolean bb) { + b = bb; + } +} + // simple generic class class Wrapper { public T field; diff --git a/jbmc/unit/java_bytecode/goto_program_generics/generic_parameters_test.cpp b/jbmc/unit/java_bytecode/goto_program_generics/generic_parameters_test.cpp index 14b61f44c01..9d7b1633b35 100644 --- a/jbmc/unit/java_bytecode/goto_program_generics/generic_parameters_test.cpp +++ b/jbmc/unit/java_bytecode/goto_program_generics/generic_parameters_test.cpp @@ -102,6 +102,21 @@ SCENARIO( require_goto_statements::require_entry_point_argument_assignment( "this", entry_point_code); + THEN("Type of multiple generic fields should be right") + { + const typet &class_type = + symbol_table.lookup_ref("java::GenericFields$MultipleGenericFields") + .type; + + const auto &component = require_type::require_component( + to_java_class_type(class_type), "field_input2"); + + const java_generic_typet &type = + require_type::require_java_generic_type(component.type()); + require_type::require_pointer( + type.generic_type_arguments()[0], symbol_typet{"java::BWrapper"}); + } + THEN("Object 'this' has field 'field_input1' of type Wrapper") { const auto &field_input1_name = @@ -136,13 +151,13 @@ SCENARIO( {}, entry_point_code); - THEN("Object 'field_input1' has field 'field' of type IWrapper") + THEN("Object 'field_input2' has field 'field' of type BWrapper") { require_goto_statements::require_struct_component_assignment( field_input2_name, {}, "field", - "java::IWrapper", + "java::BWrapper", {}, entry_point_code); } diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 2706e179ee7..c7b233c17ab 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -655,7 +655,7 @@ IREP_ID_TWO(C_java_implicitly_generic_class_type, #java_implicitly_generic_class IREP_ID_TWO(C_java_generic_symbol, #java_generic_symbol) IREP_ID_TWO(generic_types, #generic_types) IREP_ID_TWO(implicit_generic_types, #implicit_generic_types) -IREP_ID_TWO(type_variables, #type_variables) +IREP_ID_ONE(type_variables) IREP_ID_TWO(java_lambda_method_handle_index, lambda_method_handle_index) IREP_ID_TWO(java_lambda_method_handles, lambda_method_handles) IREP_ID_ONE(havoc_object)