Merge "Avoid processing empty bridge methods in VisibilityBridgeRemover."
diff --git a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
index 5847a80..ebf110e 100644
--- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.optimize.InvokeSingleTargetExtractor.InvokeKind;
import com.google.common.collect.Sets;
@@ -28,7 +29,8 @@
}
private void identifyBridgeMethod(DexEncodedMethod method) {
- if (method.accessFlags.isBridge()) {
+ MethodAccessFlags accessFlags = method.accessFlags;
+ if (accessFlags.isBridge() && !accessFlags.isAbstract()) {
InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor();
method.getCode().registerCodeReferences(targetExtractor);
DexMethod target = targetExtractor.getTarget();
@@ -36,11 +38,11 @@
// javac-generated visibility forward bridge method has same descriptor (name, signature and
// return type).
if (target != null && target.hasSameProtoAndName(method.method)) {
- assert !method.accessFlags.isPrivate() && !method.accessFlags.isConstructor();
+ assert !accessFlags.isPrivate() && !accessFlags.isConstructor();
if (kind == InvokeKind.SUPER) {
// This is a visibility forward, so check for the direct target.
- DexEncodedMethod targetMethod
- = appInfo.resolveMethod(target.getHolder(), target).asSingleTarget();
+ DexEncodedMethod targetMethod =
+ appInfo.resolveMethod(target.getHolder(), target).asSingleTarget();
if (targetMethod != null && targetMethod.accessFlags.isPublic()) {
if (Log.ENABLED) {
Log.info(getClass(), "Removing visibility forwarding %s -> %s", method.method,
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/EmptyBridgeTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/EmptyBridgeTest.java
new file mode 100644
index 0000000..160ad59
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/EmptyBridgeTest.java
@@ -0,0 +1,63 @@
+// Copyright (c) 2018, 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.bridgeremoval;
+
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.jasmin.JasminBuilder;
+import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.android.tools.r8.utils.DexInspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+public class EmptyBridgeTest extends TestBase {
+
+ @Test
+ public void test() throws Exception {
+ JasminBuilder jasminBuilder = new JasminBuilder();
+
+ ClassBuilder abs = jasminBuilder.addClass("Abs");
+ abs.setAccess("public abstract");
+ abs.addMethod("public bridge abstract", "emptyBridge", ImmutableList.of(), "V");
+
+ ClassBuilder cls = jasminBuilder.addClass("Main");
+ cls.addVirtualMethod("bogus", ImmutableList.of(), "V",
+ ".limit stack 3",
+ ".limit locals 2",
+ "getstatic java/lang/System/out Ljava/io/PrintStream;",
+ "ldc \"foo\"",
+ "invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+ "return");
+ cls.addMainMethod(
+ ".limit stack 4",
+ ".limit locals 2",
+ "new " + cls.name,
+ "dup",
+ "invokespecial " + cls.name + "/<init>()V",
+ "astore_0",
+ "aload_0",
+ "invokevirtual " + cls.name + "/bogus()V",
+ "return");
+
+ String absClassName = abs.name;
+ String mainClassName = cls.name;
+ String proguardConfig =
+ "-allowaccessmodification" + System.lineSeparator()
+ + "-keep class " + mainClassName + "{ *; }" + System.lineSeparator()
+ + "-keep class " + absClassName + "{ *; }";
+ AndroidApp processedApp = compileWithR8(jasminBuilder.build(), proguardConfig);
+
+ DexInspector inspector = new DexInspector(processedApp);
+ ClassSubject classSubject = inspector.clazz(absClassName);
+ assertThat(classSubject, isPresent());
+ MethodSubject methodSubject = classSubject.method("void", "emptyBridge", ImmutableList.of());
+ assertThat(methodSubject, isPresent());
+ }
+
+}
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
index eb6e943..ba04454 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
@@ -195,7 +195,7 @@
return addStaticMethod("main", ImmutableList.of("[Ljava/lang/String;"), "V", lines);
}
- private MethodSignature addMethod(
+ public MethodSignature addMethod(
String access,
String name,
List<String> argumentTypes,