Test -assumenosideeffects rule on method that returns arg
Change-Id: I219732f5d12cd57b788ac21a8b8bd2158a061f3f
diff --git a/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumeNoSideEffectsOnMethodWithArgumentReturnTest.java b/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumeNoSideEffectsOnMethodWithArgumentReturnTest.java
new file mode 100644
index 0000000..9fb503f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumeNoSideEffectsOnMethodWithArgumentReturnTest.java
@@ -0,0 +1,107 @@
+// Copyright (c) 2025, 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.assumenosideeffects;
+
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentIf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.io.PrintStream;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AssumeNoSideEffectsOnMethodWithArgumentReturnTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepClassAndMembersRules(Main.class)
+ .addKeepRules(
+ "-assumenosideeffects class " + Preconditions.class.getTypeName() + " {",
+ " static java.lang.Object checkNotNull(java.lang.Object);",
+ "}")
+ .setMinApi(parameters)
+ .compile()
+ .inspect(
+ inspector -> {
+ ClassSubject preconditionsClass = inspector.clazz(Preconditions.class);
+ assertThat(preconditionsClass, isPresentIf(parameters.isCfRuntime()));
+
+ MethodSubject checkNotNullMethod =
+ preconditionsClass.uniqueMethodWithOriginalName("checkNotNull");
+ assertThat(checkNotNullMethod, isPresentIf(parameters.isCfRuntime()));
+
+ MethodSubject testMethodSubject =
+ inspector.clazz(Main.class).uniqueMethodWithOriginalName("test");
+ assertThat(testMethodSubject, isPresent());
+ if (parameters.isCfRuntime()) {
+ // Calls are not eliminated due to not running the move-result optimization when
+ // compiling to CF.
+ assertThat(testMethodSubject, invokesMethod(checkNotNullMethod));
+ } else {
+ assertTrue(
+ testMethodSubject
+ .streamInstructions()
+ .filter(InstructionSubject::isInvokeMethod)
+ .map(InstructionSubject::getMethod)
+ .allMatch(
+ method ->
+ method.toSourceString().contains(PrintStream.class.getTypeName())));
+ }
+ })
+ .run(parameters.getRuntime(), Main.class, "Hello", ",", " ", "world", "!")
+ .assertSuccessWithOutputLines("Hello, world!");
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ test(args[0], args[1], args[2], args[3], args[4]);
+ }
+
+ static void test(Object p1, Object p2, Object p3, Object p4, Object p5) {
+ Object nonNullP1 = Preconditions.checkNotNull(p1);
+ System.out.print(nonNullP1);
+ Object nonNullP2 = Preconditions.checkNotNull(p2);
+ System.out.print(nonNullP2);
+ Object nonNullP3 = Preconditions.checkNotNull(p3);
+ System.out.print(nonNullP3);
+ Object nonNullP4 = Preconditions.checkNotNull(p4);
+ System.out.print(nonNullP4);
+ Object nonNullP5 = Preconditions.checkNotNull(p5);
+ System.out.println(nonNullP5);
+ }
+ }
+
+ static class Preconditions {
+
+ static <T> T checkNotNull(T t) {
+ if (t == null) {
+ throw new RuntimeException("Expected non-null object");
+ }
+ return t;
+ }
+ }
+}