diff options
| author | 2020-08-18 09:29:51 +0100 | |
|---|---|---|
| committer | 2020-08-24 09:32:55 +0000 | |
| commit | cfd65805a5b3b0437e355b8044a05ee6c9d352c5 (patch) | |
| tree | c91f72b2fe4325cbbc21b6d4a889ea87a7c3608f | |
| parent | 095dc4611b8001861f8d0e621f9df704a933754a (diff) | |
Optimizing: Fix weak method access check.
And improve generated code for accessing package private
methods from unresolved compiling class in the same package.
Test: Additional test in 727-checker-unresolved-class
Test: testrunner.py --host --optimizing --interpreter --jvm -t 727
Test: testrunner.py --host --optimizing
Bug: 161898207
Change-Id: Ia34552d90620e8e0398099522a5a52b4a45df15d
10 files changed, 635 insertions, 14 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 62932c989f..6839292397 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -42,6 +42,44 @@ namespace art { +namespace { + +class SamePackageCompare { + public: + explicit SamePackageCompare(const DexCompilationUnit& dex_compilation_unit) + : dex_compilation_unit_(dex_compilation_unit) {} + + bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { + if (klass->GetClassLoader() != dex_compilation_unit_.GetClassLoader().Get()) { + return false; + } + if (referrers_descriptor_ == nullptr) { + const DexFile* dex_file = dex_compilation_unit_.GetDexFile(); + uint32_t referrers_method_idx = dex_compilation_unit_.GetDexMethodIndex(); + referrers_descriptor_ = + dex_file->StringByTypeIdx(dex_file->GetMethodId(referrers_method_idx).class_idx_); + referrers_package_length_ = PackageLength(referrers_descriptor_); + } + std::string temp; + const char* klass_descriptor = klass->GetDescriptor(&temp); + size_t klass_package_length = PackageLength(klass_descriptor); + return (referrers_package_length_ == klass_package_length) && + memcmp(referrers_descriptor_, klass_descriptor, referrers_package_length_) == 0; + }; + + private: + static size_t PackageLength(const char* descriptor) { + const char* slash_pos = strrchr(descriptor, '/'); + return (slash_pos != nullptr) ? static_cast<size_t>(slash_pos - descriptor) : 0u; + } + + const DexCompilationUnit& dex_compilation_unit_; + const char* referrers_descriptor_ = nullptr; + size_t referrers_package_length_ = 0u; +}; + +} // anonymous namespace + HInstructionBuilder::HInstructionBuilder(HGraph* graph, HBasicBlockBuilder* block_builder, SsaBuilder* ssa_builder, @@ -858,8 +896,29 @@ static ArtMethod* ResolveMethod(uint16_t method_idx, // resolved because, for example, we don't find a superclass in the classpath. if (referrer == nullptr) { // The class linker cannot check access without a referrer, so we have to do it. - // Fall back to HInvokeUnresolved if the method isn't public. - if (!resolved_method->IsPublic()) { + // Check if the declaring class or referencing class is accessible. + SamePackageCompare same_package(dex_compilation_unit); + ObjPtr<mirror::Class> declaring_class = resolved_method->GetDeclaringClass(); + bool declaring_class_accessible = declaring_class->IsPublic() || same_package(declaring_class); + if (!declaring_class_accessible) { + // It is possible to access members from an inaccessible superclass + // by referencing them through an accessible subclass. + ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType( + dex_compilation_unit.GetDexFile()->GetMethodId(method_idx).class_idx_, + dex_compilation_unit.GetDexCache().Get(), + class_loader.Get()); + DCHECK(referenced_class != nullptr); // Must have been resolved when resolving the method. + if (!referenced_class->IsPublic() && !same_package(referenced_class)) { + return nullptr; + } + } + // Check whether the method itself is accessible. + // Since the referrer is unresolved but the method is resolved, it cannot be + // inside the same class, so a private method is known to be inaccessible. + // And without a resolved referrer, we cannot check for protected member access + // in superlass, so we handle only access to public member or within the package. + if (resolved_method->IsPrivate() || + (!resolved_method->IsPublic() && !declaring_class_accessible)) { return nullptr; } } diff --git a/test/727-checker-unresolved-class/expected.txt b/test/727-checker-unresolved-class/expected.txt index b0aad4deb5..b9ce449b96 100644 --- a/test/727-checker-unresolved-class/expected.txt +++ b/test/727-checker-unresolved-class/expected.txt @@ -1 +1,9 @@ -passed +ResolvedPackagePrivateClass.$noinline$publicStaticMethod() +UnresolvedClass passed +ResolvedPackagePrivateClass.$noinline$publicStaticMethod() +ResolvedPackagePrivateClass.$noinline$publicStaticMethod() +ResolvedPackagePrivateClass.$noinline$staticMethod() +ResolvedPackagePrivateClass.$noinline$staticMethod() +SubclassOfUnresolvedClass passed +ResolvedPackagePrivateClass.$noinline$publicStaticMethod() +SubclassOfUnresolvedClass2 passed diff --git a/test/727-checker-unresolved-class/run b/test/727-checker-unresolved-class/run index 8b66984065..1c9dd1179c 100644 --- a/test/727-checker-unresolved-class/run +++ b/test/727-checker-unresolved-class/run @@ -17,5 +17,11 @@ if [[ "$TEST_RUNTIME" == "jvm" ]]; then exec ${RUN} $@ else - exec ${RUN} $@ -Xcompiler-option --updatable-bcp-packages-file="$DEX_LOCATION/res/updateable.txt" + # Append graphs for checker tests (we run dex2oat twice) with + # --dump-cfg-append. + # Make some classes unresolved for AOT compilation with + # --updatable-bcp-packages-file. + exec ${RUN} $@ \ + -Xcompiler-option --dump-cfg-append \ + -Xcompiler-option --updatable-bcp-packages-file="$DEX_LOCATION/res/updateable.txt" fi diff --git a/test/727-checker-unresolved-class/src-ex/Test.java b/test/727-checker-unresolved-class/src-ex/Test.java new file mode 100644 index 0000000000..1dd03c29ad --- /dev/null +++ b/test/727-checker-unresolved-class/src-ex/Test.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 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. + */ + +import resolved.SubclassOfUnresolvedClass; +import resolved.SubclassOfUnresolvedClass2; +import unresolved.UnresolvedClass; + +public class Test { + public static void $noinline$main() { + UnresolvedClass.$noinline$main(); + SubclassOfUnresolvedClass.$noinline$main(); + SubclassOfUnresolvedClass2.$noinline$main(); + } +} diff --git a/test/727-checker-unresolved-class/src-ex/resolved/SubclassOfUnresolvedClass2.java b/test/727-checker-unresolved-class/src-ex/resolved/SubclassOfUnresolvedClass2.java new file mode 100644 index 0000000000..41b5e8b8d4 --- /dev/null +++ b/test/727-checker-unresolved-class/src-ex/resolved/SubclassOfUnresolvedClass2.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2020 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 resolved; + +import unresolved.UnresolvedClass; + +// This class is defined by the child class loader, so access to +// package-private classes and members defined in the parent class +// loader is illegal even though the package name is the same. +public class SubclassOfUnresolvedClass2 extends UnresolvedClass { + public static void $noinline$main() { + $noinline$testPublicFieldInResolvedPackagePrivateClass(); + $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPrivateFieldInResolvedPackagePrivateClass(); + $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass(); + $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass(); + + $noinline$testPublicMethodInResolvedPackagePrivateClass(); + $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPrivateMethodInResolvedPackagePrivateClass(); + $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass(); + $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass(); + + System.out.println("SubclassOfUnresolvedClass2 passed"); + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPublicFieldInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.publicIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() { + // TODO: Use StaticFieldSet. + ResolvedPublicSubclassOfPackagePrivateClass.publicIntField = 42; + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPrivateFieldInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.privateIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.privateIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.intField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.intField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod + static void $noinline$testPublicMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$publicStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod + static void $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$publicStaticMethod(); + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod + static void $noinline$testPrivateMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$privateStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod + static void $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$privateStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod + static void $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$staticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod + static void $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$staticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } +} diff --git a/test/727-checker-unresolved-class/src/Main.java b/test/727-checker-unresolved-class/src/Main.java index 04b403bc2e..5b6a46a662 100644 --- a/test/727-checker-unresolved-class/src/Main.java +++ b/test/727-checker-unresolved-class/src/Main.java @@ -14,11 +14,31 @@ * limitations under the License. */ -import unresolved.UnresolvedClass; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; public class Main { - public static void main(String[] args) { - UnresolvedClass.$noinline$main(); - System.out.println("passed"); + public static String TEST_NAME = "727-checker-unresolved-class"; + + public static ClassLoader getClassLoaderFor(String location) throws Exception { + try { + Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader"); + Constructor<?> ctor = + class_loader_class.getConstructor(String.class, ClassLoader.class); + /* on Dalvik, this is a DexFile; otherwise, it's null */ + return (ClassLoader) ctor.newInstance(location + "/" + TEST_NAME + "-ex.jar", + Main.class.getClassLoader()); + } catch (ClassNotFoundException e) { + // Running on RI. Use URLClassLoader. + return new java.net.URLClassLoader( + new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") }); + } + } + + public static void main(String[] args) throws Exception { + ClassLoader new_loader = getClassLoaderFor(System.getenv("DEX_LOCATION")); + Class<?> testClass = Class.forName("Test", true, new_loader); + Method testMain = testClass.getMethod("$noinline$main"); + testMain.invoke(null); } } diff --git a/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java index 983eea9d41..132e967eda 100644 --- a/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java +++ b/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java @@ -17,8 +17,22 @@ package resolved; // This class is used for compiling code that accesses its fields but it is -// replaced by a package-private class from src2/ to make that access illegal. +// replaced by a package-private class from src2/ with reduced access to +// some members to test different access checks. public class ResolvedPackagePrivateClass { public static int publicIntField; - static int intField; + public static int privateIntField; + public static int intField; + + public static void $noinline$publicStaticMethod() { + System.out.println("ResolvedPackagePrivateClass.$noinline$publicStaticMethod()"); + } + + public static void $noinline$privateStaticMethod() { + System.out.println("ResolvedPackagePrivateClass.$noinline$privateStaticMethod()"); + } + + public static void $noinline$staticMethod() { + System.out.println("ResolvedPackagePrivateClass.$noinline$staticMethod()"); + } } diff --git a/test/727-checker-unresolved-class/src/resolved/SubclassOfUnresolvedClass.java b/test/727-checker-unresolved-class/src/resolved/SubclassOfUnresolvedClass.java new file mode 100644 index 0000000000..fb8327cdd5 --- /dev/null +++ b/test/727-checker-unresolved-class/src/resolved/SubclassOfUnresolvedClass.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2020 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 resolved; + +import unresolved.UnresolvedClass; + +public class SubclassOfUnresolvedClass extends UnresolvedClass { + public static void $noinline$main() { + $noinline$testPublicFieldInResolvedPackagePrivateClass(); + $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPrivateFieldInResolvedPackagePrivateClass(); + $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass(); + $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass(); + + $noinline$testPublicMethodInResolvedPackagePrivateClass(); + $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPrivateMethodInResolvedPackagePrivateClass(); + $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass(); + $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass(); + + System.out.println("SubclassOfUnresolvedClass passed"); + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPublicFieldInResolvedPackagePrivateClass() { + // TODO: Use StaticFieldSet. + ResolvedPackagePrivateClass.publicIntField = 42; + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() { + // TODO: Use StaticFieldSet. + ResolvedPublicSubclassOfPackagePrivateClass.publicIntField = 42; + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPrivateFieldInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.privateIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.privateIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() { + // TODO: Use StaticFieldSet. + ResolvedPackagePrivateClass.intField = 42; + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() { + // TODO: Use StaticFieldSet. + ResolvedPublicSubclassOfPackagePrivateClass.intField = 42; + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod + static void $noinline$testPublicMethodInResolvedPackagePrivateClass() { + ResolvedPackagePrivateClass.$noinline$publicStaticMethod(); + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod + static void $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$publicStaticMethod(); + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod + static void $noinline$testPrivateMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$privateStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod + static void $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$privateStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod + static void $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() { + ResolvedPackagePrivateClass.$noinline$staticMethod(); + } + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod + + /// CHECK-START: void resolved.SubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod + static void $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$staticMethod(); + } +} diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedClass.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedClass.java index 65e072de72..73110697ac 100644 --- a/test/727-checker-unresolved-class/src/unresolved/UnresolvedClass.java +++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedClass.java @@ -22,7 +22,20 @@ import resolved.ResolvedPublicSubclassOfPackagePrivateClass; public class UnresolvedClass { public static void $noinline$main() { $noinline$testPublicFieldInResolvedPackagePrivateClass(); - $noinline$testPublicFieldInPackagePrivateClassReferencedViaResolvedPublicSubclass(); + $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPrivateFieldInResolvedPackagePrivateClass(); + $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass(); + $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass(); + + $noinline$testPublicMethodInResolvedPackagePrivateClass(); + $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPrivateMethodInResolvedPackagePrivateClass(); + $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass(); + $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass(); + $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass(); + + System.out.println("UnresolvedClass passed"); } /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after) @@ -37,13 +50,130 @@ public class UnresolvedClass { } catch (IllegalAccessError expected) {} } - /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassReferencedViaResolvedPublicSubclass() builder (after) + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) /// CHECK: UnresolvedStaticFieldSet - /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassReferencedViaResolvedPublicSubclass() builder (after) + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) /// CHECK-NOT: StaticFieldSet - static void $noinline$testPublicFieldInPackagePrivateClassReferencedViaResolvedPublicSubclass() { + static void $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() { // TODO: Use StaticFieldSet when the referenced class is public. ResolvedPublicSubclassOfPackagePrivateClass.publicIntField = 42; } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPrivateFieldInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.privateIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.privateIntField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.intField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: UnresolvedStaticFieldSet + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: StaticFieldSet + static void $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.intField = 42; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod + static void $noinline$testPublicMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$publicStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod + static void $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$publicStaticMethod(); + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod + static void $noinline$testPrivateMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$privateStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod + static void $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$privateStaticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod + static void $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() { + try { + ResolvedPackagePrivateClass.$noinline$staticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod + + /// CHECK-START: void unresolved.UnresolvedClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after) + /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod + static void $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() { + try { + ResolvedPublicSubclassOfPackagePrivateClass.$noinline$staticMethod(); + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } } diff --git a/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java index cf67135980..4d866e120f 100644 --- a/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java +++ b/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java @@ -18,5 +18,18 @@ package resolved; class ResolvedPackagePrivateClass { public static int publicIntField; + private static int privateIntField; static int intField; + + public static void $noinline$publicStaticMethod() { + System.out.println("ResolvedPackagePrivateClass.$noinline$publicStaticMethod()"); + } + + private static void $noinline$privateStaticMethod() { + System.out.println("ResolvedPackagePrivateClass.$noinline$privateStaticMethod()"); + } + + static void $noinline$staticMethod() { + System.out.println("ResolvedPackagePrivateClass.$noinline$staticMethod()"); + } } |