diff --git a/unit/java_bytecode/java_bytecode_parse_generics/AbstractGeneric.class b/unit/java_bytecode/java_bytecode_parse_generics/AbstractGeneric.class new file mode 100644 index 00000000000..df3a55764e0 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/AbstractGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/AbstractGeneric.java b/unit/java_bytecode/java_bytecode_parse_generics/AbstractGeneric.java new file mode 100644 index 00000000000..4196629ce73 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/AbstractGeneric.java @@ -0,0 +1,4 @@ +public abstract class AbstractGeneric +{ + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/AbstractGenericClass.class b/unit/java_bytecode/java_bytecode_parse_generics/AbstractGenericClass.class deleted file mode 100644 index cbfa2cb7b18..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/AbstractGenericClass.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/AbstractGenericClass.java b/unit/java_bytecode/java_bytecode_parse_generics/AbstractGenericClass.java deleted file mode 100644 index 3d0674893a4..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/AbstractGenericClass.java +++ /dev/null @@ -1,4 +0,0 @@ -public abstract class AbstractGenericClass -{ - -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Bar.class b/unit/java_bytecode/java_bytecode_parse_generics/Bar.class deleted file mode 100644 index 3b52a177cca..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/Bar.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Bar.java b/unit/java_bytecode/java_bytecode_parse_generics/Bar.java deleted file mode 100644 index 273a20744dc..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/Bar.java +++ /dev/null @@ -1,4 +0,0 @@ -class Bar extends Foo -{ - -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterface.java b/unit/java_bytecode/java_bytecode_parse_generics/BasicInterface.java deleted file mode 100644 index 47f91d66f86..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterface.java +++ /dev/null @@ -1,4 +0,0 @@ -interface BasicInterface -{ - int getX(); -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterfaceCopy.class b/unit/java_bytecode/java_bytecode_parse_generics/BasicInterfaceCopy.class deleted file mode 100644 index c61caf0740a..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterfaceCopy.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterfaceCopy.java b/unit/java_bytecode/java_bytecode_parse_generics/BasicInterfaceCopy.java deleted file mode 100644 index 3a87c8d8c88..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterfaceCopy.java +++ /dev/null @@ -1,4 +0,0 @@ -interface BasicInterfaceCopy -{ - int getX(); -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$BoundedInner.class b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$BoundedInner.class new file mode 100644 index 00000000000..99180b2bfd4 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$BoundedInner.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$DoubleBoundedInner.class b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$DoubleBoundedInner.class new file mode 100644 index 00000000000..9e145a08faa Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$DoubleBoundedInner.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$Inner.class b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$Inner.class new file mode 100644 index 00000000000..71d3e8ef04b Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$Inner.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$TwoElementInner.class b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$TwoElementInner.class new file mode 100644 index 00000000000..2f4e90df2ec Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses$TwoElementInner.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses.class b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses.class new file mode 100644 index 00000000000..e02689d3f63 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses.java b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses.java new file mode 100644 index 00000000000..c6f53609c4d --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/BoundedGenericInnerClasses.java @@ -0,0 +1,25 @@ +public class BoundedGenericInnerClasses +{ + class Inner + { + E elem; + } + + class BoundedInner + { + NUM elem; + } + + BoundedInner belem; + + class DoubleBoundedInner + { + T elem; + } + + class TwoElementInner + { + K k; + V v; + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGeneric.class b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGeneric.class deleted file mode 100644 index 65bdd950e85..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGeneric.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGeneric.java b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGeneric.java deleted file mode 100644 index 5eb08c7a2a9..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGeneric.java +++ /dev/null @@ -1,4 +0,0 @@ -class DerivedGeneric extends SimpleGeneric -{ - -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericInst.class b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericInst.class new file mode 100644 index 00000000000..f5a72b7d0a5 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericInst.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericInst.java b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericInst.java new file mode 100644 index 00000000000..b2a41911694 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericInst.java @@ -0,0 +1,4 @@ +class DerivedGenericInst extends Generic +{ + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericUninst.class b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericUninst.class new file mode 100644 index 00000000000..437daa77f9c Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericUninst.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericUninst.java b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericUninst.java new file mode 100644 index 00000000000..88dcb1c9250 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/DerivedGenericUninst.java @@ -0,0 +1,4 @@ +class DerivedGenericUninst extends Generic +{ + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Foo.class b/unit/java_bytecode/java_bytecode_parse_generics/Foo.class deleted file mode 100644 index e64c1c07f6a..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/Foo.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics$Inner.class b/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics$Inner.class new file mode 100644 index 00000000000..e2e3053da11 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics$Inner.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics.class b/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics.class new file mode 100644 index 00000000000..359c9a35a1c Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics.java b/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics.java new file mode 100644 index 00000000000..f27071a43f8 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/FunctionsWithGenerics.java @@ -0,0 +1,36 @@ +public class FunctionsWithGenerics +{ + + class Inner + { + public Generic x; + } + + public static Generic processReturnSame(Generic x) + { + return x; + } + + public static Generic processReturnDifferent(Generic s) + { + Generic x = new Generic(); + return x; + } + + public static Generic processReturnMultipleSame(Generic x, Generic y) + { + return x; + } + + public static Generic processReturnMultipleDifferent(Generic s, Generic b) + { + Generic x = new Generic(); + return x; + } + + public Generic returnInnerField(Inner inner) + { + return inner.x; + } + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Generic.class b/unit/java_bytecode/java_bytecode_parse_generics/Generic.class new file mode 100644 index 00000000000..5d5cca07ef3 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/Generic.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Generic.java b/unit/java_bytecode/java_bytecode_parse_generics/Generic.java new file mode 100644 index 00000000000..f852bc8f073 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/Generic.java @@ -0,0 +1,12 @@ +class Generic +{ + public T t; + public Generic g; + + public static Generic makeGeneric(T value) + { + Generic newST = new Generic(); + newST.t = value; + return newST; + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.class index 1b69af949ac..a54e0e2fd5a 100644 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.class and b/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.java b/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.java index 98cf9333743..0e7d24ea98a 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.java +++ b/unit/java_bytecode/java_bytecode_parse_generics/GenericArray.java @@ -1,6 +1,6 @@ class GenericArray { public T [] t; - public Integer [] Ia; - public int [] ia; + Generic[] t2; + Generic[] t3; } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClass$InnerClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClass$InnerClass.class deleted file mode 100644 index 5a263fcbd4b..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/GenericClass$InnerClass.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClass.class deleted file mode 100644 index 3b60626bea6..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/GenericClass.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClass.java b/unit/java_bytecode/java_bytecode_parse_generics/GenericClass.java deleted file mode 100644 index 8c13ed4f0db..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/GenericClass.java +++ /dev/null @@ -1,109 +0,0 @@ -public class GenericClass -{ - class InnerClass - { - } - - class GenericInnerClass - { - V field; - - class DoublyNestedInnerClass - { - - } - - class DoublyNestedInnerGenericClass - { - T field; - } - } - - class SameGenericParamInnerClass - { - T field; - } - - InnerClass field; - GenericInnerClass field2; - GenericInnerClass field3; - - GenericInnerClass.DoublyNestedInnerClass field4; - GenericInnerClass.DoublyNestedInnerClass field5; - - GenericInnerClass.DoublyNestedInnerGenericClass field6; - GenericInnerClass.DoublyNestedInnerGenericClass field7; - - void method(InnerClass input) - { - - } - - void method2(InnerClass input, InnerClass input2) - { - - } - - - void method3(GenericInnerClass input) - { - - } - - void method4(GenericInnerClass input) - { - - } - - void method5(GenericInnerClass.DoublyNestedInnerClass input) - { - - } - - void method6(GenericInnerClass.DoublyNestedInnerClass input) - { - - } - - void method7(GenericInnerClass.DoublyNestedInnerGenericClass input) - { - - } - - void method8(GenericInnerClass.DoublyNestedInnerGenericClass input) - { - - } - - InnerClass ret_method1() - { - return null; - } - - GenericInnerClass ret_method2() - { - return null; - } - - GenericInnerClass ret_method3() - { - return null; - } - - GenericInnerClass.DoublyNestedInnerClass ret_method4() - { - return null; - } - GenericInnerClass.DoublyNestedInnerClass ret_method5() - { - return null; - } - GenericInnerClass.DoublyNestedInnerGenericClass ret_method6() - { - return null; - } - GenericInnerClass.DoublyNestedInnerGenericClass ret_method7() - { - return null; - } -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass$DoublyNestedInnerClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass$DoublyNestedInnerClass.class new file mode 100644 index 00000000000..3065af91fd0 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass$DoublyNestedInnerClass.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass$DoublyNestedInnerGenericClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass$DoublyNestedInnerGenericClass.class new file mode 100644 index 00000000000..3ecc5dea34c Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass$DoublyNestedInnerGenericClass.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass.class new file mode 100644 index 00000000000..3a691c046fe Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$GenericInnerClass.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$InnerClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$InnerClass.class new file mode 100644 index 00000000000..87b4af7cb78 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$InnerClass.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$SameGenericParamInnerClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$SameGenericParamInnerClass.class new file mode 100644 index 00000000000..c46e01daea0 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$SameGenericParamInnerClass.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$TwoParamInnerClass.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$TwoParamInnerClass.class new file mode 100644 index 00000000000..c36503c16aa Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses$TwoParamInnerClass.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses.class new file mode 100644 index 00000000000..fe2480d4734 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses.java b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses.java new file mode 100644 index 00000000000..91d269a85dd --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/GenericClassWithGenericInnerClasses.java @@ -0,0 +1,147 @@ +public class GenericClassWithGenericInnerClasses +{ + class InnerClass + { + } + + class GenericInnerClass + { + V field; + + class DoublyNestedInnerClass + { + + } + + class DoublyNestedInnerGenericClass + { + T field; + } + } + + class SameGenericParamInnerClass + { + T field; + } + + class TwoParamInnerClass + { + K k; + L l; + } + + InnerClass field; + + GenericInnerClass field2; + GenericInnerClass field3; + + GenericInnerClass.DoublyNestedInnerClass field4; + GenericInnerClass.DoublyNestedInnerClass field5; + + GenericInnerClass.DoublyNestedInnerGenericClass field6; + GenericInnerClass.DoublyNestedInnerGenericClass field7; + + TwoParamInnerClass field8; + TwoParamInnerClass field9; + TwoParamInnerClass field10; + + void method(InnerClass input) + { + + } + + void method2(InnerClass input, InnerClass input2) + { + + } + + + void method3(GenericInnerClass input) + { + + } + + void method4(GenericInnerClass input) + { + + } + + void method5(GenericInnerClass.DoublyNestedInnerClass input) + { + + } + + void method6(GenericInnerClass.DoublyNestedInnerClass input) + { + + } + + void method7(GenericInnerClass.DoublyNestedInnerGenericClass input) + { + + } + + void method8(GenericInnerClass.DoublyNestedInnerGenericClass input) + { + + } + + void method9(TwoParamInnerClass input) + { + + } + + void method10(TwoParamInnerClass input) + { + + } + + void method11(TwoParamInnerClass input) + { + + } + + InnerClass ret_method1() + { + return null; + } + + GenericInnerClass ret_method2() + { + return null; + } + + GenericInnerClass ret_method3() + { + return null; + } + + GenericInnerClass.DoublyNestedInnerClass ret_method4() + { + return null; + } + GenericInnerClass.DoublyNestedInnerClass ret_method5() + { + return null; + } + GenericInnerClass.DoublyNestedInnerGenericClass ret_method6() + { + return null; + } + GenericInnerClass.DoublyNestedInnerGenericClass ret_method7() + { + return null; + } + TwoParamInnerClass ret_method8() + { + return null; + } + TwoParamInnerClass ret_method9() + { + return null; + } + TwoParamInnerClass ret_method10() + { + return null; + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericFields.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericFields.class new file mode 100644 index 00000000000..cef61ff3cc6 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericFields.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericFields.java b/unit/java_bytecode/java_bytecode_parse_generics/GenericFields.java new file mode 100644 index 00000000000..8f7a3b0e1ec --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/GenericFields.java @@ -0,0 +1,17 @@ +public class GenericFields { + public T f; + + public Generic f2; + public Generic f3; + + public Generic> f4; + public Generic>> f5; + + public GenericTwoParam f6; + public GenericTwoParam f7; + public GenericTwoParam f8; + public GenericTwoParam f9; + public GenericTwoParam f10; + + public GenericTwoParam, GenericTwoParam> f11; +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.class index e82142ef77c..15323c85953 100644 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.class and b/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.java b/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.java index 5a5eb5221f7..5140ed8705f 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.java +++ b/unit/java_bytecode/java_bytecode_parse_generics/GenericFunctions.java @@ -1,26 +1,126 @@ public class GenericFunctions { - public static void processSimpleGeneric(SimpleGeneric x) { - assert(x.t==null); + + //Methods with generic inputs + public static void processSimple(Generic x) + { + + } + + public static void processUpperBoundInterface(Generic x) + { + + } + + public static void processUpperBoundClass(Generic x) + { + + } + + public static void processDoubleUpperBoundClass(Generic x) + { + + } + + public static void processDoubleUpperBoundInterface(Generic x) + { + + } + + public static void processMultipleSimple(Generic t, Generic u) + { + + } + + public static void processMultipleUpperBound(Generic t, Generic u) + { + + } + + //Methods with generic output + public static Generic returnSimple() + { + Generic x=new Generic(); + return x; + } + + public static T returnSimpleField() + { + Generic x=new Generic(); + return x.t; + } + + public static Generic returnUpperBoundInterface() + { + Generic x=new Generic(); + return x; + } + + public static Generic returnUpperBoundClass() + { + Generic x=new Generic(); + return x; + } + + public static Generic returnDoubleUpperBoundClass() + { + Generic x=new Generic(); + return x; + } + + public static Generic returnDoubleUpperBoundInterface() + { + Generic x=new Generic(); + return x; + } + + //Methods with generic input and output + public static Generic processReturnSimpleSame(Generic x) + { + return x; + } + + public static Generic processReturnUpperBoundInterfaceSame(Generic x) + { + return x; + } + + public static Generic processReturnUpperBoundClassSame(Generic x) + { + return x; + } + + public static Generic processReturnDoubleUpperBoundClassSame(Generic x) + { + return x; + } + + public static Generic processReturnDoubleUpperBoundInterfaceSame(Generic x) + { + return x; } - // Test a wildcard generic bound by an interface - public static void processUpperBoundInterfaceGeneric(SimpleGeneric x) { - assert(x.t.getX() == 4); + public static Generic processReturnSimpleDifferent(Generic u) + { + Generic t=new Generic(); + return t; } - // Test a wild card generic bound by a class - public static void processUpperBoundClassGeneric(SimpleGeneric x) { - assert(x.t.getX() == 4); + public static Generic processReturnUpperBoundDifferent(Generic u) + { + Generic t=new Generic(); + return t; } - // Test a wild card generic bound by a class and an interface - public static void processDoubleUpperBoundClassGeneric(SimpleGeneric x) { - assert(x.t.getX() == 4); + public static Generic processReturnMultipleSimpleDifferent(Generic u, Generic v) + { + Generic t=new Generic(); + return t; } - // Test a wild card generic bound by two interfaces - public static void processDoubleUpperBoundInterfaceGeneric(SimpleGeneric x) { - assert(x.t.getX() == 4); + public static Generic processReturnMultipleUpperBoundDifferent(Generic u, Generic v) + { + Generic t=new Generic(); + return t; } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericTwoParam.class b/unit/java_bytecode/java_bytecode_parse_generics/GenericTwoParam.class new file mode 100644 index 00000000000..77a3ef12346 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/GenericTwoParam.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/GenericTwoParam.java b/unit/java_bytecode/java_bytecode_parse_generics/GenericTwoParam.java new file mode 100644 index 00000000000..c1deb233dd0 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/GenericTwoParam.java @@ -0,0 +1,5 @@ +class GenericTwoParam +{ + public T t; + public U u; +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Interface.class b/unit/java_bytecode/java_bytecode_parse_generics/Interface.class new file mode 100644 index 00000000000..c1668c7c684 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/Interface.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Interface.java b/unit/java_bytecode/java_bytecode_parse_generics/Interface.java new file mode 100644 index 00000000000..108c7204d01 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/Interface.java @@ -0,0 +1,4 @@ +interface Interface +{ + int getX(); +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterface.class b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Copy.class similarity index 50% rename from unit/java_bytecode/java_bytecode_parse_generics/BasicInterface.class rename to unit/java_bytecode/java_bytecode_parse_generics/Interface_Copy.class index 83f7444582f..a4b582ab07d 100644 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/BasicInterface.class and b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Copy.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Interface_Copy.java b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Copy.java new file mode 100644 index 00000000000..c09c1310d1c --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Copy.java @@ -0,0 +1,4 @@ +interface Interface_Copy +{ + int getX(); +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation.class b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation.class new file mode 100644 index 00000000000..6ac7e2b13eb Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Foo.java b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation.java similarity index 53% rename from unit/java_bytecode/java_bytecode_parse_generics/Foo.java rename to unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation.java index c81911835c6..2601520dcd4 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/Foo.java +++ b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation.java @@ -1,4 +1,4 @@ -class Foo implements BasicInterface +class Interface_Implementation implements Interface { public int x; diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation_Derived.class b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation_Derived.class new file mode 100644 index 00000000000..fcb2d78f8f2 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation_Derived.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation_Derived.java b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation_Derived.java new file mode 100644 index 00000000000..66c54762b39 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/Interface_Implementation_Derived.java @@ -0,0 +1,4 @@ +class Interface_Implementation_Derived extends Interface_Implementation +{ + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/NestedGenerics.class b/unit/java_bytecode/java_bytecode_parse_generics/NestedGenerics.class new file mode 100644 index 00000000000..8b73e5e887c Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/NestedGenerics.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/NestedGenerics.java b/unit/java_bytecode/java_bytecode_parse_generics/NestedGenerics.java new file mode 100644 index 00000000000..a4c1a469911 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/NestedGenerics.java @@ -0,0 +1,152 @@ +public class NestedGenerics +{ + Generic> field; + Generic> field2; + + Generic>> field3; + Generic>> field4; + + Generic> field5; + Generic> field6; + Generic> field7; + + GenericTwoParam, Generic> field8; + GenericTwoParam, Generic> field9; + GenericTwoParam, Generic> field10; + + GenericTwoParam, Interface_Implementation> field11; + GenericTwoParam>, Interface_Implementation> field12; + + GenericTwoParam, Generic> field13; + + void method(Generic> input) + { + + } + + void method2(Generic> input) + { + + } + + void method3(Generic>> input) + { + + } + + void method4(Generic>> input) + { + + } + + void method5(Generic> input) + { + + } + + void method6(Generic> input) + { + + } + + void method7(Generic> input) + { + + } + + void method8(GenericTwoParam, Generic> input) + { + + } + + void method9(GenericTwoParam, Generic> input) + { + + } + + void method10(GenericTwoParam, Generic> input) + { + + } + + void method11(GenericTwoParam, Interface_Implementation> input) + { + + } + void method12(GenericTwoParam>, Interface_Implementation> input) + { + + } + + void method13(GenericTwoParam, Generic> input) + { + + } + + + Generic> ret_method() + { + return null; + } + + Generic> ret_method2() + { + return null; + } + + Generic>> ret_method3() + { + return null; + } + + Generic>> ret_method4() + { + return null; + } + + Generic> ret_method5() + { + return null; + } + + Generic> ret_method6() + { + return null; + } + + Generic> ret_method7() + { + return null; + } + + GenericTwoParam, Generic> ret_method8() + { + return null; + } + + GenericTwoParam, Generic> ret_method9() + { + return null; + } + + GenericTwoParam, Generic> ret_method10() + { + return null; + } + + GenericTwoParam, Interface_Implementation> ret_method11() + { + return null; + } + + GenericTwoParam>, Interface_Implementation> ret_method12() + { + return null; + } + + GenericTwoParam, Generic> ret_method13() + { + return null; + } + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Outer$Inner.class b/unit/java_bytecode/java_bytecode_parse_generics/Outer$Inner.class deleted file mode 100644 index bab6c799f45..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/Outer$Inner.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Outer$InnerEnum.class b/unit/java_bytecode/java_bytecode_parse_generics/Outer$InnerEnum.class deleted file mode 100644 index a7256d80c2a..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/Outer$InnerEnum.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Outer.class b/unit/java_bytecode/java_bytecode_parse_generics/Outer.class deleted file mode 100644 index 84a9daeeae4..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/Outer.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/Outer.java b/unit/java_bytecode/java_bytecode_parse_generics/Outer.java deleted file mode 100644 index 0360a6adf15..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/Outer.java +++ /dev/null @@ -1,17 +0,0 @@ -public class Outer -{ - private class Inner - { - private final AbstractGenericClass u; - - Inner (AbstractGenericClass t) - { - this.u = t; - } - } - - private enum InnerEnum - { - - } -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.class b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.class index d637a7292a4..7cc35dde423 100644 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.class and b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.java b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.java index d3582c8bd46..f95454d3522 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.java +++ b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric.java @@ -1,4 +1,4 @@ -class RecursiveGeneric extends SimpleRecursiveGeneric +class RecursiveGeneric> { - + public T t; } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric_Derived.class b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric_Derived.class new file mode 100644 index 00000000000..ac48e62ea34 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric_Derived.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric_Derived.java b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric_Derived.java new file mode 100644 index 00000000000..4415ac9e038 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/RecursiveGeneric_Derived.java @@ -0,0 +1,4 @@ +class RecursiveGeneric_Derived extends RecursiveGeneric +{ + +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch$Inner.class b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch$Inner.class new file mode 100644 index 00000000000..aa3e07c3101 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch$Inner.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch$InnerEnum.class b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch$InnerEnum.class new file mode 100644 index 00000000000..3af3b7d4d07 Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch$InnerEnum.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch.class b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch.class new file mode 100644 index 00000000000..84c586fddfa Binary files /dev/null and b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch.java b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch.java new file mode 100644 index 00000000000..defe9600981 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/SignatureDescriptorMismatch.java @@ -0,0 +1,19 @@ +public class SignatureDescriptorMismatch +{ + // this models ArrayList.Sublist. for which we were getting an error + private class Inner + { + private final AbstractGeneric u; + + Inner (AbstractGeneric t) + { + this.u = t; + } + } + + // this models another situation in which the error occurred + private enum InnerEnum + { + + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SimpleGeneric.class b/unit/java_bytecode/java_bytecode_parse_generics/SimpleGeneric.class deleted file mode 100644 index 6ade3945c8d..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/SimpleGeneric.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SimpleGeneric.java b/unit/java_bytecode/java_bytecode_parse_generics/SimpleGeneric.java deleted file mode 100644 index 6db3d7bacbe..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/SimpleGeneric.java +++ /dev/null @@ -1,11 +0,0 @@ -class SimpleGeneric -{ - public T t; - - public static SimpleGeneric makeGeneric(T value) - { - SimpleGeneric newST = new SimpleGeneric(); - newST.t = value; - return newST; - } -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SimpleRecursiveGeneric.class b/unit/java_bytecode/java_bytecode_parse_generics/SimpleRecursiveGeneric.class deleted file mode 100644 index 3ca52a2b92b..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/SimpleRecursiveGeneric.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/SimpleRecursiveGeneric.java b/unit/java_bytecode/java_bytecode_parse_generics/SimpleRecursiveGeneric.java deleted file mode 100644 index e95851602da..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/SimpleRecursiveGeneric.java +++ /dev/null @@ -1,4 +0,0 @@ -class SimpleRecursiveGeneric> -{ - public T t; -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.class b/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.class index bf78c910d19..51f199d2bda 100644 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.class and b/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.class differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.java b/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.java index 29ad10e2e25..6d68ab25e17 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.java +++ b/unit/java_bytecode/java_bytecode_parse_generics/WildcardGenericFunctions.java @@ -1,54 +1,48 @@ public class WildcardGenericFunctions { // Test a wild card generic type - public static void processSimpleGeneric(SimpleGeneric x) { - assert(x.t.equals(null)); + public static void processSimpleGeneric(Generic x) + { + } // Test a wildcard generic bound by an interface - public static void processUpperBoundInterfaceGeneric(SimpleGeneric x) { - assert(x.t.getX() == 4); + public static void processUpperBoundInterfaceGeneric( + Generic x) + { + } // Test a wild card generic bound by a class - public static void processUpperBoundClassGeneric(SimpleGeneric x) { - assert(x.t.getX() == 4); + public static void processUpperBoundClassGeneric( + Generic x) + { + } - // It isn't legal to have an wild card with two upper bounds + // It isn't legal to have a wild card with two upper bounds // Per language spec on intersection types - public static void processLowerBoundGeneric(SimpleGeneric x, Foo assign) { - x.t = assign; + public static void processLowerBoundGeneric( + Generic x, + Interface_Implementation assign) + { + } // It is not legal Java to specify both an upper and lower bound - // public static void processBoundSuperClassGeneric(SimpleGeneric x, Foo assign) { - // x.t = assign; + // public static void processBoundSuperClassGeneric( + // Generic x, + // Interface_Implementation assign) + // { + // // } - // Test a wild card generic bound by a class - // public static void processBoundClassGenericDoubleBound(SimpleGeneric x) { - // assert(x.t.getX() == 4); + // It is not legal Java to specify two upper bounds + // Test a wild card generic bound by a class and an interface + // public static void processBoundClassGenericDoubleBound( + // Generic x) + // { + // // } - - public static void test() - { - SimpleGeneric myGenericValue = new SimpleGeneric(); - myGenericValue.t = null; - processSimpleGeneric(myGenericValue); - - myGenericValue.t = new Foo(); - myGenericValue.t.x = 4; - processUpperBoundInterfaceGeneric(myGenericValue); - - SimpleGeneric anotherGenericValue = new SimpleGeneric(); - anotherGenericValue.t = new Bar(); - anotherGenericValue.t.x = 4; - processUpperBoundClassGeneric(anotherGenericValue); - - - SimpleGeneric baseGenericValue = new SimpleGeneric(); - processLowerBoundGeneric(baseGenericValue, new Foo()); - } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics$bound_element.class b/unit/java_bytecode/java_bytecode_parse_generics/generics$bound_element.class deleted file mode 100644 index ef168d8e34c..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics$bound_element.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics$double_bound_element.class b/unit/java_bytecode/java_bytecode_parse_generics/generics$double_bound_element.class deleted file mode 100644 index af550821f2a..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics$double_bound_element.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics$dummyInterface.class b/unit/java_bytecode/java_bytecode_parse_generics/generics$dummyInterface.class deleted file mode 100644 index 20f3e82c81b..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics$dummyInterface.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics$element.class b/unit/java_bytecode/java_bytecode_parse_generics/generics$element.class deleted file mode 100644 index f1c63b72dde..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics$element.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics$two_elements.class b/unit/java_bytecode/java_bytecode_parse_generics/generics$two_elements.class deleted file mode 100644 index 4bbc9b11c62..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics$two_elements.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics.class b/unit/java_bytecode/java_bytecode_parse_generics/generics.class deleted file mode 100644 index 476830f150a..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics.java b/unit/java_bytecode/java_bytecode_parse_generics/generics.java deleted file mode 100644 index b2e18689158..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/generics.java +++ /dev/null @@ -1,59 +0,0 @@ -public class generics { - - interface dummyInterface - { - int getX(); - } - - class element { - E elem; - } - - class bound_element { - NUM elem; - NUM f() { - return elem; - } - void g(NUM e) { - elem=e; - } - } - - class double_bound_element - { - T elem; - } - -// definitely need to do some tests with bounded two elements - // the java_generic_type_from_string does not work for complex types - // Need to to unblock just get it so it throws when failing rather than wrong - class two_elements - { - K k; - V v; - } - - - - public static boolean foo(String s) - { - if(s.length == 0) - return true; - return false; - } - - bound_element belem; - - Integer f(int n) { - - element e=new element<>(); - e.elem=n; - bound_element be=new bound_element<>(); - belem=new bound_element<>(); - be.elem=new Integer(n+1); - if(n>0) - return e.elem; - else - return be.elem; - } -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/generics05$igeneric05.class b/unit/java_bytecode/java_bytecode_parse_generics/generics05$igeneric05.class deleted file mode 100644 index 179141a38e2..00000000000 Binary files a/unit/java_bytecode/java_bytecode_parse_generics/generics05$igeneric05.class and /dev/null differ diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_bounded_generic_inner_classes.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_bounded_generic_inner_classes.cpp new file mode 100644 index 00000000000..8e0111869c9 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_bounded_generic_inner_classes.cpp @@ -0,0 +1,155 @@ +/*******************************************************************\ + + Module: Unit tests for parsing generic classes + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include + +SCENARIO( + "parse_bounded_generic_inner_classes", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "BoundedGenericInnerClasses", + "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::BoundedGenericInnerClasses"; + REQUIRE(new_symbol_table.has_symbol(class_prefix)); + + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_class_typet &java_class_type = + require_type::require_java_non_generic_class(class_symbol.type); + + WHEN("Parsing an inner class with type variable") + { + std::string inner_name = class_prefix + "$Inner"; + REQUIRE(new_symbol_table.has_symbol(inner_name)); + THEN("The symbol type should be generic") + { + const symbolt &class_symbol = new_symbol_table.lookup_ref(inner_name); + const java_generics_class_typet &java_generics_class_type = + require_type::require_java_generic_class( + class_symbol.type, {inner_name + "::E"}); + + THEN("The fields are of correct types") + { + const struct_union_typet::componentt &elem = + require_type::require_component( + to_struct_type(class_symbol.type), "elem"); + require_type::require_java_generic_parameter( + elem.type(), + {require_type::type_parameter_kindt::Var, inner_name + "::E"}); + } + } + } + + WHEN("Parsing an inner class with bounded type variable") + { + std::string boundedinner_name = class_prefix + "$BoundedInner"; + REQUIRE(new_symbol_table.has_symbol(boundedinner_name)); + THEN("The symbol type should be generic") + { + const symbolt &class_symbol = + new_symbol_table.lookup_ref(boundedinner_name); + const java_generics_class_typet &java_generics_class_type = + require_type::require_java_generic_class( + class_symbol.type, {boundedinner_name + "::NUM"}); + + // TODO extend when bounds are parsed correctly - TG-1286 + + THEN("The fields are of correct types") + { + const struct_union_typet::componentt &elem = + require_type::require_component( + to_struct_type(class_symbol.type), "elem"); + require_type::require_java_generic_parameter( + elem.type(), + {require_type::type_parameter_kindt::Var, + boundedinner_name + "::NUM"}); + } + } + } + + WHEN("There is a generic field with a concrete type") + { + const struct_union_typet::componentt &belem_type = + require_type::require_component( + to_struct_type(class_symbol.type), "belem"); + require_type::require_pointer( + belem_type.type(), symbol_typet(class_prefix + "$BoundedInner")); + require_type::require_java_generic_type( + belem_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::java.lang.Integer"}}); + } + + WHEN("Parsing an inner class with double bounded type variable") + { + std::string doubleboundedinner_name = class_prefix + "$DoubleBoundedInner"; + REQUIRE(new_symbol_table.has_symbol(doubleboundedinner_name)); + THEN("The symbol type should be generic") + { + const symbolt &class_symbol = + new_symbol_table.lookup_ref(doubleboundedinner_name); + // TODO the symbol should be generic - TG-1349 + // const java_generics_class_typet &java_generics_class_type = + // require_type::require_java_generic_class( + // class_symbol.type, {doubleboundedinner_name + "::T"}); + + // TODO extend when bounds are parsed correctly - TG-1286 + + THEN("The fields are of correct types") + { + const struct_union_typet::componentt &elem = + require_type::require_component( + to_struct_type(class_symbol.type), "elem"); + require_type::require_java_generic_parameter( + elem.type(), + {require_type::type_parameter_kindt::Var, + doubleboundedinner_name + "::T"}); + + // TODO extend when bounds are parsed correctly - TG-1286 + } + } + } + + GIVEN("An inner class with multiple generic parameters") + { + std::string twoelementinner_name = class_prefix + "$TwoElementInner"; + REQUIRE(new_symbol_table.has_symbol(twoelementinner_name)); + THEN("The symbol type should be generic with two type variables") + { + const symbolt &class_symbol = + new_symbol_table.lookup_ref(twoelementinner_name); + const java_generics_class_typet &java_generics_class_type = + require_type::require_java_generic_class( + class_symbol.type, + {twoelementinner_name + "::K", twoelementinner_name + "::V"}); + + // TODO extend when bounds are parsed correctly - TG-1286 + + THEN("The fields are of correct types") + { + const struct_union_typet::componentt &elemk = + require_type::require_component( + to_struct_type(class_symbol.type), "k"); + require_type::require_java_generic_parameter( + elemk.type(), + {require_type::type_parameter_kindt::Var, + twoelementinner_name + "::K"}); + + const struct_union_typet::componentt &elemv = + require_type::require_component( + to_struct_type(class_symbol.type), "v"); + require_type::require_java_generic_parameter( + elemv.type(), + {require_type::type_parameter_kindt::Var, + twoelementinner_name + "::V"}); + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp index c0826e63cd0..2c4b698879d 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp @@ -7,37 +7,48 @@ \*******************************************************************/ #include +#include +#include -#include -#include +SCENARIO( + "parse_derived_generic_class_inst", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "DerivedGenericInst", "./java_bytecode/java_bytecode_parse_generics"); -#include -#include -#include -#include -#include -#include -#include + THEN("There should be a symbol for the DerivedGenericInst class") + { + std::string class_prefix = "java::DerivedGenericInst"; + REQUIRE(new_symbol_table.has_symbol(class_prefix)); + + const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix); + const class_typet &derived_class_type = + require_type::require_java_non_generic_class(derived_symbol.type); + + // TODO: Currently we do not support extracting information + // about the base classes generic information - issue TG-1287 + } +} SCENARIO( - "java_bytecode_parse_derived_generic_class", + "parse_derived_generic_class_uninst", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class( - "DerivedGeneric", - "./java_bytecode/java_bytecode_parse_generics"); + const symbol_tablet &new_symbol_table = load_java_class( + "DerivedGenericUninst", "./java_bytecode/java_bytecode_parse_generics"); - THEN("There should be a symbol for the DerivedGenreic class") + THEN("There should be a symbol for the DerivedGenericUninst class") { - std::string class_prefix="java::DerivedGeneric"; + std::string class_prefix = "java::DerivedGenericUninst"; REQUIRE(new_symbol_table.has_symbol(class_prefix)); - const symbolt &derived_symbol=new_symbol_table.lookup_ref(class_prefix); - const class_typet &derived_class_type= - require_symbol::require_complete_class(derived_symbol); + const symbolt &derived_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_generics_class_typet &derived_class_type = + require_type::require_java_generic_class( + derived_symbol.type, {class_prefix + "::T"}); - // TODO(tkiley): Currently we do not support extracting information - // about the base classes generic information. + // TODO: Currently we do not support extracting information + // about the base classes generic information - issue TG-1287 } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_functions_with_generics.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_functions_with_generics.cpp new file mode 100644 index 00000000000..f1aef3ff5d8 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_functions_with_generics.cpp @@ -0,0 +1,287 @@ +/*******************************************************************\ + + Module: Unit tests for parsing generic classes + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include + +SCENARIO( + "parse_functions_with_generics", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "FunctionsWithGenerics", "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::FunctionsWithGenerics"; + + WHEN("Parsing processReturnSame") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnSame"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet &func_code = + require_type::require_code(func_symbol.type); + + THEN("It has parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + + THEN("It has return type pointing to Generic") + { + const typet return_type = func_code.return_type(); + require_type::require_pointer( + return_type, symbol_typet("java::Generic")); + + THEN("It is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + return_type, + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + } + } + + WHEN("Parsing processReturnDifferent") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnDifferent"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = require_type::require_code(func_symbol.type); + + THEN("It has parameter s pointing to Generic") + { + const code_typet::parametert ¶m_s = + require_type::require_parameter(func_code, "s"); + require_type::require_pointer( + param_s.type(), symbol_typet("java::Generic")); + + THEN("s is generic with parameter pointing to java.lang.String") + { + require_type::require_java_generic_type( + param_s.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.String"}}); + } + } + + THEN("It has return type pointing to Generic") + { + const typet return_type = func_code.return_type(); + require_type::require_pointer( + return_type, symbol_typet("java::Generic")); + + THEN("It is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + return_type, + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + } + } + + WHEN("Parsing processReturnMultipleSame") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnMultipleSame"; + const std::string func_descriptor = ":(LGeneric;LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = require_type::require_code(func_symbol.type); + + THEN("It has parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + + THEN("It has parameter y pointing to Generic") + { + const code_typet::parametert ¶m_y = + require_type::require_parameter(func_code, "y"); + require_type::require_pointer( + param_y.type(), symbol_typet("java::Generic")); + + THEN("y is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + param_y.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + + THEN("It has return type pointing to Generic") + { + const typet return_type = func_code.return_type(); + require_type::require_pointer( + return_type, symbol_typet("java::Generic")); + + THEN("It is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + return_type, + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + } + } + + WHEN("Parsing processReturnMultipleDifferent") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnMultipleDifferent"; + const std::string func_descriptor = ":(LGeneric;LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = require_type::require_code(func_symbol.type); + + THEN("It has parameter s pointing to Generic") + { + const code_typet::parametert ¶m_s = + require_type::require_parameter(func_code, "s"); + require_type::require_pointer( + param_s.type(), symbol_typet("java::Generic")); + + THEN("s is generic with parameter pointing to java.lang.String") + { + require_type::require_java_generic_type( + param_s.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.String"}}); + } + } + + THEN("It has parameter b pointing to Generic") + { + const code_typet::parametert ¶m_b = + require_type::require_parameter(func_code, "b"); + require_type::require_pointer( + param_b.type(), symbol_typet("java::Generic")); + + THEN("b is generic with parameter pointing to java.lang.Boolean") + { + require_type::require_java_generic_type( + param_b.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Boolean"}}); + } + } + + THEN("It has return type pointing to Generic") + { + const typet return_type = func_code.return_type(); + require_type::require_pointer( + return_type, symbol_typet("java::Generic")); + + THEN("It is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + return_type, + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + } + } + + WHEN("Parsing returnInnerField") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnInnerField"; + const std::string func_descriptor = + ":(LFunctionsWithGenerics$Inner;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = require_type::require_code(func_symbol.type); + + THEN("It has parameter inner pointing to Inner") + { + const code_typet::parametert ¶m_inner = + require_type::require_parameter(func_code, "inner"); + require_type::require_pointer( + param_inner.type(), symbol_typet(class_prefix + "$Inner")); + } + + THEN("It has return type pointing to Generic") + { + const typet return_type = func_code.return_type(); + require_type::require_pointer( + return_type, symbol_typet("java::Generic")); + + THEN("It is generic with parameter pointing to java.lang.Integer") + { + require_type::require_java_generic_type( + return_type, + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_array_class.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_array_class.cpp index 6060c33c906..ac054de5e5e 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_array_class.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_array_class.cpp @@ -7,58 +7,102 @@ \*******************************************************************/ #include - -#include -#include -#include -#include - -#include #include - -#include -#include +#include SCENARIO( - "java_bytecode_parse_generic_array_class", + "parse_generic_array_class", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class("GenericArray", "" - "./java_bytecode/java_bytecode_parse_generics"); - - std::string class_prefix="java::GenericArray"; + const symbol_tablet &new_symbol_table = load_java_class( + "GenericArray", "./java_bytecode/java_bytecode_parse_generics"); + std::string class_prefix = "java::GenericArray"; REQUIRE(new_symbol_table.has_symbol(class_prefix)); - const struct_typet &type=to_struct_type( - new_symbol_table.lookup_ref(class_prefix).type); + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_generics_class_typet &java_generic_class = + require_type::require_java_generic_class( + class_symbol.type, {class_prefix + "::T"}); - THEN("There should be a component with name t") + THEN("There should be field t") { - REQUIRE(type.has_component("t")); + const struct_union_typet::componentt &field_t = + require_type::require_component(java_generic_class, "t"); + + THEN("It is an array") + { + const pointer_typet &field_t_pointer = require_type::require_pointer( + field_t.type(), symbol_typet("java::array[reference]")); + + const symbol_typet &field_t_subtype = + to_symbol_type(field_t_pointer.subtype()); + const struct_typet &subtype_type = to_struct_type( + new_symbol_table.lookup_ref(field_t_subtype.get_identifier()).type); + REQUIRE(is_valid_java_array(subtype_type)); + + THEN("The elements have the parametric type T") + { + const typet &element = java_array_element_type(field_t_subtype); + require_type::require_java_generic_parameter( + element, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}); + } + } } - const pointer_typet &t_component=to_pointer_type( - type.get_component("t") - .type()); - const symbol_typet &subtype=to_symbol_type(t_component.subtype()); - - THEN("The t component is a valid java array") + THEN("There should be field t2") { - const struct_typet &subtype_type=to_struct_type( - new_symbol_table.lookup_ref(subtype.get_identifier()).type); - REQUIRE(is_valid_java_array(subtype_type)); + const struct_union_typet::componentt &field_t2 = + require_type::require_component(java_generic_class, "t2"); + + THEN("It is an array") + { + const pointer_typet &field_t2_pointer = require_type::require_pointer( + field_t2.type(), symbol_typet("java::array[reference]")); + + const symbol_typet &field_t2_subtype = + to_symbol_type(field_t2_pointer.subtype()); + const struct_typet &subtype_struct = to_struct_type( + new_symbol_table.lookup_ref(field_t2_subtype.get_identifier()).type); + REQUIRE(is_valid_java_array(subtype_struct)); + + THEN("The elements have type Generic") + { + const typet &element = java_array_element_type(field_t2_subtype); + require_type::require_pointer(element, symbol_typet("java::Generic")); + require_type::require_java_generic_type( + element, + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } } - THEN("The elements of the t component have the parametric type T") + THEN("There should be field t3") { - const typet &element=static_cast(subtype.find( - ID_C_element_type)); - REQUIRE(is_java_generic_parameter(element)); - - REQUIRE( - to_java_generic_parameter(element).type_variable().get_identifier()== - "java::GenericArray::T"); + const struct_union_typet::componentt &field_t3 = + require_type::require_component(java_generic_class, "t3"); + + THEN("It is an array") + { + const pointer_typet &field_t3_pointer = require_type::require_pointer( + field_t3.type(), symbol_typet("java::array[reference]")); + + const symbol_typet &field_t3_subtype = + to_symbol_type(field_t3_pointer.subtype()); + const struct_typet &subtype_struct = to_struct_type( + new_symbol_table.lookup_ref(field_t3_subtype.get_identifier()).type); + REQUIRE(is_valid_java_array(subtype_struct)); + + THEN("The elements have type Generic") + { + const typet &element = java_array_element_type(field_t3_subtype); + require_type::require_pointer(element, symbol_typet("java::Generic")); + require_type::require_java_generic_type( + element, + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp index ade836cb549..3487a4e4e3e 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp @@ -8,315 +8,105 @@ #include #include - -#include -#include - -#include -#include -#include -#include +#include SCENARIO( - "java_bytecode_parse_generics", + "parse_generic_class_one_param", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class("generics", "./java_bytecode/java_bytecode_parse_generics"); + const symbol_tablet &new_symbol_table = + load_java_class("Generic", "./java_bytecode/java_bytecode_parse_generics"); - GIVEN("Some class files with Generics") + std::string class_prefix = "java::Generic"; + + WHEN("Parsing the class") { - WHEN("Parsing a class with type variable") + THEN("There is a generic class symbol Generic") { - REQUIRE(new_symbol_table.has_symbol("java::generics$element")); - THEN("The symbol type should be generic") - { - const symbolt &class_symbol= - new_symbol_table.lookup_ref("java::generics$element"); - const typet &symbol_type=class_symbol.type; + REQUIRE(new_symbol_table.has_symbol(class_prefix)); - REQUIRE(symbol_type.id()==ID_struct); - class_typet class_type=to_class_type(symbol_type); - REQUIRE(class_type.is_class()); - java_class_typet java_class_type=to_java_class_type(class_type); - REQUIRE(is_java_generics_class_type(java_class_type)); - java_generics_class_typet java_generics_class_type= - to_java_generics_class_type(java_class_type); + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_generics_class_typet &java_generics_class = + require_type::require_java_generic_class( + class_symbol.type, {class_prefix + "::T"}); - const struct_union_typet::componentt &elem= - java_generics_class_type.get_component("elem"); - const typet &elem_type=java_class_type.component_type("elem"); - - REQUIRE(is_java_generic_parameter(elem_type)); + const struct_typet class_struct = to_struct_type(class_symbol.type); + THEN("It has field t") + { + const struct_union_typet::componentt &field_t = + require_type::require_component(class_struct, "t"); - REQUIRE(java_generics_class_type.generic_types().size()==1); - THEN("Type variable is named 'E'") + THEN("It is the generic parameter T") { - typet &type_var=java_generics_class_type.generic_types().front(); - REQUIRE(is_java_generic_parameter(type_var)); - java_generic_parametert generic_type_var= - to_java_generic_parameter(type_var); - REQUIRE( - generic_type_var.type_variable().get_identifier()== - "java::generics$element::E"); - typet &sub_type=generic_type_var.subtype(); - REQUIRE(sub_type.id()==ID_symbol); - symbol_typet &bound_type=to_symbol_type(sub_type); - REQUIRE(bound_type.get_identifier()=="java::java.lang.Object"); + require_type::require_java_generic_parameter( + field_t.type(), + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}); } } - } - } - GIVEN("Some class files with generic type variable") - { - WHEN("Parsing a class with bounded type variable") - { - REQUIRE(new_symbol_table.has_symbol("java::generics$bound_element")); - THEN("The symbol type should be generic") + THEN("It has field g pointing to Generic") { - const symbolt &class_symbol= - new_symbol_table.lookup_ref("java::generics$bound_element"); - const typet &symbol_type=class_symbol.type; + const struct_union_typet::componentt &field_g = + require_type::require_component(class_struct, "g"); + require_type::require_pointer( + field_g.type(), symbol_typet("java::Generic")); - REQUIRE(symbol_type.id()==ID_struct); - class_typet class_type=to_class_type(symbol_type); - REQUIRE(class_type.is_class()); - java_class_typet java_class_type=to_java_class_type(class_type); - REQUIRE(is_java_generics_class_type(java_class_type)); - java_generics_class_typet java_generics_class_type= - to_java_generics_class_type(java_class_type); - REQUIRE(java_generics_class_type.generic_types().size()==1); - typet &type_var=java_generics_class_type.generic_types().front(); - REQUIRE(is_java_generic_parameter(type_var)); - java_generic_parametert generic_type_var= - to_java_generic_parameter(type_var); - - REQUIRE( - generic_type_var.type_variable().get_identifier()== - "java::generics$bound_element::NUM"); - REQUIRE( - java_generics_class_type_var(0, java_generics_class_type)== - "java::generics$bound_element::NUM"); - THEN("Bound must be Number") + THEN("It is generic with parameter pointing to java.lang.Integer") { - typet &sub_type=generic_type_var.subtype(); - REQUIRE(sub_type.id()==ID_symbol); - symbol_typet &bound_type=to_symbol_type(sub_type); - REQUIRE(bound_type.get_identifier()=="java::java.lang.Number"); - REQUIRE( - to_symbol_type( - java_generics_class_type_bound(0, java_generics_class_type)) - .get_identifier()=="java::java.lang.Number"); + require_type::require_java_generic_type( + field_g.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); } - - const struct_union_typet::componentt &elem= - java_generics_class_type.get_component("elem"); - const typet &elem_type=java_class_type.component_type("elem"); - - REQUIRE(is_java_generic_parameter(elem_type)); } } } +} - GIVEN("Some class files with generic type variable") - { - WHEN("Parsing a class with bounded type variable") - { - REQUIRE(new_symbol_table.has_symbol("java::generics")); - - THEN("The generic fields should be annotated with concrete types") - { - const symbolt &class_symbol= - new_symbol_table.lookup_ref("java::generics"); - const typet &symbol_type=class_symbol.type; - - REQUIRE(symbol_type.id()==ID_struct); - class_typet class_type=to_class_type(symbol_type); - REQUIRE(class_type.is_class()); - java_class_typet java_class_type=to_java_class_type(class_type); - REQUIRE(!is_java_generics_class_type(java_class_type)); - - const struct_union_typet::componentt &belem= - java_class_type.get_component("belem"); - const typet &belem_type=java_class_type.component_type("belem"); - - REQUIRE(belem_type!=nil_typet()); - REQUIRE(is_java_generic_type(belem_type)); - THEN("Field has instantiated type variable") - { - const java_generic_typet &container= - to_java_generic_type(belem_type); - - const std::vector &generic_types= - container.generic_type_variables(); - REQUIRE(generic_types.size()==1); - - const typet& inst_type=java_generic_get_inst_type(0, container); +SCENARIO( + "parse_generic_class_two_param", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "GenericTwoParam", "./java_bytecode/java_bytecode_parse_generics"); - REQUIRE(inst_type.id()==ID_pointer); - const typet &inst_type_symbol=inst_type.subtype(); - REQUIRE(inst_type_symbol.id()==ID_symbol); - REQUIRE( - to_symbol_type(inst_type_symbol).get_identifier()== - "java::java.lang.Integer"); - } - } - } - } + std::string class_prefix = "java::GenericTwoParam"; - GIVEN("Some class files with Generics") + WHEN("Parsing the class") { - WHEN("Methods with generic signatures") + THEN("There is a generic class symbol GenericTwoParam") { - REQUIRE( - new_symbol_table - .has_symbol("java::generics$bound_element.f:()Ljava/lang/Number;")); + REQUIRE(new_symbol_table.has_symbol(class_prefix)); -// TODO: methods should have generic return type (the tests needs to be -// extended) - THEN("The method should have generic return type") - { - const symbolt &method_symbol= - new_symbol_table - .lookup_ref("java::generics$bound_element.f:()Ljava/lang/Number;"); - const typet &symbol_type=method_symbol.type; - - REQUIRE(symbol_type.id()==ID_code); - - const code_typet &code=to_code_type(symbol_type); - } + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_generics_class_typet &java_generics_class = + require_type::require_java_generic_class( + class_symbol.type, {class_prefix + "::T", class_prefix + "::U"}); - REQUIRE( - new_symbol_table - .has_symbol("java::generics$bound_element.g:(Ljava/lang/Number;)V")); - THEN("The method should have a generic parameter.") + const struct_typet class_struct = to_struct_type(class_symbol.type); + THEN("It has field t") { - const symbolt &method_symbol= - new_symbol_table - .lookup_ref("java::generics$bound_element.g:(Ljava/lang/Number;)V"); - const typet &symbol_type=method_symbol.type; + const struct_union_typet::componentt &field_t = + require_type::require_component(class_struct, "t"); - REQUIRE(symbol_type.id()==ID_code); - - const code_typet &code=to_code_type(symbol_type); - - bool found=false; - for(const auto &p : code.parameters()) + THEN("It is the generic parameter T") { - if(p.get_identifier()== - "java::generics$bound_element.g:(Ljava/lang/Number;)V::e") - { - found=true; - const typet &t=p.type(); - REQUIRE(is_java_generic_parameter(p.type())); - const java_generic_parametert &gen_type= - to_java_generic_parameter(p.type()); - const symbol_typet &type_var=gen_type.type_variable(); - REQUIRE(type_var.get_identifier()== - "java::generics$bound_element::NUM"); - break; - } + require_type::require_java_generic_parameter( + field_t.type(), + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}); } - REQUIRE(found); } - } - } - GIVEN("A class with multiple bounds") - { - THEN("The bounds should be encoded") - { - REQUIRE( - new_symbol_table.has_symbol("java::generics$double_bound_element")); - THEN("The symbol should have a generic parameter") + THEN("It has field u") { - const symbolt &class_symbol= - new_symbol_table.lookup_ref("java::generics$double_bound_element"); - const typet &symbol_type=class_symbol.type; - - REQUIRE(symbol_type.id()==ID_struct); - class_typet class_type=to_class_type(symbol_type); - REQUIRE(class_type.is_class()); - java_class_typet java_class_type=to_java_class_type(class_type); - REQUIRE_FALSE(is_java_generics_class_type(java_class_type)); - - // TODO (tkiley): Extend this unit test when bounds are correctly - // parsed. -#if 0 - java_generics_class_typet java_generics_class_type= - to_java_generics_class_type(java_class_type); - REQUIRE(java_generics_class_type.generic_types().size()==1); - typet &type_var=java_generics_class_type.generic_types().front(); - REQUIRE(is_java_generic_parameter(type_var)); - java_generic_parametert generic_type_var= - to_java_generic_parameter(type_var); + const struct_union_typet::componentt &field_u = + require_type::require_component(class_struct, "u"); - REQUIRE( - generic_type_var.type_variable().get_identifier()== - "java::generics$double_bound_element::T"); - REQUIRE( - java_generics_class_type_var(0, java_generics_class_type)== - "java::generics$double_bound_element::T"); - THEN("Bound must be Number and dummyInterface") + THEN("It is the generic parameter U") { - + require_type::require_java_generic_parameter( + field_u.type(), + {require_type::type_parameter_kindt::Var, class_prefix + "::U"}); } -#endif - } - } - } - GIVEN("A class with multiple generic parameters") - { - THEN("Both generic parameters should be encoded") - { - const symbolt &class_symbol= - new_symbol_table.lookup_ref("java::generics$two_elements"); - const typet &symbol_type=class_symbol.type; - - REQUIRE(symbol_type.id()==ID_struct); - class_typet class_type=to_class_type(symbol_type); - REQUIRE(class_type.is_class()); - java_class_typet java_class_type=to_java_class_type(class_type); - REQUIRE(is_java_generics_class_type(java_class_type)); - - java_generics_class_typet java_generics_class_type= - to_java_generics_class_type(java_class_type); - REQUIRE(java_generics_class_type.generic_types().size()==2); - - auto generic_param_iterator= - java_generics_class_type.generic_types().cbegin(); - - // The first parameter should be called K - { - const typet &first_param=*generic_param_iterator; - REQUIRE(is_java_generic_parameter(first_param)); - java_generic_parametert generic_type_var= - to_java_generic_parameter(first_param); - - REQUIRE( - generic_type_var.type_variable().get_identifier()== - "java::generics$two_elements::K"); - REQUIRE( - java_generics_class_type_var(0, java_generics_class_type)== - "java::generics$two_elements::K"); - } - - ++generic_param_iterator; - - - // The second parameter should be called V - { - const typet &second_param=*generic_param_iterator; - REQUIRE(is_java_generic_parameter(second_param)); - java_generic_parametert generic_type_var= - to_java_generic_parameter(second_param); - - REQUIRE( - generic_type_var.type_variable().get_identifier()== - "java::generics$two_elements::V"); - REQUIRE( - java_generics_class_type_var(1, java_generics_class_type)== - "java::generics$two_elements::V"); } } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class_with_generic_inner_classes.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class_with_generic_inner_classes.cpp new file mode 100644 index 00000000000..47bbcd2c2e9 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_class_with_generic_inner_classes.cpp @@ -0,0 +1,926 @@ +/*******************************************************************\ + + Module: Unit tests for parsing generic classes + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include + +SCENARIO( + "parse_generic_class_with_generic_inner_classes_fields", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "GenericClassWithGenericInnerClasses", + "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::GenericClassWithGenericInnerClasses"; + THEN( + "There should be a symbol for " + "GenericClassWithGenericInnerClasses with correct components") + { + REQUIRE(new_symbol_table.has_symbol(class_prefix)); + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_generics_class_typet &java_generic_class = + require_type::require_java_generic_class( + class_symbol.type, {class_prefix + "::T"}); + + THEN( + "The field component should be a pointer to " + "GenericClassWithGenericInnerClasses$InnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field"); + + require_type::require_pointer( + field_component.type(), symbol_typet(class_prefix + "$InnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN( + "The field2 component should be a pointer to " + "GenericClassWithGenericInnerClasses$GenericInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field2"); + + require_type::require_pointer( + field_component.type(), + symbol_typet(class_prefix + "$GenericInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + + THEN( + "The field3 component should be a pointer to " + "GenericClassWithGenericInnerClasses$GenericInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field3"); + + require_type::require_pointer( + field_component.type(), + symbol_typet(class_prefix + "$GenericInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN( + "The field4 component should be a pointer to GenericClassWithGeneric" + "InnerClasses$GenericInnerClass$DoublyNestedInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field4"); + + require_type::require_pointer( + field_component.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + + THEN( + "The field5 component should be a pointer to GenericClassWithGeneric" + "InnerClasses$GenericInnerClass$DoublyNestedInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field5"); + + require_type::require_pointer( + field_component.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN( + "The field6 component should be a pointer to GenericClassWithGeneric" + "InnerClasses$GenericInnerClass$DoublyNestedInnerGenericClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field6"); + + require_type::require_pointer( + field_component.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + + THEN( + "The field7 component should be a pointer to GenericClassWithGeneric" + "InnerClasses$GenericInnerClass$DoublyNestedInnerGenericClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field7"); + + require_type::require_pointer( + field_component.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN( + "The field8 component should be a pointer to " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field8"); + + require_type::require_pointer( + field_component.type(), + symbol_typet(class_prefix + "$TwoParamInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + + THEN( + "The field9 component should be a pointer to " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field9"); + + require_type::require_pointer( + field_component.type(), + symbol_typet(class_prefix + "$TwoParamInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Var, + class_prefix + "::T"}}); + } + } + + THEN( + "The field10 component should be a pointer to " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const struct_typet::componentt &field_component = + require_type::require_component(java_generic_class, "field10"); + + require_type::require_pointer( + field_component.type(), + symbol_typet(class_prefix + "$TwoParamInnerClass")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + } +} + +SCENARIO( + "parse_generic_class_with_generic_inner_classes_methods", + "[core][java_bytecode][java_bytecode_parse_generics][caskjd]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "GenericClassWithGenericInnerClasses", + "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::GenericClassWithGenericInnerClasses"; + + THEN( + "Method 1 should take a pointer to " + "GenericClassWithGenericInnerClasses$InnerClass") + { + const std::string func_name = ".method"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$InnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$InnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Method 2 should take two pointers to " + "GenericClassWithGenericInnerClasses$InnerClass") + { + const std::string func_name = ".method2"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$InnerClass;" + "LGenericClassWithGenericInnerClasses$InnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 3); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$InnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + const auto ¶m_type2 = + require_type::require_parameter(function_call, "input2"); + require_type::require_pointer( + param_type2.type(), symbol_typet(class_prefix + "$InnerClass")); + require_type::require_java_generic_type( + param_type2.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Method 3 should take a pointer to " + "GenericClassWithGenericInnerClasses$GenericInnerClass") + { + const std::string func_name = ".method3"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$GenericInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$GenericInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Method 4 should take a pointer to " + "GenericClassWithGenericInnerClasses$GenericInnerClass") + { + const std::string func_name = ".method4"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$GenericInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$GenericInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Method 5 should take a pointer to GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerClass") + { + const std::string func_name = ".method5"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Method 6 should take a pointer to GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerClass") + { + const std::string func_name = ".method6"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Method 7 should take a pointer to GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerGenericClass") + { + const std::string func_name = ".method7"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerGenericClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Method 8 should take a pointer to GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerGenericClass") + { + const std::string func_name = ".method8"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerGenericClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Method 9 should take a pointer to " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const std::string func_name = ".method9"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$TwoParamInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of the correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$TwoParamInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Method 10 should take a pointer to " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const std::string func_name = ".method10"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$TwoParamInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of the correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$TwoParamInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Var, + class_prefix + "::T"}}); + } + } + THEN( + "Method 11 should take a pointer to " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const std::string func_name = ".method11"; + const std::string func_descriptor = + ":(LGenericClassWithGenericInnerClasses$TwoParamInnerClass;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs should be of the correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet(class_prefix + "$TwoParamInnerClass")); + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Ret Method 1 should return a " + "GenericClassWithGenericInnerClasses$InnerClass") + { + const std::string func_name = ".ret_method1"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$InnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet(class_prefix + "$InnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Ret method 2 should return a " + "GenericClassWithGenericInnerClasses$GenericInnerClass") + { + const std::string func_name = ".ret_method2"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$GenericInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet(class_prefix + "$GenericInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Ret method 3 should return a " + "GenericClassWithGenericInnerClasses$GenericInnerClass") + { + const std::string func_name = ".ret_method3"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$GenericInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet(class_prefix + "$GenericInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Ret method 4 should return a GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerClass") + { + const std::string func_name = ".ret_method4"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Ret method 5 should return a GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerClass") + { + const std::string func_name = ".ret_method5"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Ret method 6 should return a GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerGenericClass") + { + const std::string func_name = ".ret_method6"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerGenericClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Ret method 7 should return a GenericClassWithGenericInnerClasses" + "$GenericInnerClass$DoublyNestedInnerGenericClass") + { + const std::string func_name = ".ret_method7"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$" + "GenericInnerClass$DoublyNestedInnerGenericClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet( + class_prefix + "$GenericInnerClass$DoublyNestedInnerGenericClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN( + "Ret method 8 should return a " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const std::string func_name = ".ret_method8"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$" + "TwoParamInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet(class_prefix + "$TwoParamInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + } + } + THEN( + "Ret method 9 should return a " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const std::string func_name = ".ret_method9"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$TwoParamInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet(class_prefix + "$TwoParamInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}, + {require_type::type_parameter_kindt::Var, + class_prefix + "::T"}}); + } + } + THEN( + "Ret method 10 should return a " + "GenericClassWithGenericInnerClasses$TwoParamInnerClass") + { + const std::string func_name = ".ret_method10"; + const std::string func_descriptor = + ":()LGenericClassWithGenericInnerClasses$TwoParamInnerClass;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type should be correct") + { + require_type::require_pointer( + function_call.return_type(), + symbol_typet(class_prefix + "$TwoParamInnerClass")); + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_fields.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_fields.cpp new file mode 100644 index 00000000000..d1108be3952 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_fields.cpp @@ -0,0 +1,218 @@ +/*******************************************************************\ + + Module: Unit tests for parsing generic classes + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include + +SCENARIO( + "parse_generic_fields", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "GenericFields", "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::GenericFields"; + + WHEN("Parsing the class with generic fields") + { + THEN("There is a generic class symbol GenericField") + { + REQUIRE(new_symbol_table.has_symbol(class_prefix)); + + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + const java_generics_class_typet &java_generics_class_type = + require_type::require_java_generic_class( + class_symbol.type, {class_prefix + "::T", class_prefix + "::S"}); + + const struct_typet class_struct = to_struct_type(class_symbol.type); + + THEN("It has field f of type T") + { + const struct_union_typet::componentt &field = + require_type::require_component(class_struct, "f"); + require_type::require_java_generic_parameter( + field.type(), + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}); + } + + THEN("It has field f2 pointing to Generic") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f2"); + require_type::require_pointer( + field.type(), symbol_typet("java::Generic")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN("It has field f3 pointing to Generic") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f3"); + require_type::require_pointer( + field.type(), symbol_typet("java::Generic")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + + THEN("It has field f3 pointing to Generic") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f3"); + require_type::require_pointer( + field.type(), symbol_typet("java::Generic")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + + THEN("It has field f4 pointing to Generic") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f4"); + require_type::require_pointer( + field.type(), symbol_typet("java::Generic")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO extend when nested generics are parsed correctly - TG-1301 + } + } + + THEN("It has field f5 pointing to Generic") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f5"); + require_type::require_pointer( + field.type(), symbol_typet("java::Generic")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO extend when nested generics are parsed correctly - TG-1301 + } + } + + THEN("It has field f6 pointing to GenericTwoParam") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f6"); + require_type::require_pointer( + field.type(), symbol_typet("java::GenericTwoParam")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN("It has field f7 pointing to GenericTwoParam") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f7"); + require_type::require_pointer( + field.type(), symbol_typet("java::GenericTwoParam")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}, + {require_type::type_parameter_kindt::Var, class_prefix + "::S"}}); + } + } + + THEN("It has field f8 pointing to GenericTwoParam") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f8"); + require_type::require_pointer( + field.type(), symbol_typet("java::GenericTwoParam")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}, + {require_type::type_parameter_kindt::Var, + class_prefix + "::T"}}); + } + } + + THEN("It has field f9 pointing to GenericTwoParam") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f9"); + require_type::require_pointer( + field.type(), symbol_typet("java::GenericTwoParam")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Var, + class_prefix + "::T"}, + {require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}}); + } + } + + THEN("It has field f10 pointing to GenericTwoParam") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f10"); + require_type::require_pointer( + field.type(), symbol_typet("java::GenericTwoParam")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, + "java::java.lang.Integer"}, + {require_type::type_parameter_kindt::Inst, + "java::java.lang.String"}}); + } + } + + THEN("It has field f11 pointing to GenericTwoParam") + { + const struct_typet::componentt &field = + require_type::require_component(class_struct, "f11"); + require_type::require_pointer( + field.type(), symbol_typet("java::GenericTwoParam")); + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field.type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + // TODO extend when nested generics are parsed correctly - TG-1301 + } + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_functions.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_functions.cpp index 66e89cddb12..e4818e7639a 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_functions.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_functions.cpp @@ -7,69 +7,1013 @@ \*******************************************************************/ #include - -#include -#include -#include -#include - -#include - -#include #include +#include SCENARIO( - "java_bytecode_parse_generic_function", + "parse_generic_functions", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class( - "GenericFunctions", - "./java_bytecode/java_bytecode_parse_generics"); + const symbol_tablet &new_symbol_table = load_java_class( + "GenericFunctions", "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::GenericFunctions"; + + WHEN("Parsing processSimple") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processSimple"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + } + } + + WHEN("Parsing processUpperBoundInterface") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processUpperBoundInterface"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend tests when fixed - + // issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processUpperBoundClass") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processUpperBoundClass"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend tests when fixed - + // issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processDoubleUpperBoundClass") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processDoubleUpperBoundClass"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processDoubleUpperBoundInterface") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processDoubleUpperBoundInterface"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processMultipleSimple") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processMultipleSimple"; + const std::string func_descriptor = ":(LGeneric;LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 2); + + THEN("It contains parameter t pointing to Generic") + { + const code_typet::parametert ¶m_t = + require_type::require_parameter(func_code, "t"); + require_type::require_pointer( + param_t.type(), symbol_typet("java::Generic")); + + THEN("t is generic with type variable T") + { + require_type::require_java_generic_type( + param_t.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + THEN("It contains parameter u pointing to Generic") + { + const code_typet::parametert ¶m_u = + require_type::require_parameter(func_code, "u"); + require_type::require_pointer( + param_u.type(), symbol_typet("java::Generic")); + + THEN("u is generic with type variable U") + { + require_type::require_java_generic_type( + param_u.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::U"}}); + } + } + } + } + + WHEN("Parsing processMultipleUpperBound") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processMultipleUpperBound"; + const std::string func_descriptor = ":(LGeneric;LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 2); + + THEN("It contains parameter t pointing to Generic") + { + const code_typet::parametert ¶m_t = + require_type::require_parameter(func_code, "t"); + require_type::require_pointer( + param_t.type(), symbol_typet("java::Generic")); + + THEN("t is generic with type variable T") + { + require_type::require_java_generic_type( + param_t.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend the tests when + // fixed - issue TG-1286 + } + } + } + THEN("It contains parameter u pointing to Generic") + { + const code_typet::parametert ¶m_u = + require_type::require_parameter(func_code, "u"); + require_type::require_pointer( + param_u.type(), symbol_typet("java::Generic")); + + THEN("u is generic with type variable U") + { + require_type::require_java_generic_type( + param_u.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::U"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing returnSimple") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnSimple"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 0); + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + } + } + + WHEN("Parsing returnSimpleField") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnSimpleField"; + const std::string func_descriptor = ":()Ljava/lang/Object;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 0); + THEN("It has return type pointing to java.lang.Object") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::java.lang.Object")); + + THEN("It is the generic parameter T") + { + require_type::require_java_generic_parameter( + func_code.return_type(), + {require_type::type_parameter_kindt::Var, class_prefix + "::T"}); + } + } + } + } + + WHEN("Parsing returnUpperBoundInterface") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnUpperBoundInterface"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = to_code_type(func_symbol.type); + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing returnUpperBoundClass") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnUpperBoundClass"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 0); + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing returnDoubleUpperBoundClass") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnDoubleUpperBoundClass"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 0); + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); - std::string class_prefix="java::GenericFunctions"; - THEN("There should be a symbol for processSimpleGeneric") + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing returnDoubleUpperBoundInterface") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".returnDoubleUpperBoundInterface"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 0); + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processReturnSimpleSame") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnSimpleSame"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + } + } + + WHEN("Parsing processReturnUpperBoundInterfaceSame") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnUpperBoundInterfaceSame"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processReturnUpperBoundClassSame") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnUpperBoundClassSame"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processReturnDoubleUpperBoundClassSame") + { + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnDoubleUpperBoundClassSame"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); + + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } + } + + WHEN("Parsing processReturnDoubleUpperBoundInterfaceSame") { - const std::string func_name=".processSimpleGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + THEN("There should be a symbol for the function") + { + const std::string func_name = + ".processReturnDoubleUpperBoundInterfaceSame"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + + THEN("It contains parameter x pointing to Generic") + { + const code_typet::parametert ¶m_x = + require_type::require_parameter(func_code, "x"); + require_type::require_pointer( + param_x.type(), symbol_typet("java::Generic")); - REQUIRE(new_symbol_table.has_symbol(process_func_name)); + THEN("x is generic with type variable T") + { + require_type::require_java_generic_type( + param_x.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; extend the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } } - THEN("There should be a symbol for processUpperBoundInterfaceGeneric") + WHEN("Parsing processReturnSimpleDifferent") { - const std::string func_name=".processUpperBoundInterfaceGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnSimpleDifferent"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); - REQUIRE(new_symbol_table.has_symbol(process_func_name)); + THEN("It contains parameter u pointing to Generic") + { + const code_typet::parametert ¶m_u = + require_type::require_parameter(func_code, "u"); + require_type::require_pointer( + param_u.type(), symbol_typet("java::Generic")); + + THEN("u is generic with type variable U") + { + require_type::require_java_generic_type( + param_u.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::U"}}); + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + } } - THEN("There should be a symbol for processUpperBoundClassGeneric") + WHEN("Parsing processReturnUpperBoundDifferent") { - const std::string func_name=".processUpperBoundClassGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnUpperBoundDifferent"; + const std::string func_descriptor = ":(LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 1); + + THEN("It contains parameter u pointing to Generic") + { + const code_typet::parametert ¶m_u = + require_type::require_parameter(func_code, "u"); + require_type::require_pointer( + param_u.type(), symbol_typet("java::Generic")); - REQUIRE(new_symbol_table.has_symbol(process_func_name)); + THEN("u is generic with type variable U") + { + require_type::require_java_generic_type( + param_u.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::U"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } } - THEN("There should be a symbol for processDoubleUpperBoundClassGeneric") + WHEN("Parsing processReturnMultipleSimpleDifferent") { - const std::string func_name=".processDoubleUpperBoundClassGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnMultipleSimpleDifferent"; + const std::string func_descriptor = ":(LGeneric;LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 2); + + THEN("It contains parameter u pointing to Generic") + { + const code_typet::parametert ¶m_u = + require_type::require_parameter(func_code, "u"); + require_type::require_pointer( + param_u.type(), symbol_typet("java::Generic")); + + THEN("u is generic with type variable U") + { + require_type::require_java_generic_type( + param_u.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::U"}}); + } + } + + THEN("It contains parameter v pointing to Generic") + { + const code_typet::parametert ¶m_v = + require_type::require_parameter(func_code, "v"); + require_type::require_pointer( + param_v.type(), symbol_typet("java::Generic")); + + THEN("v is generic with type variable V") + { + require_type::require_java_generic_type( + param_v.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::V"}}); + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); - REQUIRE(new_symbol_table.has_symbol(process_func_name)); + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); + } + } + } } - THEN("There should be a symbol for processDoubleUpperBoundInterfaceGeneric") + WHEN("Parsing processReturnMultipleUpperBoundDifferent") { - const std::string func_name=".processDoubleUpperBoundInterfaceGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + THEN("There should be a symbol for the function") + { + const std::string func_name = ".processReturnMultipleUpperBoundDifferent"; + const std::string func_descriptor = ":(LGeneric;LGeneric;)LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt func_symbol = + new_symbol_table.lookup_ref(process_func_name); + const code_typet func_code = + require_type::require_code(func_symbol.type, 2); + + THEN("It contains parameter u pointing to Generic") + { + const code_typet::parametert ¶m_u = + require_type::require_parameter(func_code, "u"); + require_type::require_pointer( + param_u.type(), symbol_typet("java::Generic")); + + THEN("u is generic with type variable U") + { + require_type::require_java_generic_type( + param_u.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::U"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It contains parameter v pointing to Generic") + { + const code_typet::parametert ¶m_v = + require_type::require_parameter(func_code, "v"); + require_type::require_pointer( + param_v.type(), symbol_typet("java::Generic")); + + THEN("v is generic with type variable V") + { + require_type::require_java_generic_type( + param_v.type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::V"}}); + + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + + THEN("It has return type pointing to Generic") + { + require_type::require_pointer( + func_code.return_type(), symbol_typet("java::Generic")); + + THEN("It is generic with type variable T") + { + require_type::require_java_generic_type( + func_code.return_type(), + {{require_type::type_parameter_kindt::Var, class_prefix + "::T"}}); - REQUIRE(new_symbol_table.has_symbol(process_func_name)); + THEN("The bounds are set correctly") + { + // TODO: the bounds are not parsed yet; enable the tests when + // fixed - issue TG-1286 + } + } + } + } } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_inner_class.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_inner_class.cpp deleted file mode 100644 index acb09972a88..00000000000 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_inner_class.cpp +++ /dev/null @@ -1,935 +0,0 @@ -/*******************************************************************\ - - Module: Unit tests for parsing generic classes - - Author: DiffBlue Limited. All rights reserved. - -\*******************************************************************/ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -SCENARIO( - "Parse fields of inner classes on a generic class", - "[core][java_bytecode][java_bytecode_parse_generics]") -{ - const symbol_tablet &new_symbol_table = load_java_class( - "GenericClass", "./java_bytecode/java_bytecode_parse_generics"); - - std::string class_prefix = "java::GenericClass"; - THEN("There should be a symbol for GenericClass with correct components") - { - REQUIRE(new_symbol_table.has_symbol(class_prefix)); - const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); - - const class_typet &class_type = - require_symbol::require_complete_class(class_symbol); - - THEN("The field component should be a pointer to GenericClass$InnerClass") - { - const struct_typet::componentt &field_component = - require_type::require_component(class_type, "field"); - - require_type::require_pointer( - field_component.type(), symbol_typet("java::GenericClass$InnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(field_component.type())); - const auto &generic_variables = - to_java_generic_type(field_component.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 1); - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - - THEN("The field component should be a pointer to GenericClass$InnerClass") - { - const struct_typet::componentt &field_component = - require_type::require_component(class_type, "field2"); - - require_type::require_pointer( - field_component.type(), - symbol_typet("java::GenericClass$GenericInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(field_component.type())); - const auto &generic_variables = - to_java_generic_type(field_component.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - - THEN( - "The field component should be a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerClass") - { - const struct_typet::componentt &field_component = - require_type::require_component(class_type, "field4"); - - require_type::require_pointer( - field_component.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$DoublyNestedInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(field_component.type())); - const auto &generic_variables = - to_java_generic_type(field_component.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - - THEN( - "The field component should be a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerClass") - { - const struct_typet::componentt &field_component = - require_type::require_component(class_type, "field5"); - - require_type::require_pointer( - field_component.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$DoublyNestedInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(field_component.type())); - const auto &generic_variables = - to_java_generic_type(field_component.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - - THEN( - "The field component should be a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerGenericClass") - { - const struct_typet::componentt &field_component = - require_type::require_component(class_type, "field6"); - - require_type::require_pointer( - field_component.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$" - "DoublyNestedInnerGenericClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(field_component.type())); - const auto &generic_variables = - to_java_generic_type(field_component.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 3); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - { - const java_generic_parametert &generic_param = generic_variables[2]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - - THEN( - "The field component should be a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerGenericClass") - { - const struct_typet::componentt &field_component = - require_type::require_component(class_type, "field7"); - - require_type::require_pointer( - field_component.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$" - "DoublyNestedInnerGenericClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(field_component.type())); - const auto &generic_variables = - to_java_generic_type(field_component.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 3); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[2]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - } -} - -SCENARIO( - "Parse methods of generic classes using inner parameters", - "[core][java_bytecode][java_bytecode_parse_generics][caskjd]") -{ - const symbol_tablet &new_symbol_table = load_java_class( - "GenericClass", "./java_bytecode/java_bytecode_parse_generics"); - - std::string class_prefix = "java::GenericClass"; - - THEN("Method 1 should take a pointer to GenericClass$InnerClass") - { - const std::string func_name = ".method"; - const std::string func_descriptor = ":(LGenericClass$InnerClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), symbol_typet("java::GenericClass$InnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 1); - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE( - generic_param.type_variable() == symbol_typet("java::GenericClass::T")); - } - } - THEN("Method 2 should take two pointers to GenericClass$InnerClass") - { - const std::string func_name = ".method2"; - const std::string func_descriptor = - ":(LGenericClass$InnerClass;LGenericClass$InnerClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - // Check param input - { - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), symbol_typet("java::GenericClass$InnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 1); - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - - // Check param input2 - { - const auto param_type2 = - require_type::require_parameter(function_call, "input2"); - require_type::require_pointer( - param_type2.type(), symbol_typet("java::GenericClass$InnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type2.type())); - const auto &generic_variables = - to_java_generic_type(param_type2.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 1); - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - THEN("Method 3 should take a pointer to GenericClass$GenericInnerClass") - { - const std::string func_name = ".method3"; - const std::string func_descriptor = ":(LGenericClass$GenericInnerClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), symbol_typet("java::GenericClass$GenericInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - THEN("Method 4 should take a pointer to GenericClass$GenericInnerClass") - { - const std::string func_name = ".method4"; - const std::string func_descriptor = ":(LGenericClass$GenericInnerClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), symbol_typet("java::GenericClass$GenericInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - THEN( - "Method 5 should take a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerClass") - { - const std::string func_name = ".method5"; - const std::string func_descriptor = - ":(LGenericClass$GenericInnerClass$DoublyNestedInnerClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$DoublyNestedInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - THEN( - "Method 6 should take a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerClass") - { - const std::string func_name = ".method6"; - const std::string func_descriptor = - ":(LGenericClass$GenericInnerClass$DoublyNestedInnerClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$DoublyNestedInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - THEN( - "Method 7 should take a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerGenericClass") - { - const std::string func_name = ".method7"; - const std::string func_descriptor = - ":(LGenericClass$GenericInnerClass$DoublyNestedInnerGenericClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$" - "DoublyNestedInnerGenericClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 3); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - { - const java_generic_parametert &generic_param = generic_variables[2]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - THEN( - "Method 8 should take a pointer to " - "GenericClass$GenericInnerClass$DoublyNestedInnerGenericClass") - { - const std::string func_name = ".method8"; - const std::string func_descriptor = - ":(LGenericClass$GenericInnerClass$DoublyNestedInnerGenericClass;)V"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - const auto param_type = - require_type::require_parameter(function_call, "input"); - require_type::require_pointer( - param_type.type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$" - "DoublyNestedInnerGenericClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(param_type.type())); - const auto &generic_variables = - to_java_generic_type(param_type.type()).generic_type_variables(); - REQUIRE(generic_variables.size() == 3); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[2]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - THEN("Ret Method 1 should return a GenericClass$InnerClass") - { - const std::string func_name = ".ret_method1"; - const std::string func_descriptor = ":()LGenericClass$InnerClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet("java::GenericClass$InnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 1); - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE( - generic_param.type_variable() == symbol_typet("java::GenericClass::T")); - } - } - THEN("Ret method 2 should return a GenericClass$GenericInnerClass") - { - const std::string func_name = ".ret_method2"; - const std::string func_descriptor = ":()LGenericClass$GenericInnerClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet("java::GenericClass$GenericInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - THEN("Ret method 3 should return a GenericClass$GenericInnerClass") - { - const std::string func_name = ".ret_method3"; - const std::string func_descriptor = ":()LGenericClass$GenericInnerClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet("java::GenericClass$GenericInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - THEN( - "Ret method 4 should return a " - "GenericClass$GenericInnerClass$DoublyNestedInnerClass") - { - const std::string func_name = ".ret_method4"; - const std::string func_descriptor = - ":()LGenericClass$GenericInnerClass$DoublyNestedInnerClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$DoublyNestedInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - THEN( - "Ret method 5 should return a " - "GenericClass$GenericInnerClass$DoublyNestedInnerClass") - { - const std::string func_name = ".ret_method5"; - const std::string func_descriptor = - ":()LGenericClass$GenericInnerClass$DoublyNestedInnerClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$DoublyNestedInnerClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 2); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } - THEN( - "Ret method 6 should return a " - "GenericClass$GenericInnerClass$DoublyNestedInnerGenericClass") - { - const std::string func_name = ".ret_method6"; - const std::string func_descriptor = - ":()LGenericClass$GenericInnerClass$DoublyNestedInnerGenericClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$" - "DoublyNestedInnerGenericClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 3); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - { - const java_generic_parametert &generic_param = generic_variables[2]; - REQUIRE(is_java_generic_inst_parameter(generic_param)); - REQUIRE( - generic_param == - java_generic_inst_parametert(symbol_typet("java::Foo"))); - } - } - } - THEN( - "Ret method 7 should return a " - "GenericClass$GenericInnerClass$DoublyNestedInnerGenericClass") - { - const std::string func_name = ".ret_method7"; - const std::string func_descriptor = - ":()LGenericClass$GenericInnerClass$DoublyNestedInnerGenericClass;"; - const std::string process_func_name = - class_prefix + func_name + func_descriptor; - - REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const symbolt &function_symbol = - new_symbol_table.lookup_ref(process_func_name); - - const code_typet &function_call = - require_type::require_code(function_symbol.type); - - require_type::require_pointer( - function_call.return_type(), - symbol_typet( - "java::GenericClass$GenericInnerClass$" - "DoublyNestedInnerGenericClass")); - - THEN("The pointer should be generic") - { - REQUIRE(is_java_generic_type(function_call.return_type())); - const auto &generic_variables = - to_java_generic_type(function_call.return_type()) - .generic_type_variables(); - REQUIRE(generic_variables.size() == 3); - { - const java_generic_parametert &generic_param = generic_variables[0]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[1]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - { - const java_generic_parametert &generic_param = generic_variables[2]; - REQUIRE(is_java_generic_parameter(generic_param)); - REQUIRE( - generic_param.type_variable() == - symbol_typet("java::GenericClass::T")); - } - } - } -} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_wildcard_function.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_wildcard_function.cpp index b596572252c..bf4c0a66578 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_wildcard_function.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_generic_wildcard_function.cpp @@ -7,61 +7,59 @@ \*******************************************************************/ #include - -#include -#include -#include -#include - -#include - -#include #include SCENARIO( - "java_bytecode_parse_generic_wildcard", + "parse_generic_wildcard", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class( - "WildcardGenericFunctions", - "./java_bytecode/java_bytecode_parse_generics"); + const symbol_tablet &new_symbol_table = load_java_class( + "WildcardGenericFunctions", "./java_bytecode/java_bytecode_parse_generics"); - std::string class_prefix="java::WildcardGenericFunctions"; + std::string class_prefix = "java::WildcardGenericFunctions"; THEN("There should be a symbol for processSimpleGeneric") { - const std::string func_name=".processSimpleGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + const std::string func_name = ".processSimpleGeneric"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; REQUIRE(new_symbol_table.has_symbol(process_func_name)); + // TODO extend tests when wildcards are parsed correctly - TG-675 } THEN("There should be a symbol for processUpperBoundInterfaceGeneric") { - const std::string func_name=".processUpperBoundInterfaceGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + const std::string func_name = ".processUpperBoundInterfaceGeneric"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; REQUIRE(new_symbol_table.has_symbol(process_func_name)); + // TODO extend tests when wildcards are parsed correctly - TG-675 } THEN("There should be a symbol for processUpperBoundClassGeneric") { - const std::string func_name=".processUpperBoundClassGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + const std::string func_name = ".processUpperBoundClassGeneric"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; REQUIRE(new_symbol_table.has_symbol(process_func_name)); + // TODO extend tests when wildcards are parsed correctly - TG-675 } THEN("There should be a symbol for processLowerBoundGeneric") { - const std::string func_name=".processLowerBoundGeneric"; - const std::string func_descriptor=":(LSimpleGeneric;LFoo;)V"; - const std::string process_func_name=class_prefix+func_name+func_descriptor; + const std::string func_name = ".processLowerBoundGeneric"; + const std::string func_descriptor = + ":(LGeneric;LInterface_Implementation;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; REQUIRE(new_symbol_table.has_symbol(process_func_name)); + // TODO extend tests when wildcards are parsed correctly - TG-675 } } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_nested_generics.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_nested_generics.cpp new file mode 100644 index 00000000000..17441a81dd9 --- /dev/null +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_nested_generics.cpp @@ -0,0 +1,1138 @@ +/*******************************************************************\ + + Module: Unit tests for parsing generic classes + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include + +SCENARIO( + "parse_nested_generics_fields", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "NestedGenerics", "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::NestedGenerics"; + THEN("There should be a symbol for NestedGenerics with correct components") + { + REQUIRE(new_symbol_table.has_symbol(class_prefix)); + const symbolt &class_symbol = new_symbol_table.lookup_ref(class_prefix); + + const class_typet &class_type = + require_type::require_java_non_generic_class(class_symbol.type); + + THEN("The field component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field2 component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field2"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field3 component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field3"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field4 component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field4"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field5 component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field5"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field6 component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field6"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field7 component should be a pointer to java::Generic") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field7"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field8 component should be a pointer to java::GenericTwoParam") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field8"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field9 component should be a pointer to java::GenericTwoParam") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field9"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field10 component should be a pointer to java::GenericTwoParam") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field10"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field11 component should be a pointer to java::GenericTwoParam") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field11"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field12 component should be a pointer to java::GenericTwoParam") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field12"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + + THEN("The field13 component should be a pointer to java::GenericTwoParam") + { + const struct_typet::componentt &field_component = + require_type::require_component(class_type, "field13"); + require_type::require_pointer( + field_component.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + field_component.type(), + {{require_type::type_parameter_kindt::Inst, "java::GenericTwoParam"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - + // issue TG-1301 + } + } + } +} + +SCENARIO( + "parse_nested_generics_methods", + "[core][java_bytecode][java_bytecode_parse_generics]") +{ + const symbol_tablet &new_symbol_table = load_java_class( + "NestedGenerics", "./java_bytecode/java_bytecode_parse_generics"); + + std::string class_prefix = "java::NestedGenerics"; + + THEN("Method 1 should take a pointer to java::Generic") + { + const std::string func_name = ".method"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 2 should take a pointer to java::Generic") + { + const std::string func_name = ".method2"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of oorrect type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 3 should take a pointer to java::Generic") + { + const std::string func_name = ".method3"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 4 should take a pointer to java::Generic") + { + const std::string func_name = ".method4"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 5 should take a pointer to java::Generic") + { + const std::string func_name = ".method5"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs are of correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 6 should take a pointer to java::Generic") + { + const std::string func_name = ".method6"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 7 should take a pointer to java::Generic") + { + const std::string func_name = ".method7"; + const std::string func_descriptor = ":(LGeneric;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 8 should take a pointer to java::GenericTwoParam") + { + const std::string func_name = ".method8"; + const std::string func_descriptor = ":(LGenericTwoParam;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 9 should take a pointer to java::GenericTwoParam") + { + const std::string func_name = ".method9"; + const std::string func_descriptor = ":(LGenericTwoParam;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 10 should take a pointer to java::GenericTwoParam") + { + const std::string func_name = ".method10"; + const std::string func_descriptor = ":(LGenericTwoParam;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 11 should take a pointer to java::GenericTwoParam") + { + const std::string func_name = ".method11"; + const std::string func_descriptor = ":(LGenericTwoParam;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 12 should take a pointer to java::GenericTwoParam") + { + const std::string func_name = ".method12"; + const std::string func_descriptor = ":(LGenericTwoParam;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Method 13 should take a pointer to java::GenericTwoParam") + { + const std::string func_name = ".method13"; + const std::string func_descriptor = ":(LGenericTwoParam;)V"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 2); + + THEN("The inputs have correct type") + { + const auto ¶m_type = + require_type::require_parameter(function_call, "input"); + require_type::require_pointer( + param_type.type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + param_type.type(), + {{require_type::type_parameter_kindt::Inst, "java::GenericTwoParam"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 1 should return a java::Generic") + { + const std::string func_name = ".ret_method"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 2 should return a java::Generic") + { + const std::string func_name = ".ret_method2"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 3 should return a java::Generic") + { + const std::string func_name = ".ret_method3"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 4 should return a java::Generic") + { + const std::string func_name = ".ret_method4"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 5 should return a java::Generic") + { + const std::string func_name = ".ret_method5"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 6 should return a java::Generic") + { + const std::string func_name = ".ret_method6"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 7 should return a java::Generic") + { + const std::string func_name = ".ret_method7"; + const std::string func_descriptor = ":()LGeneric;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::Generic")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, + "java::GenericTwoParam"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 8 should return a java::GenericTwoParam") + { + const std::string func_name = ".ret_method8"; + const std::string func_descriptor = ":()LGenericTwoParam;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 9 should return a java::GenericTwoParam") + { + const std::string func_name = ".ret_method9"; + const std::string func_descriptor = ":()LGenericTwoParam;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 10 should return a java::GenericTwoParam") + { + const std::string func_name = ".ret_method10"; + const std::string func_descriptor = ":()LGenericTwoParam;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::Generic"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 11 should return a java::GenericTwoParam") + { + const std::string func_name = ".ret_method11"; + const std::string func_descriptor = ":()LGenericTwoParam;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 12 should return a java::GenericTwoParam") + { + const std::string func_name = ".ret_method12"; + const std::string func_descriptor = ":()LGenericTwoParam;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, + "java::Generic"}, + {require_type::type_parameter_kindt::Inst, + "java::Interface_Implementation"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } + + THEN("Ret Method 13 should return a java::GenericTwoParam") + { + const std::string func_name = ".ret_method13"; + const std::string func_descriptor = ":()LGenericTwoParam;"; + const std::string process_func_name = + class_prefix + func_name + func_descriptor; + + REQUIRE(new_symbol_table.has_symbol(process_func_name)); + const symbolt &function_symbol = + new_symbol_table.lookup_ref(process_func_name); + + const code_typet &function_call = + require_type::require_code(function_symbol.type, 1); + + THEN("The return type is correct") + { + require_type::require_pointer( + function_call.return_type(), symbol_typet("java::GenericTwoParam")); + + THEN("The pointer should be generic") + { + require_type::require_java_generic_type( + function_call.return_type(), + {{require_type::type_parameter_kindt::Inst, "java::GenericTwoParam"}, + {require_type::type_parameter_kindt::Inst, "java::Generic"}}); + + // TODO: extend tests when nested generics are parsed correctly - issue + // TG-1301 + } + } + } +} diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_recursive_generic_class.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_recursive_generic_class.cpp index f20de637e5c..a9e888bb800 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_recursive_generic_class.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_recursive_generic_class.cpp @@ -7,30 +7,20 @@ \*******************************************************************/ #include - -#include -#include -#include -#include - -#include #include -#include -#include - SCENARIO( - "java_bytecode_parse_recursive_generic_class", + "parse_recursive_generic_class", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class("RecursiveGeneric", "" - "./java_bytecode/java_bytecode_parse_generics"); + const symbol_tablet &new_symbol_table = load_java_class( + "RecursiveGeneric", + "./java_bytecode/java_bytecode_parse_generics"); - std::string class_prefix="java::RecursiveGeneric"; + std::string class_prefix = "java::RecursiveGeneric"; REQUIRE(new_symbol_table.has_symbol(class_prefix)); // TODO: Extend this unit test when recursive generic types are correctly - // parsed. + // parsed - issue TG-1305 } diff --git a/unit/java_bytecode/java_bytecode_parse_generics/parse_signature_descriptor_mismatch.cpp b/unit/java_bytecode/java_bytecode_parse_generics/parse_signature_descriptor_mismatch.cpp index 40288e62cc4..cb6b6289502 100644 --- a/unit/java_bytecode/java_bytecode_parse_generics/parse_signature_descriptor_mismatch.cpp +++ b/unit/java_bytecode/java_bytecode_parse_generics/parse_signature_descriptor_mismatch.cpp @@ -7,74 +7,87 @@ \*******************************************************************/ #include - -#include - -#include -#include -#include -#include #include -#include +#include SCENARIO( - "java_bytecode_parse_signature_descriptor_mismatch", + "parse_signature_descriptor_mismatch", "[core][java_bytecode][java_bytecode_parse_generics]") { - const symbol_tablet &new_symbol_table= - load_java_class( - "Outer", - "./java_bytecode/java_bytecode_parse_generics"); + const symbol_tablet &new_symbol_table = load_java_class( + "SignatureDescriptorMismatch", + "./java_bytecode/java_bytecode_parse_generics"); - const std::string class_prefix="java::Outer"; + const std::string class_prefix = "java::SignatureDescriptorMismatch"; REQUIRE(new_symbol_table.has_symbol(class_prefix)); - const std::string inner_prefix=class_prefix+"$Inner"; + const std::string inner_prefix = class_prefix + "$Inner"; THEN("There is a (complete) symbol for the inner class Inner") { REQUIRE(new_symbol_table.has_symbol(inner_prefix)); - const symbolt &inner_symbol=new_symbol_table.lookup_ref(inner_prefix); - const class_typet &inner_class_type= - require_symbol::require_complete_class(inner_symbol); + const symbolt &inner_symbol = new_symbol_table.lookup_ref(inner_prefix); + const class_typet &inner_class_type = + require_type::require_java_non_generic_class(inner_symbol.type); } - THEN("There is a symbol for the constructor of the inner class with correct" - " descriptor") + THEN( + "There is a symbol for the constructor of the class Inner with " + "the correct number of parameters") { - const std::string func_name="."; - const std::string func_descriptor=":(LOuter;LAbstractGenericClass;)V"; - const std::string process_func_name= - inner_prefix+func_name+func_descriptor; + const std::string func_name = "."; + const std::string func_descriptor = + ":(LSignatureDescriptorMismatch;LAbstractGeneric;)V"; + const std::string process_func_name = + inner_prefix + func_name + func_descriptor; REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const code_typet func_code= + const code_typet func_code = to_code_type(new_symbol_table.lookup_ref(process_func_name).type); - REQUIRE(func_code.parameters().size()==3); + REQUIRE(func_code.parameters().size() == 3); + + // TODO: for now, the parameters are not generic because we fall back to + // descriptor due to mismatch; enable tests when fixed - issue TG-1309 + // code_typet::parametert param_parent= + // require_type::require_parameter(func_code,"arg1a"); + // REQUIRE(is_java_generic_type(param_parent.type())); + // code_typet::parametert param_t= + // require_type::require_parameter(func_code,"t"); + // REQUIRE(is_java_generic_type(param_t.type())); } - const std::string inner_enum_prefix=class_prefix+"$InnerEnum"; + const std::string inner_enum_prefix = class_prefix + "$InnerEnum"; THEN("There is a (complete) symbol for the inner enum InnerEnum") { REQUIRE(new_symbol_table.has_symbol(inner_enum_prefix)); - const symbolt &inner_enum_symbol= + const symbolt &inner_enum_symbol = new_symbol_table.lookup_ref(inner_enum_prefix); - const class_typet &inner_enum_class_type= - require_symbol::require_complete_class(inner_enum_symbol); + const class_typet &inner_enum_class_type = + require_type::require_java_non_generic_class(inner_enum_symbol.type); } - THEN("There is a symbol for the constructor of the inner enum with correct" - " number of parameters") + THEN( + "There is a symbol for the constructor of the inner enum with the " + "correct number of parameters") { - const std::string func_name="."; - const std::string func_descriptor=":(Ljava/lang/String;I)V"; - const std::string process_func_name= - inner_enum_prefix+func_name+func_descriptor; + const std::string func_name = "."; + const std::string func_descriptor = ":(Ljava/lang/String;I)V"; + const std::string process_func_name = + inner_enum_prefix + func_name + func_descriptor; REQUIRE(new_symbol_table.has_symbol(process_func_name)); - const code_typet func_code= + const code_typet func_code = to_code_type(new_symbol_table.lookup_ref(process_func_name).type); - REQUIRE(func_code.parameters().size()==3); + REQUIRE(func_code.parameters().size() == 3); + + // TODO: for now, the parameters are not generic because we fall back to + // descriptor due to mismatch; enable tests when fixed - issue TG-1309 + // code_typet::parametert param_parent= + // require_type::require_parameter(func_code,"arg1a"); + // REQUIRE(is_java_generic_type(param_parent.type())); + // code_typet::parametert param_t= + // require_type::require_parameter(func_code,"arg2i"); + // REQUIRE(is_java_generic_type(param_t.type())); } } diff --git a/unit/testing-utils/Makefile b/unit/testing-utils/Makefile index f211e7eb832..45ccd69ec7b 100644 --- a/unit/testing-utils/Makefile +++ b/unit/testing-utils/Makefile @@ -3,7 +3,6 @@ SRC = \ load_java_class.cpp \ require_expr.cpp \ require_goto_statements.cpp \ - require_symbol.cpp \ require_type.cpp \ # Empty last line (please keep above list sorted!) diff --git a/unit/testing-utils/require_symbol.cpp b/unit/testing-utils/require_symbol.cpp deleted file mode 100644 index e291017c5cc..00000000000 --- a/unit/testing-utils/require_symbol.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*******************************************************************\ - - Module: Unit test utilities - - Author: DiffBlue Limited. All rights reserved. - -\*******************************************************************/ - -/// \file -/// Helper functions for requiring properties of symbols - -#include "require_symbol.h" - -#include - -const class_typet &require_symbol::require_complete_class( - const symbolt &class_symbol) -{ - REQUIRE(class_symbol.is_type); - - const typet &class_symbol_type=class_symbol.type; - REQUIRE(class_symbol_type.id()==ID_struct); - - const class_typet &class_class_type=to_class_type(class_symbol_type); - REQUIRE(class_class_type.is_class()); - REQUIRE_FALSE(class_class_type.get_bool(ID_incomplete_class)); - - return class_class_type; -} diff --git a/unit/testing-utils/require_symbol.h b/unit/testing-utils/require_symbol.h deleted file mode 100644 index c8d1e636e65..00000000000 --- a/unit/testing-utils/require_symbol.h +++ /dev/null @@ -1,25 +0,0 @@ -/*******************************************************************\ - - Module: Unit test utilities - - Author: DiffBlue Limited. All rights reserved. - -\*******************************************************************/ - -/// \file -/// Helper functions for requiring properties of symbols - -#include -#include - -#ifndef CPROVER_TESTING_UTILS_REQUIRE_SYMBOL_H -#define CPROVER_TESTING_UTILS_REQUIRE_SYMBOL_H - -// NOLINTNEXTLINE(readability/namespace) -namespace require_symbol -{ - const class_typet &require_complete_class( - const symbolt &class_symbol); -} - -#endif // CPROVER_TESTING_UTILS_REQUIRE_SYMBOL_H diff --git a/unit/testing-utils/require_type.cpp b/unit/testing-utils/require_type.cpp index 9d8233a52d8..78b51b53762 100644 --- a/unit/testing-utils/require_type.cpp +++ b/unit/testing-utils/require_type.cpp @@ -65,12 +65,11 @@ code_typet require_type::require_code(const typet &type) /// \param num_params check the the given code_typet expects this /// number of parameters /// \return The type cast to a code_typet -code_typet require_type::require_code( - const typet &type, - const size_t num_params) +code_typet +require_type::require_code(const typet &type, const size_t num_params) { - code_typet code_type=require_code(type); - REQUIRE(code_type.parameters().size()==num_params); + code_typet code_type = require_code(type); + REQUIRE(code_type.parameters().size() == num_params); return code_type; } @@ -105,82 +104,98 @@ bool require_java_generic_parametert_expectation( { switch(expected.kind) { - case require_type::type_parameter_kindt::Var: - REQUIRE(!is_java_generic_inst_parameter((param))); - REQUIRE(param.type_variable().get_identifier()==expected.description); - return true; - case require_type::type_parameter_kindt::Inst: - REQUIRE(is_java_generic_inst_parameter((param))); - REQUIRE(param.subtype()==symbol_typet(expected.description)); - return true; + case require_type::type_parameter_kindt::Var: + REQUIRE(!is_java_generic_inst_parameter((param))); + REQUIRE(param.type_variable().get_identifier() == expected.description); + return true; + case require_type::type_parameter_kindt::Inst: + REQUIRE(is_java_generic_inst_parameter((param))); + REQUIRE(param.subtype() == symbol_typet(expected.description)); + return true; } // Should be unreachable... REQUIRE(false); return false; } +/// Verify a given type is a java_generic_type +/// \param type The type to check +/// \return The type, cast to a java_generic_typet +java_generic_typet require_type::require_java_generic_type(const typet &type) +{ + REQUIRE(is_java_generic_type(type)); + return to_java_generic_type(type); +} -/// Verify a given type is a java_generic_type, optionally checking +/// Verify a given type is a java_generic_type, checking /// that it's associated type variables match a given set of identifiers. /// Expected usage is something like this: /// /// require_java_generic_type(type, -/// {{Inst,"java::java.lang.Integer"},{Var,"T"}}) +/// {{require_type::type_parameter_kindt::Inst, "java::java.lang.Integer"}, +/// {require_type::type_parameter_kindt::Var, "T"}}) /// /// \param type The type to check -/// \param type_expectations An optional set of type variable kinds +/// \param type_expectations A set of type variable kinds /// and identifiers which should be expected as the type parameters of the /// given generic type. /// \return The given type, cast to a java_generic_typet java_generic_typet require_type::require_java_generic_type( const typet &type, - const optionalt &type_expectations) + const require_type::expected_type_parameterst &type_expectations) { - REQUIRE(is_java_generic_type(type)); - const java_generic_typet &generic_type=to_java_generic_type(type); - if(type_expectations) - { - const java_generic_typet::generic_type_variablest &generic_type_vars= - generic_type.generic_type_variables(); - REQUIRE(generic_type_vars.size()==type_expectations->size()); - REQUIRE( - std::equal( - generic_type_vars.begin(), - generic_type_vars.end(), - type_expectations->begin(), - require_java_generic_parametert_expectation)); - } + const java_generic_typet &generic_type = + require_type::require_java_generic_type(type); + + const java_generic_typet::generic_type_variablest &generic_type_vars = + generic_type.generic_type_variables(); + REQUIRE(generic_type_vars.size() == type_expectations.size()); + REQUIRE( + std::equal( + generic_type_vars.begin(), + generic_type_vars.end(), + type_expectations.begin(), + require_java_generic_parametert_expectation)); return generic_type; } -/// Verify a given type is a java_generic_parameter, optionally checking +/// Verify a given type is a java_generic_parameter +/// \param type The type to check +/// \return The type, cast to a java_generic_parametert +java_generic_parametert +require_type::require_java_generic_parameter(const typet &type) +{ + REQUIRE(is_java_generic_parameter(type)); + return to_java_generic_parameter(type); +} + +/// Verify a given type is a java_generic_parameter, checking /// that it's associated type variables match a given set of expectations. /// Expected usage is something like this: /// -/// require_java_generic_parameter(parameter, {Inst,"java::java.lang.Integer"}) +/// require_java_generic_parameter(parameter, +/// {require_type::type_parameter_kindt::Inst,"java::java.lang.Integer"}) /// /// or /// -/// require_java_generic_parameter(parameter, {Var,"T"}) +/// require_java_generic_parameter(parameter, +/// {require_type::type_parameter_kindt::Var,"T"}) /// /// \param type The type to check -/// \param type_expectation An optional description of the identifiers/kinds +/// \param type_expectation A description of the identifiers/kinds /// which / should be expected as the type parameter of the generic parameter. /// \return The given type, cast to a java_generic_parametert java_generic_parametert require_type::require_java_generic_parameter( const typet &type, - const optionalt &type_expectation) + const require_type::expected_type_parametert &type_expectation) { - REQUIRE(is_java_generic_parameter(type)); - const java_generic_parametert &generic_param=to_java_generic_parameter(type); - if(type_expectation) - { - REQUIRE( - require_java_generic_parametert_expectation( - generic_param, - type_expectation.value())); - } + const java_generic_parametert &generic_param = + require_type::require_java_generic_parameter(type); + + REQUIRE( + require_java_generic_parametert_expectation( + generic_param, type_expectation)); return generic_param; } @@ -198,6 +213,79 @@ const typet &require_type::require_java_non_generic_type( REQUIRE(!is_java_generic_type(type)); REQUIRE(!is_java_generic_inst_parameter(type)); if(expect_subtype) - REQUIRE(type.subtype()==expect_subtype.value()); + REQUIRE(type.subtype() == expect_subtype.value()); return type; } + +/// Checks that the given type is a complete class. +/// \param class_type type of the class +/// \return class_type of the class +class_typet require_complete_class(const typet &class_type) +{ + REQUIRE(class_type.id() == ID_struct); + + const class_typet &class_class_type = to_class_type(class_type); + REQUIRE(class_class_type.is_class()); + REQUIRE_FALSE(class_class_type.get_bool(ID_incomplete_class)); + + return class_class_type; +} + +/// Verify that a class is a complete, valid java generic class. +/// \param class_type: the class +/// \return: A reference to the java generic class type. +java_generics_class_typet +require_type::require_java_generic_class(const typet &class_type) +{ + const class_typet &class_class_type = require_complete_class(class_type); + java_class_typet java_class_type = to_java_class_type(class_class_type); + + REQUIRE(is_java_generics_class_type(java_class_type)); + java_generics_class_typet java_generic_class_type = + to_java_generics_class_type(java_class_type); + + return java_generic_class_type; +} + +/// Verify that a class is a complete, valid java generic class with the +/// specified list of variables. +/// \param class_type: the class +/// \param type_variables: vector of type variables +/// \return: A reference to the java generic class type. +java_generics_class_typet require_type::require_java_generic_class( + const typet &class_type, + const std::initializer_list &type_variables) +{ + const java_generics_class_typet java_generic_class_type = + require_type::require_java_generic_class(class_type); + + const java_generics_class_typet::generic_typest &generic_type_vars = + java_generic_class_type.generic_types(); + REQUIRE(generic_type_vars.size() == type_variables.size()); + REQUIRE( + std::equal( + type_variables.begin(), + type_variables.end(), + generic_type_vars.begin(), + [](const irep_idt &type_var_name, const java_generic_parametert ¶m) + { + REQUIRE(!is_java_generic_inst_parameter((param))); + return param.type_variable().get_identifier() == type_var_name; + })); + + return java_generic_class_type; +} + +/// Verify that a class is a complete, valid nongeneric java class +/// \param class_type: the class +/// \return: A reference to the java generic class type. +java_class_typet +require_type::require_java_non_generic_class(const typet &class_type) +{ + const class_typet &class_class_type = require_complete_class(class_type); + java_class_typet java_class_type = to_java_class_type(class_class_type); + + REQUIRE(!is_java_generics_class_type(java_class_type)); + + return java_class_type; +} diff --git a/unit/testing-utils/require_type.h b/unit/testing-utils/require_type.h index 215f5335cf0..6d61f7d325b 100644 --- a/unit/testing-utils/require_type.h +++ b/unit/testing-utils/require_type.h @@ -19,7 +19,6 @@ #include #include - // NOLINTNEXTLINE(readability/namespace) namespace require_type { @@ -35,13 +34,15 @@ code_typet require_code(const typet &type); code_typet::parametert require_parameter(const code_typet &function_type, const irep_idt ¶m_name); -code_typet require_code( - const typet &type, - const size_t num_params); +code_typet require_code(const typet &type, const size_t num_params); // A mini DSL for describing an expected set of type parameters for a // java_generic_typet -enum class type_parameter_kindt { Inst, Var }; +enum class type_parameter_kindt +{ + Inst, + Var +}; struct expected_type_parametert { type_parameter_kindt kind; @@ -50,18 +51,29 @@ struct expected_type_parametert typedef std::initializer_list expected_type_parameterst; +java_generic_typet require_java_generic_type(const typet &type); + java_generic_typet require_java_generic_type( const typet &type, - const optionalt &type_expectations); + const require_type::expected_type_parameterst &type_expectations); +java_generic_parametert require_java_generic_parameter(const typet &type); java_generic_parametert require_java_generic_parameter( const typet &type, - const optionalt &type_expectation); + const require_type::expected_type_parametert &type_expectation); const typet &require_java_non_generic_type( const typet &type, const optionalt &expect_subtype); + +java_generics_class_typet require_java_generic_class(const typet &class_type); + +java_generics_class_typet require_java_generic_class( + const typet &class_type, + const std::initializer_list &type_variables); + +java_class_typet require_java_non_generic_class(const typet &class_type); } #endif // CPROVER_TESTING_UTILS_REQUIRE_TYPE_H