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) {