From 8588412a56999d997a99e8349b61160d6ff3ad6a Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Fri, 5 Mar 2021 12:30:12 +0100 Subject: [PATCH] [JVM IR] Support break in do-while condition. This breaks from the loop itself which is inconsistent with what happens for breaks in while conditions. Also, the frontend will report that code after the loop is unreachable, which it isn't. :-\ However, those issues are covered in https://youtrack.jetbrains.com/issue/KT-17728, so for now we follow the old backend to not "break" anyone. :) Fixes KT-44412 --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../backend/jvm/codegen/ExpressionCodegen.kt | 6 +-- .../breakInLoopConditions.kt | 39 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ .../IrCodegenBoxWasmTestGenerated.java | 5 +++ 10 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index f06180b9cb0..adcf3c5c73d 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -7843,6 +7843,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @Test + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @Test @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 0831392f7c8..fb439eb082f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -1061,10 +1061,10 @@ class ExpressionCodegen( mv.fakeAlwaysFalseIfeq(endLabel) data.withBlock(LoopInfo(loop, continueLabel, endLabel)) { loop.body?.accept(this, data)?.discard() + mv.visitLabel(continueLabel) + loop.condition.markLineNumber(true) + loop.condition.accept(this, data).coerceToBoolean().jumpIfTrue(entry) } - mv.visitLabel(continueLabel) - loop.condition.markLineNumber(true) - loop.condition.accept(this, data).coerceToBoolean().jumpIfTrue(entry) mv.mark(endLabel) addInlineMarker(mv, false) return unitValue diff --git a/compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt b/compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt new file mode 100644 index 00000000000..2ab064c5341 --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt @@ -0,0 +1,39 @@ +// See: https://youtrack.jetbrains.com/issue/KT-45319 +// IGNORE_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// IGNORE_BACKEND: JS + +fun breakInDoWhileCondition(): String { + var i = 0 + while (true) { + ++i + var j = 0 + do { + ++j + } while (break) + if (j != 1) return "FAIL1" + if (i == 3) break + } + if (i != 3) return "FAIL2" + return "OK" +} + +fun breakInWhileCondition(): String { + var i = 0 + while (true) { + ++i + var j = 0 + while (break) { + j++ + } + return "FAIL3" + } + if (i != 1) return "FAIL4" + return "OK" +} + +fun box(): String { + val breakInDoWhileResult = breakInDoWhileCondition() + if (breakInDoWhileResult != "OK") return breakInDoWhileResult + return breakInWhileCondition() +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index c32f1d039ca..a457d16c748 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -7843,6 +7843,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @Test + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @Test @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 2ccf27bf5dc..f4f0f6c2b7d 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -7843,6 +7843,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @Test + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @Test @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 409c454ab0c..a21992f49ea 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6036,6 +6036,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class BreakContinueInExpressions extends AbstractLightAnalysisModeTest { + @TestMetadata("breakInLoopConditions.kt") + public void ignoreBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 8c5b2c9fb95..ed13db9eda1 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -5322,6 +5322,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/continueInDoWhile.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 0c771a767ad..e3fe07105d5 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -4779,6 +4779,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/continueInDoWhile.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9432a0896fd..fc2b251625f 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -4779,6 +4779,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/continueInDoWhile.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 2876d70def3..cff81972b95 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -3372,6 +3372,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInExpr.kt"); } + @TestMetadata("breakInLoopConditions.kt") + public void testBreakInLoopConditions() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/breakInLoopConditions.kt"); + } + @TestMetadata("continueInDoWhile.kt") public void testContinueInDoWhile() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/continueInDoWhile.kt");