OSDN Git Service

Abstract methods aren't implementations.
authorElliott Hughes <enh@google.com>
Sat, 23 Feb 2013 01:04:54 +0000 (17:04 -0800)
committerElliott Hughes <enh@google.com>
Sat, 23 Feb 2013 01:04:54 +0000 (17:04 -0800)
We should only be checking the visibility of actual implementations
of interface methods. Intervening abstract methods are allowed to
be non-public.

Bug: https://code.google.com/p/android/issues/detail?id=42991
Change-Id: I510d0cc6c1f89d161d4ebad7ef058c03fa09e9b0

tests/301-abstract-protected/expected.txt [new file with mode: 0644]
tests/301-abstract-protected/info.txt [new file with mode: 0644]
tests/301-abstract-protected/src/Main.java [new file with mode: 0644]
vm/oo/Class.cpp

diff --git a/tests/301-abstract-protected/expected.txt b/tests/301-abstract-protected/expected.txt
new file mode 100644 (file)
index 0000000..b0aad4d
--- /dev/null
@@ -0,0 +1 @@
+passed
diff --git a/tests/301-abstract-protected/info.txt b/tests/301-abstract-protected/info.txt
new file mode 100644 (file)
index 0000000..0751eff
--- /dev/null
@@ -0,0 +1,3 @@
+Tests a dalvik bug where we'd treat an abstract method as an implementation
+of an interface method; the RI only cares about the visibility of the actual
+implementation in non-abstract subclasses.
diff --git a/tests/301-abstract-protected/src/Main.java b/tests/301-abstract-protected/src/Main.java
new file mode 100644 (file)
index 0000000..9b19a9d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static void main(String args[]) throws Exception {
+    System.err.println(new C().m());
+  }
+}
+
+// An arbitrary interface.
+interface I { public String m(); }
+
+// This is I-like, but doesn't actually claim to implement I.
+abstract class Abstract { protected abstract String m(); }
+
+// This claims to implement I, but the inherited m isn't sufficiently visible.
+abstract class AbstractI extends Abstract implements I { }
+
+// This has a concrete m that's sufficiently visible, so all should be good.
+class C extends AbstractI { public String m() { return "passed"; }; }
index 85ac9a7..78a2273 100644 (file)
@@ -3232,7 +3232,9 @@ static bool createIftable(ClassObject* clazz)
                     == 0)
                 {
                     LOGVV("INTF:   matched at %d", j);
-                    if (!dvmIsPublicMethod(clazz->vtable[j])) {
+                    if (!dvmIsAbstractMethod(clazz->vtable[j]) &&
+                        !dvmIsPublicMethod(clazz->vtable[j]))
+                    {
                         ALOGW("Implementation of %s.%s is not public",
                             clazz->descriptor, clazz->vtable[j]->name);
                         dvmThrowIllegalAccessError(