Merge "Fix bug during computation of methods to implement"
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 2d5d803..1eb8707 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -96,7 +96,7 @@
             continue;
           }
           DexMethod actualTarget = graphLense.lookupMethod(invokedMethod, method);
-          Invoke.Type invokeType = getInvokeType(invoke, actualTarget);
+          Invoke.Type invokeType = getInvokeType(invoke, actualTarget, invokedMethod);
           if (actualTarget != invokedMethod || invoke.getType() != invokeType) {
             Invoke newInvoke = Invoke
                 .create(invokeType, actualTarget, null,
@@ -228,16 +228,26 @@
     return methodHandle;
   }
 
-  private Type getInvokeType(InvokeMethod invoke, DexMethod actualTarget) {
+  private Type getInvokeType(InvokeMethod invoke, DexMethod actualTarget,
+      DexMethod originalTarget) {
     if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
       // Get the invoke type of the actual definition.
-      DexClass clazz = appInfo.definitionFor(actualTarget.holder);
-      if (clazz == null) {
+      DexClass newTargetClass = appInfo.definitionFor(actualTarget.holder);
+      if (newTargetClass == null) {
         return invoke.getType();
       } else {
-        return clazz.accessFlags.isInterface()
-            ? Type.INTERFACE
-            : Type.VIRTUAL;
+        DexClass originalTargetClass = appInfo.definitionFor(originalTarget.holder);
+        if (originalTargetClass.isInterface() ^ (invoke.getType() == Type.INTERFACE)) {
+          // The invoke was wrong to start with, so we keep it wrong. This is to ensure we get
+          // the IncompatibleClassChangeError the original invoke would have triggered.
+          return newTargetClass.accessFlags.isInterface()
+              ? Type.VIRTUAL
+              : Type.INTERFACE;
+        } else {
+          return newTargetClass.accessFlags.isInterface()
+              ? Type.INTERFACE
+              : Type.VIRTUAL;
+        }
       }
     } else {
       return invoke.getType();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 11548bc..bc9b95e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -138,8 +138,13 @@
         assert target.getCode().isDexCode();
         return target.buildIR(generator, options);
       } else {
-        assert target.getCode().isJarCode();
-        IRCode code = target.getCode().asJarCode().buildIR(target, generator, options);
+        // Build the IR for a yet not processed method, and perform minimal IR processing.
+        IRCode code;
+        if (target.getCode().isJarCode()) {
+          code = target.getCode().asJarCode().buildIR(target, generator, options);
+        } else {
+          code = target.getCode().asDexCode().buildIR(target, generator, options);
+        }
         new LensCodeRewriter(graphLense, appInfo).rewrite(code, target);
         return code;
       }
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 6fb9d2e..6dbf79b 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -682,6 +682,7 @@
     }
     superInvokeDependencies.computeIfAbsent(from, ignore -> Sets.newIdentityHashSet()).add(target);
     if (liveMethods.contains(from)) {
+      markMethodAsTargeted(target, KeepReason.invokedViaSuperFrom(from));
       markVirtualMethodAsLive(target, KeepReason.invokedViaSuperFrom(from));
     }
   }
@@ -822,6 +823,7 @@
             Log.verbose(getClass(), "Found super invoke constraint on `%s`.",
                 superCallTarget.method);
           }
+          markMethodAsTargeted(superCallTarget, KeepReason.invokedViaSuperFrom(method));
           markVirtualMethodAsLive(superCallTarget, KeepReason.invokedViaSuperFrom(method));
         }
       }
diff --git a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
index 3fe2173..8c5e094 100644
--- a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
@@ -78,13 +78,14 @@
             "java.lang.NullPointerException: Attempt to read from field " +
                 "'Test Test.a' on a null object reference\n"},
         {"merge-blocks-regression", "java.lang.NullPointerException: Attempt to invoke virtual"
-            +" method 'Test Test.bW_()' on a null object reference\n"},
+            + " method 'Test Test.bW_()' on a null object reference\n"},
         {"self-is-catch-block", "100\n-1\n"},
         {"infinite-loop", ""},
         {"regression/33336471",
             "START\n0\n2\nLOOP\n1\n2\nLOOP\n2\n2\nDONE\n" +
                 "START\n0\n2\nLOOP\n1\n2\nLOOP\n2\n2\nDONE\n"},
         {"regression/33846227", ""},
