From b3e075173b79fa1b501d30d12dff59206564409c Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Fri, 26 Sep 2014 11:03:19 +0400 Subject: [PATCH] KT-5863: Inlined try/catch/finally block with non-local return doesn't work properly #KT-5863 Fixed --- .../jetbrains/jet/codegen/inline/MethodInliner.java | 11 ++++++++--- .../codegen/boxInline/tryCatchFinally/kt5863.1.kt | 6 ++++++ .../codegen/boxInline/tryCatchFinally/kt5863.2.kt | 9 +++++++++ .../generated/BlackBoxInlineCodegenTestGenerated.java | 6 ++++++ ...CompileKotlinAgainstInlineKotlinTestGenerated.java | 6 ++++++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.1.kt create mode 100644 compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.2.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java index 3d5673517de..14288988580 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java @@ -354,7 +354,7 @@ public class MethodInliner { AbstractInsnNode cur = node.instructions.getFirst(); int index = 0; - Set deadLabels = new HashSet(); + Set possibleDeadLabels = new HashSet(); while (cur != null) { Frame frame = sources[index]; @@ -414,10 +414,15 @@ public class MethodInliner { if (frame == null) { //clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems if (prevNode.getType() == AbstractInsnNode.LABEL) { - deadLabels.add((LabelNode) prevNode); + possibleDeadLabels.add((LabelNode) prevNode); } else { node.instructions.remove(prevNode); } + } else { + //Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression) + //it may occurs that interval for default handler starts before catch start label, so this label seems as dead, + //but as result all this labels will be merged into one (see KT-5863) + possibleDeadLabels.remove(prevNode.getPrevious()); } } @@ -425,7 +430,7 @@ public class MethodInliner { List blocks = node.tryCatchBlocks; for (Iterator iterator = blocks.iterator(); iterator.hasNext(); ) { TryCatchBlockNode block = iterator.next(); - if (deadLabels.contains(block.start) && deadLabels.contains(block.end)) { + if (possibleDeadLabels.contains(block.start) && possibleDeadLabels.contains(block.end)) { iterator.remove(); } } diff --git a/compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.1.kt b/compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.1.kt new file mode 100644 index 00000000000..0e32fe8b179 --- /dev/null +++ b/compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.1.kt @@ -0,0 +1,6 @@ +inline fun test2Inline() = performWithFinally { "OK" } + +fun box(): String { + return test2Inline() +} + diff --git a/compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.2.kt b/compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.2.kt new file mode 100644 index 00000000000..d172192f052 --- /dev/null +++ b/compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.2.kt @@ -0,0 +1,9 @@ +inline fun performWithFinally(finally: () -> R) : R { + try { + throw RuntimeException("1") + } catch (e: RuntimeException) { + throw RuntimeException("2") + } finally { + return finally() + } +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java index 687f0ce3edb..872434294db 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -745,6 +745,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/tryCatchFinally"), Pattern.compile("^(.+)\\.1.kt$"), true); } + @TestMetadata("kt5863.1.kt") + public void testKt5863() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + @TestMetadata("tryCatch.1.kt") public void testTryCatch() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/tryCatchFinally/tryCatch.1.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index 1d37956aea6..78860bbb060 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -745,6 +745,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/tryCatchFinally"), Pattern.compile("^(.+)\\.1.kt$"), true); } + @TestMetadata("kt5863.1.kt") + public void testKt5863() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/tryCatchFinally/kt5863.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + @TestMetadata("tryCatch.1.kt") public void testTryCatch() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/tryCatchFinally/tryCatch.1.kt");