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
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 62932c9..6839292 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 @@
   // 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 b0aad4d..b9ce449 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 8b66984..1c9dd11 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 0000000..1dd03c2
--- /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 0000000..41b5e8b
--- /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 04b403b..5b6a46a 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 983eea9..132e967 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 0000000..fb8327c
--- /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 65e072d..7311069 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 @@
 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 @@
     } 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 cf67135..4d866e1 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 @@
 
 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()");
+    }
 }