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 ecef50945a5..490b71d337a 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 @@ -29694,6 +29694,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @Test + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @Test + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @Test + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @Test @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() 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 562926ff256..b0d9c7f6fb7 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 @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol @@ -1061,9 +1062,47 @@ class ExpressionCodegen( val entry = markNewLabel() val endLabel = linkedLabel() val continueLabel = linkedLabel() + + val loopInfo = LoopInfo(loop, continueLabel, endLabel) + + // If we have a 'for' loop transformed into a 'do-while' loop, + // then corresponding loop variable initialization should happen before we mark loop end and loop continue labels, + // because loop variable can be used in the loop condition, + // and corresponding slot might contain arbitrary garbage left over from previous computations (see KT-47492). + // TODO consider adding special intrinsics for loop body markers instead of generating them manually. + if (loop.origin == IrStatementOrigin.FOR_LOOP_INNER_WHILE) { + val body = loop.body + if (body is IrComposite && body.origin == IrStatementOrigin.FOR_LOOP_INNER_WHILE && body.statements.isNotEmpty()) { + val forLoopNext = body.statements[0] + if (forLoopNext is IrComposite && forLoopNext.origin == IrStatementOrigin.FOR_LOOP_NEXT) { + // We have a 'for' loop transformed into a 'do-while' loop. + // Generate it's loop variable initialization, + // then mark loop end and loop continue labels, + // then generate the for loop body. + val forLoopBody = IrCompositeImpl( + body.startOffset, body.endOffset, body.type, body.origin, + body.statements.subList(1, body.statements.size) + ) + data.withBlock(loopInfo) { + forLoopNext.accept(this, data).discard() + mv.fakeAlwaysFalseIfeq(continueLabel) + mv.fakeAlwaysFalseIfeq(endLabel) + forLoopBody.accept(this, data).discard() + mv.visitLabel(continueLabel) + loop.condition.markLineNumber(true) + loop.condition.accept(this, data).coerceToBoolean().jumpIfTrue(entry) + } + mv.mark(endLabel) + addInlineMarker(mv, false) + return unitValue + } + } + } + + // We have a regular 'do-while' loop. Proceed as usual. mv.fakeAlwaysFalseIfeq(continueLabel) mv.fakeAlwaysFalseIfeq(endLabel) - data.withBlock(LoopInfo(loop, continueLabel, endLabel)) { + data.withBlock(loopInfo) { loop.body?.accept(this, data)?.discard() mv.visitLabel(continueLabel) loop.condition.markLineNumber(true) diff --git a/compiler/testData/codegen/box/ranges/kt47492.kt b/compiler/testData/codegen/box/ranges/kt47492.kt new file mode 100644 index 00000000000..ab44ed40f76 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/kt47492.kt @@ -0,0 +1,11 @@ +// DONT_TARGET_EXACT_BACKEND: WASM +// WITH_RUNTIME + +fun p() {} + +fun box(): String { + var sum = 1 + for (i: Int? in sum downTo sum.toULong().countTrailingZeroBits()) + p() + return "OK" +} diff --git a/compiler/testData/codegen/box/ranges/kt47492a.kt b/compiler/testData/codegen/box/ranges/kt47492a.kt new file mode 100644 index 00000000000..6954ac3dcc4 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/kt47492a.kt @@ -0,0 +1,20 @@ +// DONT_TARGET_EXACT_BACKEND: WASM +// WITH_RUNTIME + +fun a() = 5 +fun b() = 1 +fun p() {} + +fun box(): String { + when (false) { + else -> { + val h1 = 1 + val h2 = 2L + val h3 = 3L + } + } + var sum = 1 + for (i: Int? in a() downTo b()) + p() + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/kt47492b.kt b/compiler/testData/codegen/box/ranges/kt47492b.kt new file mode 100644 index 00000000000..ba164dbc9a0 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/kt47492b.kt @@ -0,0 +1,19 @@ +// DONT_TARGET_EXACT_BACKEND: WASM +// WITH_RUNTIME + +fun a() = 5 +fun b() = 1 + +fun p() {} + +fun box(): String { + try { + val h1 = 1 + val h2 = 2L + val h3 = 3L + } catch (e: Exception) { throw e } + var sum = 1 + for (i: Int? in a() downTo b()) + p() + return "OK" +} \ No newline at end of file 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 51d9a7b7dae..80524f8c49f 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 @@ -29652,6 +29652,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @Test + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @Test + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @Test + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @Test @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() 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 4e2b9d14e7d..f56f12735e0 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 @@ -29694,6 +29694,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @Test + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @Test + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @Test + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @Test @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() 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 0ab19bf9830..1fef11db3a2 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -25203,6 +25203,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() throws Exception { runTest("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.kt"); 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 564b73d2989..24f0b52d6c3 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 @@ -19942,6 +19942,21 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() throws Exception { runTest("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.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 17cf357a9ec..11c5ed765f4 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 @@ -19348,6 +19348,21 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() throws Exception { runTest("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.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 1c2a63b2d35..c7a63877a91 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 @@ -19398,6 +19398,21 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/ranges/kt37370a.kt"); } + @TestMetadata("kt47492.kt") + public void testKt47492() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492.kt"); + } + + @TestMetadata("kt47492a.kt") + public void testKt47492a() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492a.kt"); + } + + @TestMetadata("kt47492b.kt") + public void testKt47492b() throws Exception { + runTest("compiler/testData/codegen/box/ranges/kt47492b.kt"); + } + @TestMetadata("multiAssignmentIterationOverIntRange.kt") public void testMultiAssignmentIterationOverIntRange() throws Exception { runTest("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.kt");