ART: Reload class on miranda method in verifier

When checking the receiver of a call and we have a miranda method,
reload the class from the method index instead of using the declared
class - which is the interface class, not the abstract class.

Bug: 21646347
Change-Id: I5bceab75c3b76233cb42ea5cf0214d32c8149994
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9faaa4a..4d88227 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3318,7 +3318,10 @@
     }
     if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
       const RegType* res_method_class;
-      if (res_method != nullptr) {
+      // Miranda methods have the declaring interface as their declaring class, not the abstract
+      // class. It would be wrong to use this for the type check (interface type checks are
+      // postponed to runtime).
+      if (res_method != nullptr && !res_method->IsMiranda()) {
         mirror::Class* klass = res_method->GetDeclaringClass();
         std::string temp;
         res_method_class = &reg_types_.FromClass(klass->GetDescriptor(&temp), klass,
diff --git a/test/135-MirandaDispatch/expected.txt b/test/135-MirandaDispatch/expected.txt
index 134d8d0..5b098e5 100644
--- a/test/135-MirandaDispatch/expected.txt
+++ b/test/135-MirandaDispatch/expected.txt
@@ -1 +1,2 @@
+b/21646347
 Finishing
diff --git a/test/135-MirandaDispatch/smali/b_21646347.smali b/test/135-MirandaDispatch/smali/b_21646347.smali
new file mode 100644
index 0000000..b4979a5
--- /dev/null
+++ b/test/135-MirandaDispatch/smali/b_21646347.smali
@@ -0,0 +1,15 @@
+.class public LB21646347;
+
+# If an invoke-virtual dispatches to a miranda method, ensure that we test for the receiver
+# being a subclass of the abstract class, not postpone the check because the miranda method's
+# declaring class is an interface.
+
+.super Ljava/lang/Object;
+
+.method public static run(LB21646347;)V
+    .registers 1
+    # Invoke the miranda method on an object of this class. This should fail type-checking,
+    # instead of letting this pass as the declaring class is an interface.
+    invoke-virtual {v0}, LMain$AbstractClass;->m()V
+    return-void
+.end method
diff --git a/test/135-MirandaDispatch/src/Main.java b/test/135-MirandaDispatch/src/Main.java
index bb005b0..ada8cef 100644
--- a/test/135-MirandaDispatch/src/Main.java
+++ b/test/135-MirandaDispatch/src/Main.java
@@ -46,6 +46,15 @@
         if (counter != loopIterations * loopIterations) {
           System.out.println("Expected " + loopIterations * loopIterations + " got " + counter);
         }
+
+        try {
+            Class<?> b21646347 = Class.forName("B21646347");
+            throw new RuntimeException("Expected a VerifyError");
+        } catch (VerifyError expected) {
+            System.out.println("b/21646347");
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
         System.out.println("Finishing");
     }
 }