diff options
author | 2022-07-07 18:14:15 +0000 | |
---|---|---|
committer | 2022-07-07 18:14:15 +0000 | |
commit | e4feb40fc359d353f2a9c61d9a53e02df30a88d8 (patch) | |
tree | 123110d1ca0cb41b1609901d155b0737f5317840 | |
parent | 9ca36b31c995b24054202f8121e469392182cffa (diff) | |
parent | 385e5df0ca2a739a4bdbe2ab364ce71adfa00bff (diff) |
Fix one edge case at method linking to throw at runtime. am: d88c1499ef am: 8bc8a6b5b6 am: 3c3a870149 am: ffbdfeec4c am: 385e5df0ca
Original change: https://android-review.googlesource.com/c/platform/art/+/2146626
Change-Id: I5666fdec77e93e5746722354d8bd743d379bfe46
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
24 files changed, 499 insertions, 61 deletions
diff --git a/runtime/art_method.cc b/runtime/art_method.cc index cef9d7b9bd..71f08e7b4d 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -150,10 +150,34 @@ uint16_t ArtMethod::FindObsoleteDexClassDefIndex() { return dex_file->GetIndexForClassDef(*class_def); } -void ArtMethod::ThrowInvocationTimeError() { +void ArtMethod::ThrowInvocationTimeError(ObjPtr<mirror::Object> receiver) { DCHECK(!IsInvokable()); if (IsDefaultConflicting()) { ThrowIncompatibleClassChangeErrorForMethodConflict(this); + } else if (GetDeclaringClass()->IsInterface() && receiver != nullptr) { + // If this was an interface call, check whether there is a method in the + // superclass chain that isn't public. In this situation, we should throw an + // IllegalAccessError. + DCHECK(IsAbstract()); + ObjPtr<mirror::Class> current = receiver->GetClass(); + while (current != nullptr) { + for (ArtMethod& method : current->GetDeclaredMethodsSlice(kRuntimePointerSize)) { + ArtMethod* np_method = method.GetInterfaceMethodIfProxy(kRuntimePointerSize); + if (!np_method->IsStatic() && + np_method->GetNameView() == GetNameView() && + np_method->GetSignature() == GetSignature()) { + if (!np_method->IsPublic()) { + ThrowIllegalAccessErrorForImplementingMethod(receiver->GetClass(), np_method, this); + return; + } else if (np_method->IsAbstract()) { + ThrowAbstractMethodError(this); + return; + } + } + } + current = current->GetSuperClass(); + } + ThrowAbstractMethodError(this); } else { DCHECK(IsAbstract()); ThrowAbstractMethodError(this); diff --git a/runtime/art_method.h b/runtime/art_method.h index d8bd3803fc..072dea2c4d 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -422,8 +422,10 @@ class ArtMethod final { bool CheckIncompatibleClassChange(InvokeType type) REQUIRES_SHARED(Locks::mutator_lock_); // Throws the error that would result from trying to invoke this method (i.e. - // IncompatibleClassChangeError or AbstractMethodError). Only call if !IsInvokable(); - void ThrowInvocationTimeError() REQUIRES_SHARED(Locks::mutator_lock_); + // IncompatibleClassChangeError, AbstractMethodError, or IllegalAccessError). + // Only call if !IsInvokable(); + void ThrowInvocationTimeError(ObjPtr<mirror::Object> receiver) + REQUIRES_SHARED(Locks::mutator_lock_); uint16_t GetMethodIndex() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index d21aecc2fa..c2ce3e2eb8 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -7857,20 +7857,6 @@ bool ClassLinker::LinkMethodsHelper<kPointerSize>::FinalizeIfTable( return true; } -NO_INLINE -static void ThrowIllegalAccessErrorForImplementingMethod(ObjPtr<mirror::Class> klass, - ArtMethod* vtable_method, - ArtMethod* interface_method) - REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK(!vtable_method->IsAbstract()); - DCHECK(!vtable_method->IsPublic()); - ThrowIllegalAccessError( - klass, - "Method '%s' implementing interface method '%s' is not public", - vtable_method->PrettyMethod().c_str(), - interface_method->PrettyMethod().c_str()); -} - template <PointerSize kPointerSize> ObjPtr<mirror::PointerArray> ClassLinker::LinkMethodsHelper<kPointerSize>::AllocPointerArray( Thread* self, size_t length) { @@ -8124,15 +8110,11 @@ size_t ClassLinker::LinkMethodsHelper<kPointerSize>::AssignVTableIndexes( found = true; } } + found = found && vtable_method->IsPublic(); + uint32_t vtable_index = vtable_length; if (found) { DCHECK(vtable_method != nullptr); - if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) { - // FIXME: Delay the exception until we actually try to call the method. b/211854716 - sants.reset(); - ThrowIllegalAccessErrorForImplementingMethod(klass, vtable_method, interface_method); - return 0u; - } vtable_index = vtable_method->GetMethodIndexDuringLinking(); if (!vtable_method->IsOverridableByDefaultMethod()) { method_array->SetElementPtrSize(j, vtable_index, kPointerSize); diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 3a33f2a3aa..0bc913874b 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -237,6 +237,19 @@ void ThrowIllegalAccessError(ObjPtr<mirror::Class> referrer, const char* fmt, .. va_end(args); } +void ThrowIllegalAccessErrorForImplementingMethod(ObjPtr<mirror::Class> klass, + ArtMethod* implementation_method, + ArtMethod* interface_method) + REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(!implementation_method->IsAbstract()); + DCHECK(!implementation_method->IsPublic()); + ThrowIllegalAccessError( + klass, + "Method '%s' implementing interface method '%s' is not public", + implementation_method->PrettyMethod().c_str(), + interface_method->PrettyMethod().c_str()); +} + // IllegalAccessException void ThrowIllegalAccessException(const char* msg) { diff --git a/runtime/common_throws.h b/runtime/common_throws.h index 843c455878..d9620df0b9 100644 --- a/runtime/common_throws.h +++ b/runtime/common_throws.h @@ -111,6 +111,11 @@ void ThrowIllegalAccessError(ObjPtr<mirror::Class> referrer, const char* fmt, .. __attribute__((__format__(__printf__, 2, 3))) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +void ThrowIllegalAccessErrorForImplementingMethod(ObjPtr<mirror::Class> klass, + ArtMethod* implementation_method, + ArtMethod* interface_method) + REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + // IllegalAccessException void ThrowIllegalAccessException(const char* msg) diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 5995d5b0c5..7e3fdee3e1 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -224,13 +224,8 @@ class QuickArgumentVisitor { #endif public: - // Special handling for proxy methods. Proxy methods are instance methods so the - // 'this' object is the 1st argument. They also have the same frame layout as the - // kRefAndArgs runtime method. Since 'this' is a reference, it is located in the - // 1st GPR. - static StackReference<mirror::Object>* GetProxyThisObjectReference(ArtMethod** sp) + static StackReference<mirror::Object>* GetThisObjectReference(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK((*sp)->IsProxyMethod()); CHECK_GT(kNumQuickGprArgs, 0u); constexpr uint32_t kThisGprIndex = 0u; // 'this' is in the 1st GPR. size_t this_arg_offset = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset + @@ -529,7 +524,8 @@ class QuickArgumentVisitor { // allows to use the QuickArgumentVisitor constants without moving all the code in its own module. extern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { - return QuickArgumentVisitor::GetProxyThisObjectReference(sp)->AsMirrorPtr(); + DCHECK((*sp)->IsProxyMethod()); + return QuickArgumentVisitor::GetThisObjectReference(sp)->AsMirrorPtr(); } // Visits arguments on the stack placing them into the shadow frame. @@ -655,7 +651,10 @@ extern "C" uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ScopedQuickEntrypointChecks sqec(self); if (UNLIKELY(!method->IsInvokable())) { - method->ThrowInvocationTimeError(); + method->ThrowInvocationTimeError( + method->IsStatic() + ? nullptr + : QuickArgumentVisitor::GetThisObjectReference(sp)->AsMirrorPtr()); return 0; } diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 311cb23510..0ffc38beeb 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -374,7 +374,7 @@ void EnterInterpreterFromInvoke(Thread* self, num_ins = accessor.InsSize(); } else if (!method->IsInvokable()) { self->EndAssertNoThreadSuspension(old_cause); - method->ThrowInvocationTimeError(); + method->ThrowInvocationTimeError(receiver); return; } else { DCHECK(method->IsNative()) << method->PrettyMethod(); diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 0b91120c58..fe9cf57ec5 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -259,18 +259,23 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self, } // Null pointer check and virtual method resolution. - ObjPtr<mirror::Object> receiver = - (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC); - ArtMethod* called_method; - called_method = FindMethodToCall<type, do_access_check>( - method_idx, resolved_method, &receiver, sf_method, self); - if (UNLIKELY(called_method == nullptr)) { - CHECK(self->IsExceptionPending()); - result->SetJ(0); - return false; + ArtMethod* called_method = nullptr; + { + // `FindMethodToCall` might suspend, so don't keep `receiver` as a local + // variable after the call. + ObjPtr<mirror::Object> receiver = + (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC); + called_method = FindMethodToCall<type, do_access_check>( + method_idx, resolved_method, &receiver, sf_method, self); + if (UNLIKELY(called_method == nullptr)) { + CHECK(self->IsExceptionPending()); + result->SetJ(0); + return false; + } } if (UNLIKELY(!called_method->IsInvokable())) { - called_method->ThrowInvocationTimeError(); + called_method->ThrowInvocationTimeError( + (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC)); result->SetJ(0); return false; } diff --git a/test/182-method-linking/src/Main.java b/test/182-method-linking/src/Main.java index 39029560f7..638ff654a3 100644 --- a/test/182-method-linking/src/Main.java +++ b/test/182-method-linking/src/Main.java @@ -33,12 +33,6 @@ import pkg2.I2; public class Main { public static void main(String args[]) { - try { - Class.forName("dalvik.system.PathClassLoader"); - } catch (ClassNotFoundException e) { - usingRI = true; - } - // A single method signature can result in multiple vtable entries // when package-private methods from different packages are involved. // All classes here define the method `void foo()` but classes @@ -120,7 +114,6 @@ public class Main { CXI1 cxi1 = new CXI1(); I1.callI1Foo(cxi1); } catch (IllegalAccessError expected) { - printOnDalvik("Calling pkg1.I1.foo on pkg1.CXI1"); System.out.println("Caught IllegalAccessError"); } @@ -128,7 +121,6 @@ public class Main { CXI2 cxi2 = new CXI2(); I2.callI2Foo(cxi2); } catch (IllegalAccessError expected) { - printOnDalvik("Calling pkg2.I2.foo on pkg1.CXI2"); System.out.println("Caught IllegalAccessError"); } @@ -136,7 +128,6 @@ public class Main { DXI1 dxi1 = new DXI1(); I1.callI1Foo(dxi1); } catch (IllegalAccessError expected) { - printOnDalvik("Calling pkg1.I1.foo on pkg2.DXI1"); System.out.println("Caught IllegalAccessError"); } @@ -144,17 +135,7 @@ public class Main { DXI2 dxi2 = new DXI2(); I2.callI2Foo(dxi2); } catch (IllegalAccessError expected) { - printOnDalvik("Calling pkg2.I2.foo on pkg2.DXI2"); System.out.println("Caught IllegalAccessError"); } } - - private static void printOnDalvik(String line) { - if (!usingRI) { - // FIXME: Delay IAE until calling the method. Bug: 211854716 - System.out.println(line); - } - } - - private static boolean usingRI = false; } diff --git a/test/840-resolution/expected-stderr.txt b/test/840-resolution/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/840-resolution/expected-stderr.txt diff --git a/test/840-resolution/expected-stdout.txt b/test/840-resolution/expected-stdout.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/840-resolution/expected-stdout.txt diff --git a/test/840-resolution/info.txt b/test/840-resolution/info.txt new file mode 100644 index 0000000000..bd88f7d47d --- /dev/null +++ b/test/840-resolution/info.txt @@ -0,0 +1,2 @@ +Various tests on interface method linking when not finding a public +implementation. diff --git a/test/840-resolution/jasmin/SubClass2.j b/test/840-resolution/jasmin/SubClass2.j new file mode 100644 index 0000000000..8a65e1f554 --- /dev/null +++ b/test/840-resolution/jasmin/SubClass2.j @@ -0,0 +1,35 @@ +; Copyright (C) 2022 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. + +.class public SubClass2 +.super SuperClass +.implements Interface + +.method public <init>()V + .limit stack 1 + .limit locals 1 + aload_0 + invokespecial SuperClass/<init>()V + return +.end method + +.method foo()Ljava/lang/Class; + .limit stack 1 + .limit locals 1 + ; jasmin does not support ldc with a class, so just return null for the + ; purpose of this test. + aconst_null + areturn +.end method + diff --git a/test/840-resolution/src/Main.java b/test/840-resolution/src/Main.java new file mode 100644 index 0000000000..23cd31d3ab --- /dev/null +++ b/test/840-resolution/src/Main.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2022 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 { + + // Testcase 1: the superclass has a package private version in the same package. + static Interface s = new SubClass(); + + // Testcase 2: the class has a package private version. + static Interface s2; + + // Testcase 3: the superclass has a package private version in a different package. + static Interface s3 = new SubClassFromPkg(); + + // Testcase 4: there is no implementation in the hierarchy. + static Interface s4 = new SubClassNoFoo(); + + // Testcase 5: there is a private method in the hierarchy. + static Interface s5 = new SubClassPrivateFoo(); + + // Testcase 6: there is a static method in the hierarchy. + static Interface s6 = new SubClassStaticFoo(); + + static { + try { + s2 = (Interface) Class.forName("SubClass2").newInstance(); + } catch (Exception e) { + throw new Error(e); + } + } + + public static void assertEquals(Object expected, Object actual) { + if (expected != actual) { + throw new Error("Expected " + expected + ", got " + actual); + } + } + + public static void assertTrue(boolean value) { + if (!value) { + throw new Error(""); + } + } + + public static void main(String[] args) throws Exception { + assertEquals(SuperClass.class, ((SubClass) s).foo()); + assertEquals(SuperClass.class, ((SuperClass) s).foo()); + + try { + s.foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError ie) { + // expected + } + + assertEquals(null, ((SuperClass) s2).foo()); + try { + s2.foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError ie) { + // expected + } + + try { + ((pkg.PkgSuperClass) s3).foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError ie) { + // expected + } + + try { + ((SubClassFromPkg) s3).foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError ie) { + // expected + } + + try { + s3.foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError ie) { + // expected + } + + try { + ((SuperClassNoFoo) s4).foo(); + throw new Error("Expected NoSuchMethodError"); + } catch (NoSuchMethodError e) { + // expected + } + + try { + ((SubClassNoFoo) s4).foo(); + throw new Error("Expected AbstractMethodError"); + } catch (AbstractMethodError e) { + // expected + } + + try { + s4.foo(); + throw new Error("Expected AbstractMethodError"); + } catch (AbstractMethodError e) { + // expected + } + + try { + ((SuperClassPrivateFoo) s5).foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError e) { + // expected + } + + try { + ((SubClassPrivateFoo) s5).foo(); + throw new Error("Expected IllegalAccessError"); + } catch (IllegalAccessError e) { + // expected + } + + try { + s5.foo(); + throw new Error("Expected AbstractMethodError on RI, IllegalAccessError on ART"); + } catch (AbstractMethodError | IllegalAccessError e) { + // expected + } + + try { + ((SuperClassStaticFoo) s6).foo(); + throw new Error("Expected IncompatibleClassChangeError"); + } catch (IncompatibleClassChangeError e) { + // expected + } + + try { + ((SubClassStaticFoo) s6).foo(); + throw new Error("Expected IncompatibleClassChangeError"); + } catch (IncompatibleClassChangeError e) { + // expected + } + + try { + s6.foo(); + throw new Error("Expected AbstractMethodError"); + } catch (AbstractMethodError e) { + // expected + } + } +} + +interface Interface { + public Class<?> foo(); +} + +class SubClass extends SuperClass implements Interface { +} + +class SubClassFromPkg extends pkg.PkgSuperClass implements Interface { +} + +class SubClassNoFoo extends SuperClassNoFoo implements Interface { +} + +class SubClassPrivateFoo extends SuperClassPrivateFoo implements Interface { +} + +class SubClassStaticFoo extends SuperClassStaticFoo implements Interface { +} diff --git a/test/840-resolution/src/SuperClass.java b/test/840-resolution/src/SuperClass.java new file mode 100644 index 0000000000..ece01886b7 --- /dev/null +++ b/test/840-resolution/src/SuperClass.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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. + */ + +class SuperClass { + public Class<?> foo() { + return SuperClass.class; + } +} diff --git a/test/840-resolution/src/SuperClassNoFoo.java b/test/840-resolution/src/SuperClassNoFoo.java new file mode 100644 index 0000000000..747aaefb8c --- /dev/null +++ b/test/840-resolution/src/SuperClassNoFoo.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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 SuperClassNoFoo { + public Class<?> foo() { + throw new Error("Unreachable"); + } +} diff --git a/test/840-resolution/src/SuperClassPrivateFoo.java b/test/840-resolution/src/SuperClassPrivateFoo.java new file mode 100644 index 0000000000..95af4f78db --- /dev/null +++ b/test/840-resolution/src/SuperClassPrivateFoo.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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. + */ + +class SuperClassPrivateFoo { + public Class<?> foo() { + return SuperClass.class; + } +} diff --git a/test/840-resolution/src/SuperClassStaticFoo.java b/test/840-resolution/src/SuperClassStaticFoo.java new file mode 100644 index 0000000000..490637f8dc --- /dev/null +++ b/test/840-resolution/src/SuperClassStaticFoo.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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 SuperClassStaticFoo { + public Class<?> foo() { + throw new Error("Unreachable"); + } +} diff --git a/test/840-resolution/src/pkg/PkgSuperClass.java b/test/840-resolution/src/pkg/PkgSuperClass.java new file mode 100644 index 0000000000..397ae28a59 --- /dev/null +++ b/test/840-resolution/src/pkg/PkgSuperClass.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 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. + */ + +package pkg; + +public class PkgSuperClass { + public Class<?> foo() { + return PkgSuperClass.class; + } +} diff --git a/test/840-resolution/src2/SuperClass.java b/test/840-resolution/src2/SuperClass.java new file mode 100644 index 0000000000..fe40c0a060 --- /dev/null +++ b/test/840-resolution/src2/SuperClass.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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. + */ + +class SuperClass { + Class<?> foo() { + return SuperClass.class; + } +} diff --git a/test/840-resolution/src2/SuperClassNoFoo.java b/test/840-resolution/src2/SuperClassNoFoo.java new file mode 100644 index 0000000000..c0e8c442ed --- /dev/null +++ b/test/840-resolution/src2/SuperClassNoFoo.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 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 SuperClassNoFoo { +} diff --git a/test/840-resolution/src2/SuperClassPrivateFoo.java b/test/840-resolution/src2/SuperClassPrivateFoo.java new file mode 100644 index 0000000000..f0c1c6853f --- /dev/null +++ b/test/840-resolution/src2/SuperClassPrivateFoo.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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. + */ + +class SuperClassPrivateFoo { + private Class<?> foo() { + return SuperClass.class; + } +} diff --git a/test/840-resolution/src2/SuperClassStaticFoo.java b/test/840-resolution/src2/SuperClassStaticFoo.java new file mode 100644 index 0000000000..ecf8bc17a5 --- /dev/null +++ b/test/840-resolution/src2/SuperClassStaticFoo.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 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 SuperClassStaticFoo { + public static Class<?> foo() { + return SuperClassStaticFoo.class; + } +} diff --git a/test/840-resolution/src2/pkg/PkgSuperClass.java b/test/840-resolution/src2/pkg/PkgSuperClass.java new file mode 100644 index 0000000000..2f333eec46 --- /dev/null +++ b/test/840-resolution/src2/pkg/PkgSuperClass.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 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. + */ + +package pkg; + +public class PkgSuperClass { + Class<?> foo() { + return PkgSuperClass.class; + } +} |