Regression test for retaining illegal access across isolated split

Bug: b/300247439
Change-Id: Ia7b86542d5e818deb3ed373f0da59b86a2269384
diff --git a/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java b/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
index 840b82a..1043723 100644
--- a/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
+++ b/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.features;
 
+import com.android.tools.r8.errors.dontwarn.DontWarnConfiguration;
 import com.android.tools.r8.features.diagnostic.IllegalAccessWithIsolatedFeatureSplitsDiagnostic;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
@@ -75,12 +76,17 @@
   }
 
   private void checkAccess(ProgramDefinition accessedItem, ProgramMethod context) {
-    if (!features.isInSameFeature(accessedItem, context, appView)
-        && !accessedItem.getAccessFlags().isPublic()) {
-      appView
-          .reporter()
-          .error(new IllegalAccessWithIsolatedFeatureSplitsDiagnostic(accessedItem, context));
+    if (accessedItem.getAccessFlags().isPublic()
+        || features.isInSameFeature(accessedItem, context, appView)) {
+      return;
     }
+    DontWarnConfiguration dontWarnConfiguration = appView.getDontWarnConfiguration();
+    if (dontWarnConfiguration.matches(accessedItem) || dontWarnConfiguration.matches(context)) {
+      return;
+    }
+    appView
+        .reporter()
+        .error(new IllegalAccessWithIsolatedFeatureSplitsDiagnostic(accessedItem, context));
   }
 
   // Field accesses.
diff --git a/src/test/java/com/android/tools/r8/features/PreserveIllegalAccessAcrossIsolatedSplitBoundaryTest.java b/src/test/java/com/android/tools/r8/features/PreserveIllegalAccessAcrossIsolatedSplitBoundaryTest.java
new file mode 100644
index 0000000..d6edc0b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/features/PreserveIllegalAccessAcrossIsolatedSplitBoundaryTest.java
@@ -0,0 +1,98 @@
+// Copyright (c) 2023, 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.features;
+
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.Box;
+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 java.util.List;
+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 PreserveIllegalAccessAcrossIsolatedSplitBoundaryTest extends TestBase {
+
+  @Parameter(0)
+  public boolean enableIsolatedSplits;
+
+  @Parameter(1)
+  public TestParameters parameters;
+
+  @Parameters(name = "{1}, isolated splits: {0}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        BooleanUtils.values(), getTestParameters().withDexRuntimesAndAllApiLevels().build());
+  }
+
+  @Test
+  public void test() throws Exception {
+    Box<CodeInspector> baseInspectorBox = new Box<>();
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Base.class)
+        .addKeepClassRules(Base.class)
+        .addFeatureSplit(Feature.class)
+        .addKeepClassAndMembersRules(Feature.class)
+        .applyIf(enableIsolatedSplits, testBuilder -> testBuilder.addDontWarn(Feature.class))
+        .enableIsolatedSplits(enableIsolatedSplits)
+        .enableInliningAnnotations()
+        .setMinApi(parameters)
+        .compile()
+        .inspect(
+            baseInspectorBox::set,
+            featureInspector -> {
+              CodeInspector baseInspector = baseInspectorBox.get();
+              ClassSubject baseClassSubject = baseInspector.clazz(Base.class);
+              assertThat(baseClassSubject, isPresent());
+
+              // TODO(b/300247439): Illegal access error should be preserved.
+              MethodSubject nonPublicMethodSubject =
+                  baseClassSubject.uniqueMethodWithOriginalName("nonPublicMethod");
+              assertThat(nonPublicMethodSubject, isAbsent());
+
+              MethodSubject otherMethodSubject =
+                  baseClassSubject.uniqueMethodWithOriginalName("otherMethod");
+              assertThat(otherMethodSubject, isPresent());
+
+              ClassSubject featureClassSubject = featureInspector.clazz(Feature.class);
+              assertThat(featureClassSubject, isPresent());
+
+              MethodSubject featureMethodSubject =
+                  featureClassSubject.uniqueMethodWithOriginalName("test");
+              assertThat(featureMethodSubject, isPresent());
+              assertThat(featureMethodSubject, invokesMethod(otherMethodSubject));
+            });
+  }
+
+  public static class Base {
+
+    static void nonPublicMethod() {
+      otherMethod();
+    }
+
+    @NeverInline
+    public static void otherMethod() {
+      System.out.println("Hello, world!");
+    }
+  }
+
+  public static class Feature {
+
+    public static void test() {
+      Base.nonPublicMethod();
+    }
+  }
+}