Enable unused argument removal for non-private constructors
Bug: 123004864, 122683370
Change-Id: I4e576c2c9f90fd64fbf35731b06099c639be4a52
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
index 9d2bb32..061907f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
@@ -211,7 +211,9 @@
int argumentCount =
method.method.proto.parameters.size() + (method.accessFlags.isStatic() ? 0 : 1);
// TODO(65810338): Implement for virtual methods as well.
- if (method.accessFlags.isPrivate() || method.accessFlags.isStatic()) {
+ if (method.accessFlags.isPrivate()
+ || method.accessFlags.isStatic()
+ || method.isInstanceInitializer()) {
CollectUsedArguments collector = new CollectUsedArguments();
if (!method.accessFlags.isStatic()) {
// TODO(65810338): The receiver cannot be removed without transforming the method to being
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
new file mode 100644
index 0000000..20d7bae
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedarguments/UnusedArgumentsInstanceConstructorTest.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2019, 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.ir.optimize.unusedarguments;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+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 UnusedArgumentsInstanceConstructorTest extends TestBase {
+
+ private final Backend backend;
+
+ @Parameters(name = "Backend: {0}")
+ public static Backend[] data() {
+ return Backend.values();
+ }
+
+ public UnusedArgumentsInstanceConstructorTest(Backend backend) {
+ this.backend = backend;
+ }
+
+ @Test
+ public void test() throws Exception {
+ String expectedOutput = StringUtils.lines("Hello world");
+
+ if (backend == Backend.CF) {
+ testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expectedOutput);
+ }
+
+ CodeInspector inspector =
+ testForR8(backend)
+ .addInnerClasses(UnusedArgumentsInstanceConstructorTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableClassInliningAnnotations()
+ .run(TestClass.class)
+ .assertSuccessWithOutput(expectedOutput)
+ .inspector();
+
+ ClassSubject classSubject = inspector.clazz(A.class);
+ assertThat(classSubject, isPresent());
+
+ MethodSubject methodSubject = classSubject.uniqueMethodWithName("<init>");
+ assertThat(methodSubject, isPresent());
+ assertTrue(methodSubject.getMethod().method.proto.parameters.isEmpty());
+
+ assertThat(inspector.clazz(B.class), not(isPresent()));
+ assertThat(inspector.clazz(C.class), not(isPresent()));
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ new A(null, new C()).doSomething();
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ public A(B uninstantiated, C unused) {
+ System.out.print("Hello");
+ if (uninstantiated != null) {
+ throw new RuntimeException("Unreachable");
+ } else {
+ System.out.print(" ");
+ }
+ }
+
+ @NeverInline
+ public void doSomething() {
+ System.out.println("world");
+ }
+ }
+
+ static class B {}
+
+ static class C {}
+}