Fix bridge insertion for code with illegal access errors

Change-Id: If47d870a713ab21679311e697f3e448c020ce524
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 7fcedfc..42adbc6 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -323,7 +323,10 @@
         || !packageDescriptor.equals(target.getHolderType().getPackageDescriptor())) {
       DexClass bridgeHolder =
           findHolderForVisibilityBridge(originalClass, target.getHolder(), packageDescriptor);
-      assert bridgeHolder != null;
+      if (bridgeHolder == null) {
+        // The original class does not have access to the target so we cannot insert a valid bridge.
+        return target.getReference().withHolder(originalClass, appView.dexItemFactory());
+      }
       if (bridgeHolder.isClasspathClass()) {
         // Intentionally empty. We do not need to insert a bridge on a classpath class.
       } else if (bridgeHolder.isLibraryClass()) {
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingClasspathSplitTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingClasspathSplitTest.java
index e87a04d..89d12eb 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingClasspathSplitTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingClasspathSplitTest.java
@@ -8,6 +8,8 @@
 import com.android.tools.r8.TestCompileResult;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ThrowableConsumer;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.graph.AccessFlags;
 import com.android.tools.r8.memberrebinding.testclasses.MemberRebindingClasspathSplitTestClasses;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
@@ -24,20 +26,22 @@
 
   private static class TestConfig {
     private final String desc;
-
     private final ThrowableConsumer<? super TestBuilder<?, ?>> addToClasspath;
     private final ThrowableConsumer<? super TestBuilder<?, ?>> addToProgrampath;
     private final ThrowableConsumer<? super TestCompileResult<?, ?>> addToRunClasspath;
+    private final boolean expectFailure;
 
     private TestConfig(
         String desc,
         ThrowableConsumer<? super TestBuilder<?, ?>> addToClasspath,
         ThrowableConsumer<? super TestBuilder<?, ?>> addToProgrampath,
-        ThrowableConsumer<? super TestCompileResult<?, ?>> addToRunClasspath) {
+        ThrowableConsumer<? super TestCompileResult<?, ?>> addToRunClasspath,
+        boolean expectFailure) {
       this.desc = desc;
       this.addToClasspath = addToClasspath;
       this.addToProgrampath = addToProgrampath;
       this.addToRunClasspath = addToRunClasspath;
+      this.expectFailure = expectFailure;
     }
 
     @Override
@@ -66,7 +70,8 @@
                   b.addRunClasspathClasses(
                       MemberRebindingClasspathSplitTestClasses.getA(),
                       MemberRebindingClasspathSplitTestClasses.getB());
-                }),
+                },
+                false),
             new TestConfig(
                 "Both A and B on classpath, m() bridge removed from B",
                 b -> {
@@ -83,7 +88,8 @@
                       transformer(MemberRebindingClasspathSplitTestClasses.getB())
                           .removeMethodsWithName("m")
                           .transform());
-                }),
+                },
+                false),
             new TestConfig(
                 "A on classpath and B on programpath",
                 b -> {
@@ -94,7 +100,8 @@
                 },
                 b -> {
                   b.addRunClasspathClasses(MemberRebindingClasspathSplitTestClasses.getA());
-                }),
+                },
+                false),
             new TestConfig(
                 "A on classpath and B on programpath, m() bridge removed from B",
                 b -> {
@@ -108,7 +115,26 @@
                 },
                 b -> {
                   b.addRunClasspathClasses(MemberRebindingClasspathSplitTestClasses.getA());
-                })));
+                },
+                false),
+            new TestConfig(
+                "Both A and B on classpath but neither A or B is public",
+                b -> {
+                  b.addClasspathClasses(MemberRebindingClasspathSplitTestClasses.getA());
+                  b.addClasspathClassFileData(
+                      transformer(MemberRebindingClasspathSplitTestClasses.getB())
+                          .setAccessFlags(AccessFlags::unsetPublic)
+                          .transform());
+                },
+                b -> {},
+                b -> {
+                  b.addRunClasspathClasses(MemberRebindingClasspathSplitTestClasses.getA());
+                  b.addRunClasspathClassFileData(
+                      transformer(MemberRebindingClasspathSplitTestClasses.getB())
+                          .setAccessFlags(AccessFlags::unsetPublic)
+                          .transform());
+                },
+                true)));
   }
 
   @Test
@@ -124,7 +150,12 @@
         .compile()
         .apply(split.addToRunClasspath)
         .run(parameters.getRuntime(), Main.class)
-        .assertSuccessWithOutputLines("A", "A");
+        .applyIf(
+            split.expectFailure && parameters.isDexRuntimeVersionOlderThanOrEqual(Version.V4_4_4),
+            rr -> rr.assertFailureWithErrorThatThrows(NoClassDefFoundError.class),
+            split.expectFailure,
+            rr -> rr.assertFailureWithErrorThatThrows(IllegalAccessError.class),
+            rr -> rr.assertSuccessWithOutputLines("A", "A"));
   }
 
   public static class C extends MemberRebindingClasspathSplitTestClasses.B {