+        {"illegal-invokes", "ICCE\nICCE\n"},
     });
   }
 
@@ -123,7 +124,8 @@
         thrown.expect(Throwable.class);
       }
       output =
-          ToolHelper.checkArtOutputIdentical(originalDexFile.toString(), generated, mainClass, null);
+          ToolHelper
+              .checkArtOutputIdentical(originalDexFile.toString(), generated, mainClass, null);
     }
     assertEquals(expectedOutput, output);
   }
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 5902a6e..4b2ece0 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -36,17 +36,19 @@
 
   public AndroidApp runAndCheckVerification(
       CompilerUnderTest compiler,
+      CompilationMode mode,
       String referenceApk,
       String pgMap,
       String pgConf,
       String... inputs)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     return runAndCheckVerification(
-        compiler, referenceApk, pgMap, pgConf, Arrays.asList(inputs));
+        compiler, mode, referenceApk, pgMap, pgConf, Arrays.asList(inputs));
   }
 
   public AndroidApp runAndCheckVerification(
       CompilerUnderTest compiler,
+      CompilationMode mode,
       String referenceApk,
       String pgMap,
       String pgConf,
@@ -63,6 +65,7 @@
       if (pgConf != null) {
         builder.addProguardConfigurationFiles(Paths.get(pgConf));
       }
+      builder.setMode(mode);
       outputApp = ToolHelper.runR8(builder.build());
     } else {
       assert compiler == CompilerUnderTest.D8;
@@ -70,7 +73,7 @@
           ToolHelper.runD8(
               D8Command.builder()
                   .addProgramFiles(ListUtils.map(inputs, Paths::get))
-                  .setMode(CompilationMode.DEBUG)
+                  .setMode(mode)
                   .build());
     }
     Path out = temp.getRoot().toPath().resolve("all.zip");
