Test for accessibility of override before caching in seen set

Bug: 171369796
Change-Id: Ic284dd68f1293eec0b3590349d7c6bfec562c7d0
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index fead6b8..84451e1 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2008,9 +2008,10 @@
     worklist.addIfNotSeen(interfaces);
     // First we lookup and mark all targets on the instantiated class for each reachable method in
     // the super chain (inclusive).
+    DexClass initialClass = clazz;
     while (clazz != null) {
       if (clazz.isProgramClass()) {
-        markProgramMethodOverridesAsLive(instantiation, clazz.asProgramClass(), seen);
+        markProgramMethodOverridesAsLive(instantiation, initialClass, clazz.asProgramClass(), seen);
       } else {
         markLibraryAndClasspathMethodOverridesAsLive(instantiation, clazz);
       }
@@ -2031,7 +2032,7 @@
       if (iface.isNotProgramClass()) {
         markLibraryAndClasspathMethodOverridesAsLive(instantiation, iface);
       } else {
-        markProgramMethodOverridesAsLive(instantiation, iface.asProgramClass(), seen);
+        markProgramMethodOverridesAsLive(instantiation, initialClass, iface.asProgramClass(), seen);
       }
       worklist.addIfNotSeen(Arrays.asList(iface.interfaces.values));
     }
@@ -2043,18 +2044,28 @@
 
   private void markProgramMethodOverridesAsLive(
       InstantiatedObject instantiation,
+      DexClass initialClass,
       DexProgramClass superClass,
       Set<Wrapper<DexMethod>> seenMethods) {
     for (DexMethod method : getReachableVirtualTargets(superClass)) {
       assert method.holder == superClass.type;
-      if (seenMethods.add(MethodSignatureEquivalence.get().wrap(method))) {
+      Wrapper<DexMethod> signature = MethodSignatureEquivalence.get().wrap(method);
+      if (!seenMethods.contains(signature)) {
         SingleResolutionResult resolution =
             appInfo.resolveMethodOn(superClass, method).asSingleResolution();
         assert resolution != null;
         assert resolution.getResolvedHolder().isProgramClass();
-        if (resolution != null && resolution.getResolvedHolder().isProgramClass()) {
-          markLiveOverrides(
-              instantiation, superClass, resolution.getResolutionPair().asProgramMethod());
+        if (resolution != null) {
+          if (!initialClass.isProgramClass()
+              || resolution
+                  .isAccessibleForVirtualDispatchFrom(initialClass.asProgramClass(), appInfo)
+                  .isTrue()) {
+            seenMethods.add(signature);
+          }
+          if (resolution.getResolvedHolder().isProgramClass()) {
+            markLiveOverrides(
+                instantiation, superClass, resolution.getResolutionPair().asProgramMethod());
+          }
         }
       }
     }
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideInterfaceTest.java
index d2866a9..4e8bdd8 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideInterfaceTest.java
@@ -53,17 +53,7 @@
         .enableInliningAnnotations()
         .enableNeverClassInliningAnnotations()
         .run(parameters.getRuntime(), Main.class)
-        // TODO(b/171369796): Should work for ART runtimes.
-        .assertFailureWithErrorThatMatches(
-            containsString(
-                parameters.isDexRuntime()
-                        && parameters
-                            .getRuntime()
-                            .asDex()
-                            .getVm()
-                            .isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)
-                    ? "overrides final"
-                    : "NullPointerException"));
+        .apply(this::assertResult);
   }
 
   public void assertResult(TestRunResult<?> runResult) {