Merge "Test for "R8/CF does not merge identical catch handlers""
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 68d87c1..0a4416a 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -793,12 +793,22 @@
   }
 
   public static R8Command.Builder prepareR8CommandBuilder(AndroidApp app) {
-    return R8Command.builder(app).setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+    return prepareR8CommandBuilder(app, DexIndexedConsumer.emptyConsumer());
+  }
+
+  public static R8Command.Builder prepareR8CommandBuilder(
+      AndroidApp app, ProgramConsumer programConsumer) {
+    return R8Command.builder(app).setProgramConsumer(programConsumer);
   }
 
   public static AndroidApp runR8(AndroidApp app) throws IOException {
+    return runR8WithProgramConsumer(app, DexIndexedConsumer.emptyConsumer());
+  }
+
+  public static AndroidApp runR8WithProgramConsumer(AndroidApp app, ProgramConsumer programConsumer)
+      throws IOException {
     try {
-      return runR8(prepareR8CommandBuilder(app).build());
+      return runR8(prepareR8CommandBuilder(app, programConsumer).build());
     } catch (CompilationFailedException e) {
       throw new RuntimeException(e);
     }
diff --git a/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
new file mode 100644
index 0000000..fd696bc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
@@ -0,0 +1,88 @@
+// Copyright (c) 2018, 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.cf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfTryCatch;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexCode.Try;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.google.common.collect.Sets;
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
+import it.unimi.dsi.fastutil.ints.IntSet;
+import java.nio.file.Paths;
+import java.util.Set;
+import org.junit.Test;
+
+public class IdenticalCatchHandlerTest extends TestBase {
+
+  private static class TestClass {
+    public void foo(Object a, Object b, Object c) {
+      if (a == null) {
+        try {
+          System.out.println(b.toString());
+        } catch (RuntimeException e) {
+        }
+      } else {
+        try {
+          System.out.println(c.toString());
+        } catch (RuntimeException e) {
+        }
+      }
+      System.out.println("Hello");
+    }
+  }
+
+  @Test
+  public void test() throws Exception {
+    byte[] inputBytes = ToolHelper.getClassAsBytes(TestClass.class);
+    AndroidApp inputApp =
+        AndroidApp.builder()
+            .addClassProgramData(inputBytes, Origin.unknown())
+            .addLibraryFiles(Paths.get(ToolHelper.JAVA_8_RUNTIME))
+            .build();
+    assertEquals(2, countCatchHandlers(inputApp));
+    AndroidApp outputDexApp = ToolHelper.runR8(inputApp);
+    assertEquals(1, countCatchHandlers(outputDexApp));
+    AndroidApp outputCfApp =
+        ToolHelper.runR8WithProgramConsumer(inputApp, ClassFileConsumer.emptyConsumer());
+    // TODO(b/80514966): Change to assertEquals when fixed.
+    assertNotEquals(1, countCatchHandlers(outputCfApp));
+  }
+
+  private int countCatchHandlers(AndroidApp inputApp) throws Exception {
+    DexInspector inspector = new DexInspector(inputApp, o -> o.enableCfFrontend = true);
+    DexClass dexClass = inspector.clazz(TestClass.class).getDexClass();
+    Code code = dexClass.virtualMethods()[0].getCode();
+    if (code.isCfCode()) {
+      CfCode cfCode = code.asCfCode();
+      Set<CfLabel> targets = Sets.newIdentityHashSet();
+      for (CfTryCatch tryCatch : cfCode.getTryCatchRanges()) {
+        targets.addAll(tryCatch.targets);
+      }
+      return targets.size();
+    } else if (code.isDexCode()) {
+      DexCode dexCode = code.asDexCode();
+      IntSet targets = new IntOpenHashSet();
+      for (Try aTry : dexCode.tries) {
+        targets.add(aTry.handlerOffset);
+      }
+      return targets.size();
+    } else {
+      throw new Unimplemented(code.getClass().getName());
+    }
+  }
+}