diff --git a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java
new file mode 100644
index 0000000..04c1d2e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2017, 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8GMSCoreV10DeployJarVerificationTest extends GMSCoreDeployJarVerificationTest {
+
+  @Test
+  public void buildDebugFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.DEBUG,
+        GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
index d5f23d0..2e076d5 100644
--- a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,18 @@
 public class D8GMSCoreV9DeployJarVerificationTest extends GMSCoreDeployJarVerificationTest {
 
   @Test
-  public void buildFromDeployJar()
+  public void buildDebugFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildFromDeployJar(CompilerUnderTest.D8, GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.DEBUG,
+        GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    buildFromDeployJar(
+        CompilerUnderTest.D8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java
new file mode 100644
index 0000000..5e226bb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8YouTubeDeployJarVerificationTest extends YouTubeCompilationBase {
+
+  @Test
+  public void buildDebugFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.D8, CompilationMode.DEBUG, BASE + APK, null, null, BASE + DEPLOY_JAR);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.D8, CompilationMode.RELEASE, BASE + APK, null, null, BASE + DEPLOY_JAR);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
index ca8d019..1e91e0d 100644
--- a/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -30,14 +31,16 @@
   static final String DEPLOY_JAR = "GmsCore_prod_alldpi_release_all_locales_deploy.jar";
   static final String REFERENCE_APK = "noshrink_x86_GmsCore_prod_alldpi_release_unsigned.apk";
 
-  public void runR8AndCheckVerification(String version)
+  public void runR8AndCheckVerification(CompilationMode mode, String version)
       throws ProguardRuleParserException, ExecutionException, IOException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, version);
+    runAndCheckVerification(CompilerUnderTest.R8, mode, version);
   }
 
-  public void runAndCheckVerification(CompilerUnderTest compiler, String version)
+  public void runAndCheckVerification(
+      CompilerUnderTest compiler, CompilationMode mode, String version)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     runAndCheckVerification(
-        compiler, version + GMSCORE_APK, null, null, Paths.get(version, GMSCORE_APK).toString());
+        compiler, mode, version + GMSCORE_APK, null, null,
+        Paths.get(version, GMSCORE_APK).toString());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
index ecc7451..0a2cdae 100644
--- a/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -11,9 +12,10 @@
 
 public class GMSCoreDeployJarVerificationTest extends GMSCoreCompilationTestBase {
 
-  public void buildFromDeployJar(CompilerUnderTest compiler, String base, boolean hasReference)
+  public void buildFromDeployJar(
+      CompilerUnderTest compiler, CompilationMode mode, String base, boolean hasReference)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     runAndCheckVerification(
-        compiler, hasReference ? base + REFERENCE_APK : null, null, null, base + DEPLOY_JAR);
+        compiler, mode, hasReference ? base + REFERENCE_APK : null, null, null, base + DEPLOY_JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
index 2571490..fecc360 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
@@ -6,6 +6,7 @@
 import static junit.framework.TestCase.assertTrue;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApp;
@@ -18,10 +19,12 @@
 
 public class R8GMSCoreTreeShakeJarVerificationTest extends GMSCoreCompilationTestBase {
 
-  public void buildAndTreeShakeFromDeployJar(String base, boolean hasReference, int maxSize)
+  public void buildAndTreeShakeFromDeployJar(
+      CompilationMode mode, String base, boolean hasReference, int maxSize)
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     AndroidApp app = runAndCheckVerification(
         CompilerUnderTest.R8,
+        mode,
         hasReference ? base + REFERENCE_APK : null,
         null,
         base + PG_CONF,
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
index 5894981..6118b3d 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -17,6 +18,8 @@
   public void buildFromDeployJar()
       // TODO(tamaskenez): set hasReference = true when we have the noshrink file for V10
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildFromDeployJar(CompilerUnderTest.R8, GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+    buildFromDeployJar(
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
index 5253ac2..9572825 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -16,6 +17,7 @@
   public void buildAndTreeShakeFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     // TODO(tamaskenez): set hasReference = true when we have the noshrink file for V10
-    buildAndTreeShakeFromDeployJar(GMSCORE_V10_DIR, false, GMSCORE_V10_MAX_SIZE);
+    buildAndTreeShakeFromDeployJar(
+        CompilationMode.RELEASE, GMSCORE_V10_DIR, false, GMSCORE_V10_MAX_SIZE);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
index d7de82e..0405587 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V4_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V4_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
index 6a098a8..17aab5e 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V5_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V5_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
index b7ca295..d34ad90 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V6_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V6_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
index f65a8e1..2f530f4 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -14,6 +15,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V7_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V7_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
index bc0dbe8..128bd17 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -14,6 +15,6 @@
   @Test
   public void verify()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runR8AndCheckVerification(GMSCORE_V8_DIR);
+    runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V8_DIR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
index d1e6844..bc8c2b6 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -16,6 +17,8 @@
   @Test
   public void buildFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildFromDeployJar(CompilerUnderTest.R8, GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+    buildFromDeployJar(
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
index 2f5ed63..78aa1a3 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
@@ -14,6 +15,7 @@
   @Test
   public void buildAndTreeShakeFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    buildAndTreeShakeFromDeployJar(GMSCORE_V9_DIR, true, GMSCORE_V9_MAX_SIZE);
+    buildAndTreeShakeFromDeployJar(
+        CompilationMode.RELEASE, GMSCORE_V9_DIR, true, GMSCORE_V9_MAX_SIZE);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java b/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
index 08b3892..3e46590 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
@@ -4,7 +4,7 @@
 package com.android.tools.r8.internal;
 
 public abstract class YouTubeCompilationBase extends CompilationTestBase {
-  static final String BASE = "third_party/youtube/youtube.android_11.47/";
+  static final String BASE = "third_party/youtube/youtube.android_12.17/";
   static final String APK = "YouTubeRelease_unsigned.apk";
   static final String DEPLOY_JAR = "YouTubeRelease_deploy.jar";
   static final String PG_JAR = "YouTubeRelease_proguard.jar";
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
index b40ba07..7fbfb2e 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,16 @@
 public class YouTubeDeployJarVerificationTest extends YouTubeCompilationBase {
 
   @Test
-  public void buildFromDeployJar()
+  public void buildDebugFromDeployJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, null, null, BASE + DEPLOY_JAR);
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, null, null, BASE + DEPLOY_JAR);
+  }
+
+  @Test
+  public void buildReleaseFromDeployJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.RELEASE, BASE + APK, null, null, BASE + DEPLOY_JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
index 19bfe25..ba816f1 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,16 @@
 public class YouTubeDexVerificationTest extends YouTubeCompilationBase {
 
   @Test
-  public void buildFromDex()
+  public void buildDebugFromDex()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, BASE + PG_MAP, null, BASE + APK);
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, BASE + PG_MAP, null, BASE + APK);
+  }
+
+  @Test
+  public void buildReleaseFromDex()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.RELEASE, BASE + APK, BASE + PG_MAP, null, BASE + APK);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
index 0b1e553..4bbceeb 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import java.io.IOException;
@@ -13,8 +14,17 @@
 public class YouTubeProguardJarVerificationTest extends YouTubeCompilationBase {
 
   @Test
-  public void buildFromProguardJar()
+  public void buildDebugFromProguardJar()
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
-    runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
+  }
+
+  @Test
+  public void buildReleaseFromProguardJar()
+      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+    runAndCheckVerification(
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
index c51129c..229a6fb 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
@@ -6,6 +6,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApp;
@@ -25,7 +26,8 @@
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
     int maxSize = 16000000;
     AndroidApp app = runAndCheckVerification(
-        CompilerUnderTest.R8, BASE + APK, null, BASE + PG_CONF, BASE + DEPLOY_JAR);
+        CompilerUnderTest.R8, CompilationMode.RELEASE,
+        BASE + APK, null, BASE + PG_CONF, BASE + DEPLOY_JAR);
     int bytes = 0;
     try (Closer closer = Closer.create()) {
       for (InternalResource dex : app.getDexProgramResources()) {
diff --git a/src/test/smali/illegal-invokes/Iface.java b/src/test/smali/illegal-invokes/Iface.java
new file mode 100644
index 0000000..dd11626
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Iface.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, 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.
+
+public class Iface {
+
+  public void bar() {
+  }
+}
diff --git a/src/test/smali/illegal-invokes/Iface.smali b/src/test/smali/illegal-invokes/Iface.smali
new file mode 100644
index 0000000..d66777c
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Iface.smali
@@ -0,0 +1,10 @@
+# Copyright (c) 2017, 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.
+
+.class interface public LIface;
+.super Ljava/lang/Object;
+
+.method public abstract bar()V
+.end method
+
diff --git a/src/test/smali/illegal-invokes/Lowest.java b/src/test/smali/illegal-invokes/Lowest.java
new file mode 100644
index 0000000..e464313
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Lowest.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, 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.
+
+public class Lowest extends Iface implements Super {
+
+  @Override
+  public void foo() {
+
+  }
+}
diff --git a/src/test/smali/illegal-invokes/Lowest.smali b/src/test/smali/illegal-invokes/Lowest.smali
new file mode 100644
index 0000000..d6c5787
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Lowest.smali
@@ -0,0 +1,12 @@
+# Copyright (c) 2017, 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.
+
+.class public LLowest;
+.super LSuper;
+
+.method public bar()V
+    .locals 0
+    return-void
+.end method
+
diff --git a/src/test/smali/illegal-invokes/Super.java b/src/test/smali/illegal-invokes/Super.java
new file mode 100644
index 0000000..54a8714
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Super.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, 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.
+
+public interface Super {
+
+  public void foo();
+}
diff --git a/src/test/smali/illegal-invokes/Super.smali b/src/test/smali/illegal-invokes/Super.smali
new file mode 100644
index 0000000..1ec4f0e
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Super.smali
@@ -0,0 +1,13 @@
+# Copyright (c) 2017, 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.
+
+.class public LSuper;
+.super Ljava/lang/Object;
+.implements LIface;
+
+.method public foo()V
+    .locals 0
+    return-void
+.end method
+
diff --git a/src/test/smali/illegal-invokes/Test.java b/src/test/smali/illegal-invokes/Test.java
new file mode 100644
index 0000000..8ddd18e
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Test.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2017, 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.
+
+public class Test {
+
+  int ignore;
+
+  public static void main(String... args) {
+    Lowest l = new Lowest();
+    callVirtualOnIface(l);
+    callIfaceOnVirtual(l);
+  }
+
+  private static void callVirtualOnIface(Iface i) {
+    try {
+      i.bar();
+    } catch (IncompatibleClassChangeError e) {
+      System.out.println("ICCE");
+    }
+  }
+
+  private static void callIfaceOnVirtual(Super s) {
+    try {
+      s.foo();
+    } catch (IncompatibleClassChangeError e) {
+      System.out.println("ICCE");
+    }
+  }
+}