Extend visibility checks to include package names
Change-Id: I18b7fca5296b4085d3992465a018c929e94e4e65
diff --git a/src/main/java/com/android/tools/r8/graph/AccessFlags.java b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
index 10620fc6..ee86680 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
@@ -109,25 +109,14 @@
}
public boolean isMoreVisibleThan(
- AccessFlags other, String packageNameThis, String packageNameOther) {
+ AccessFlags<?> other, String packageNameThis, String packageNameOther) {
int visibilityOrdinal = getVisibilityOrdinal();
if (visibilityOrdinal > other.getVisibilityOrdinal()) {
return true;
}
- if (visibilityOrdinal == other.getVisibilityOrdinal()
+ return visibilityOrdinal == other.getVisibilityOrdinal()
&& isVisibilityDependingOnPackage()
- && !packageNameThis.equals(packageNameOther)) {
- return true;
- }
- return false;
- }
-
- public boolean isAtLeastAsVisibleAs(AccessFlags other) {
- return getVisibilityOrdinal() >= other.getVisibilityOrdinal();
- }
-
- public boolean isSameVisibility(AccessFlags other) {
- return getVisibilityOrdinal() == other.getVisibilityOrdinal();
+ && !packageNameThis.equals(packageNameOther);
}
public int getVisibilityOrdinal() {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index 42f5d96..369e60c 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -536,7 +536,7 @@
assert potentialHolder.isInterface();
for (DexEncodedMethod virtualMethod : potentialHolder.virtualMethods()) {
if (virtualMethod.getReference().match(method.getReference())
- && virtualMethod.accessFlags.isSameVisibility(method.accessFlags)) {
+ && virtualMethod.isSameVisibility(method)) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index d68d906..985e215 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -569,6 +569,40 @@
return isStatic();
}
+ public boolean isAtLeastAsVisibleAsOtherInSameHierarchy(
+ DexEncodedMethod other, AppView<? extends AppInfoWithClassHierarchy> appView) {
+ assert getReference().getProto() == other.getReference().getProto();
+ assert appView.isSubtype(getHolderType(), other.getHolderType()).isTrue()
+ || appView.isSubtype(other.getHolderType(), getHolderType()).isTrue();
+ AccessFlags<MethodAccessFlags> accessFlags = getAccessFlags();
+ AccessFlags<?> otherAccessFlags = other.getAccessFlags();
+ if (accessFlags.getVisibilityOrdinal() < otherAccessFlags.getVisibilityOrdinal()) {
+ return false;
+ } else if (accessFlags.isPrivate()) {
+ return getHolderType() == other.getHolderType();
+ } else if (accessFlags.isPublic() || accessFlags.isProtected()) {
+ return true;
+ } else {
+ assert accessFlags.isPackagePrivate();
+ return getHolderType().getPackageName().equals(other.getHolderType().getPackageName());
+ }
+ }
+
+ public boolean isSameVisibility(DexEncodedMethod other) {
+ AccessFlags<MethodAccessFlags> accessFlags = getAccessFlags();
+ if (accessFlags.getVisibilityOrdinal() != other.getAccessFlags().getVisibilityOrdinal()) {
+ return false;
+ }
+ if (accessFlags.isPublic()) {
+ return true;
+ }
+ if (accessFlags.isPrivate()) {
+ return getHolderType() == other.getHolderType();
+ }
+ assert accessFlags.isVisibilityDependingOnPackage();
+ return getHolderType().getPackageName().equals(other.getHolderType().getPackageName());
+ }
+
/**
* Returns true if this method is synthetic.
*/
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 8a023db..08f3912 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
@@ -395,8 +395,7 @@
.isPossiblyFalse()
|| !newResolutionResult
.getResolvedMethod()
- .getAccessFlags()
- .isAtLeastAsVisibleAs(resolutionResult.getResolvedMethod().getAccessFlags())
+ .isAtLeastAsVisibleAsOtherInSameHierarchy(resolutionResult.getResolvedMethod(), appView)
// isOverriding expects both arguments to be not private.
|| (!newResolutionResult.getResolvedMethod().isPrivateMethod()
&& !isOverriding(
diff --git a/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java
index d0066e0..8847f5f 100644
--- a/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java
@@ -59,18 +59,10 @@
if (targetMethod == null) {
return null;
}
- if (method.getAccessFlags().isPublic()) {
- if (!targetMethod.getAccessFlags().isPublic()) {
- return null;
- }
- } else {
- if (targetMethod.getAccessFlags().isProtected()
- && !targetMethod.getHolderType().isSamePackage(method.getHolderType())) {
- return null;
- }
- if (targetMethod.getAccessFlags().isPrivate()) {
- return null;
- }
+ if (!targetMethod
+ .getDefinition()
+ .isAtLeastAsVisibleAsOtherInSameHierarchy(method.getDefinition(), appView)) {
+ return null;
}
if (definition.isStatic()
&& method.getHolder().hasClassInitializer()
diff --git a/src/test/java/com/android/tools/r8/shaking/b136195382/AbstractBridgeInheritTest.java b/src/test/java/com/android/tools/r8/shaking/b136195382/AbstractBridgeInheritTest.java
index f1fc012..58faf90 100644
--- a/src/test/java/com/android/tools/r8/shaking/b136195382/AbstractBridgeInheritTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/b136195382/AbstractBridgeInheritTest.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.shaking.b136195382;
-import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -13,8 +12,6 @@
import com.android.tools.r8.shaking.b136195382.package2.Main;
import com.android.tools.r8.shaking.b136195382.package2.SubFactory;
import com.android.tools.r8.shaking.b136195382.package2.SubService;
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -35,8 +32,7 @@
}
@Test
- public void testRemovingBridge()
- throws ExecutionException, CompilationFailedException, IOException {
+ public void testRemovingBridge() throws Exception {
testForR8(parameters.getBackend())
.addProgramClasses(
Service.class, Factory.class, SubService.class, SubFactory.class, Main.class)
@@ -44,7 +40,6 @@
.enableInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutputLines("Hello World!")
- .inspector();
+ .assertSuccessWithOutputLines("Hello World!");
}
}