Fix incorrect IncompatibleClassChangeError in ClassInfo.getDefaultMethod (#7)
authorDan Smith <dsmith@pivotal.io>
Thu, 17 May 2018 06:15:26 +0000 (23:15 -0700)
committercyrille-artho <cyrille-artho@users.noreply.github.com>
Thu, 17 May 2018 06:15:26 +0000 (15:15 +0900)
The logic to detect if there are two conflicting default methods was incorrect.
If a class and its superclass both implement the same interface JPF should not
throw an IncompatibleClassChangeError.

src/main/gov/nasa/jpf/vm/ClassInfo.java
src/tests/gov/nasa/jpf/test/vm/basic/MethodTest.java

index d26abeda060b94d8053569a4a392188c26245035..d9e5331835833c8f8e7635daf78b2f584eca2de3 100644 (file)
@@ -1095,7 +1095,7 @@ public class ClassInfo extends InfoObject implements Iterable<MethodInfo>, Gener
       for (ClassInfo ciIfc : ci.interfaces){
         MethodInfo miIfc = ciIfc.getMethod(uniqueName, true);
         if (miIfc != null && !miIfc.isAbstract()){
       for (ClassInfo ciIfc : ci.interfaces){
         MethodInfo miIfc = ciIfc.getMethod(uniqueName, true);
         if (miIfc != null && !miIfc.isAbstract()){
-          if (mi != null){
+          if (mi != null && !mi.equals(miIfc)){
             // this has to throw a IncompatibleClassChangeError in the client since Java prohibits ambiguous default methods
             String msg = "Conflicting default methods: " + mi.getFullName() + ", " + miIfc.getFullName();
             throw new ClassChangeException(msg);
             // this has to throw a IncompatibleClassChangeError in the client since Java prohibits ambiguous default methods
             String msg = "Conflicting default methods: " + mi.getFullName() + ", " + miIfc.getFullName();
             throw new ClassChangeException(msg);
index 76e114ebeac0182924a70a26da70d5254eb902f3..24a05aeca90d20cb0b1dec54d610cb6052e8e891 100644 (file)
@@ -255,4 +255,24 @@ public class MethodTest extends TestMethodBase {
       assert a.foo() == 1 : "wrong A.foo() called for A1";
     }
   }
       assert a.foo() == 1 : "wrong A.foo() called for A1";
     }
   }
+
+
+  interface InterfaceWithDefaultMethod {
+    default int foo() {
+      return 42;
+    }
+  }
+
+  static class Base implements InterfaceWithDefaultMethod {
+  }
+
+  static class Child extends Base implements InterfaceWithDefaultMethod {
+  }
+
+  @Test
+  public void testDefaultMethodCall() {
+    if (verifyNoPropertyViolation()) {
+      assertEquals(42, new Child().foo());
+    }
+  }
 }
 }