Check for valid override in devirtualizer

Bug: 182185057
Change-Id: Ibdccf464f2c287c10fffdeb3b35c51d24e3d480f
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index 0cc7497..cf07031 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize;
 
+import static com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult.isOverriding;
+
 import com.android.tools.r8.graph.AccessControl;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
@@ -373,6 +375,10 @@
         || newResolutionResult
             .isAccessibleForVirtualDispatchFrom(context, appView.appInfo())
             .isPossiblyFalse()
+        || !isOverriding(
+            resolutionResult.getResolvedMethod(), newResolutionResult.getResolvedMethod())
+        // isOverriding do not check for invalid invokes and we should not bind if the candidate
+        // is not at least as visible.
         || !newResolutionResult
             .getResolvedMethod()
             .getAccessFlags()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java
index b3ca988..33da30f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PackagePrivateOverrideDeVirtualizerTest.java
@@ -56,8 +56,7 @@
         .enableNoVerticalClassMergingAnnotations()
         .enableNeverClassInliningAnnotations()
         .run(parameters.getRuntime(), Main.class)
-        // TODO(b/182185057): This should be EXPECTED.
-        .assertSuccessWithOutputLines(EXPECTED_DALVIK);
+        .apply(this::assertSuccessOutput);
   }
 
   private byte[] getSubViewModelInAnotherPackage() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java b/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
deleted file mode 100644
index f9583f7..0000000
--- a/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.shaking;
-
-import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.NoVerticalClassMerging;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class AbstractSuperClassLiveMethodTest extends TestBase {
-
-  private final TestParameters parameters;
-  private final String NEW_DESCRIPTOR = "Lfoo/A;";
-  private final String[] EXPECTED = new String[] {"A::foo", "Base::foo"};
-  private final String[] EXPECTED_DALVIK = new String[] {"A::foo", "A::foo"};
-
-  @Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimesAndApiLevels().build();
-  }
-
-  public AbstractSuperClassLiveMethodTest(TestParameters parameters) {
-    this.parameters = parameters;
-  }
-
-  public List<byte[]> getProgramClassFileData() throws Exception {
-    return ImmutableList.of(
-        transformer(A.class).setClassDescriptor(NEW_DESCRIPTOR).transform(),
-        transformer(Main.class)
-            .replaceClassDescriptorInMethodInstructions(descriptor(A.class), NEW_DESCRIPTOR)
-            .transform());
-  }
-
-  @Test
-  public void testRuntime() throws Exception {
-    testForRuntime(parameters)
-        .addProgramClasses(Base.class)
-        .addProgramClassFileData(getProgramClassFileData())
-        .run(parameters.getRuntime(), Main.class)
-        .applyIf(
-            parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik(),
-            r -> r.assertSuccessWithOutputLines(EXPECTED_DALVIK),
-            r -> r.assertSuccessWithOutputLines(EXPECTED));
-  }
-
-  @Test
-  public void testForR8() throws Exception {
-    testForR8(parameters.getBackend())
-        .addProgramClasses(Base.class)
-        .addProgramClassFileData(getProgramClassFileData())
-        .setMinApi(parameters.getApiLevel())
-        .addKeepMainRule(Main.class)
-        .enableInliningAnnotations()
-        .enableNoVerticalClassMergingAnnotations()
-        .enableNeverClassInliningAnnotations()
-        .addOptionsModification(options -> options.enableDevirtualization = false)
-        .run(parameters.getRuntime(), Main.class)
-        .applyIf(
-            parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik(),
-            r -> r.assertSuccessWithOutputLines(EXPECTED_DALVIK),
-            r -> r.assertSuccessWithOutputLines(EXPECTED));
-  }
-
-  @NoVerticalClassMerging
-  public abstract static class Base {
-
-    @NeverInline
-    void foo() {
-      System.out.println("Base::foo");
-    }
-  }
-
-  @NeverClassInline
-  public static class /* will be foo.A */ A extends Base {
-
-    @Override
-    @NeverInline
-    public void foo() {
-      System.out.println("A::foo");
-    }
-  }
-
-  public static class Main {
-
-    public static void main(String[] args) {
-      Base a = new A();
-      ((A) a).foo();
-      a.foo();
-    }
-  }
-}