From 486aa5675f79c3852225dd16ac474da335684371 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Fri, 8 Jul 2016 18:06:10 +0300 Subject: [PATCH] Fix for KT-12908: Variable initialization in loop causes VerifyError bad local variable type #KT-12908 Fixed --- .../kotlin/codegen/ExpressionCodegen.java | 10 ++++++++-- .../codegen/box/controlStructures/kt12908.kt | 20 +++++++++++++++++++ .../box/controlStructures/kt12908_2.kt | 20 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 12 +++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/controlStructures/kt12908.kt create mode 100644 compiler/testData/codegen/box/controlStructures/kt12908_2.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index b56beabd1cd..c24f937d23f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -561,6 +561,7 @@ public class ExpressionCodegen extends KtVisitor impleme KtExpression condition = expression.getCondition(); StackValue conditionValue; + StackValueWithLeaveTask leaveTask = null; if (body instanceof KtBlockExpression) { // If body's a block, it can contain variable declarations which may be used in the condition of a do-while loop. // We handle this case separately because otherwise such variable will be out of the frame map after the block ends @@ -570,7 +571,9 @@ public class ExpressionCodegen extends KtVisitor impleme statements.addAll(doWhileStatements); statements.add(condition); - conditionValue = generateBlock((KtBlockExpression) body, statements, false, continueLabel, null); + //Need to split leave task and condition cause otherwise BranchedValue optimizations wouldn't work + leaveTask = generateBlock((KtBlockExpression) body, statements, false, continueLabel, null); + conditionValue = leaveTask.getStackValue(); } else { if (body != null) { @@ -581,6 +584,9 @@ public class ExpressionCodegen extends KtVisitor impleme } BranchedValue.Companion.loopJump(conditionValue, beginLoopLabel, false, v); + if (leaveTask != null) { + leaveTask.getLeaveTasks().invoke(conditionValue); + } v.mark(breakLabel); blockStackElements.pop(); @@ -1759,7 +1765,7 @@ public class ExpressionCodegen extends KtVisitor impleme throw new IllegalStateException("Can't get outer value in " + this + " for " + d); } - private StackValue generateBlock( + private StackValueWithLeaveTask generateBlock( @NotNull KtBlockExpression block, @NotNull List statements, boolean isStatement, diff --git a/compiler/testData/codegen/box/controlStructures/kt12908.kt b/compiler/testData/codegen/box/controlStructures/kt12908.kt new file mode 100644 index 00000000000..e35d92b93dc --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/kt12908.kt @@ -0,0 +1,20 @@ +var field: Int = 0 + +fun next(): Int { + return ++field +} + + +fun box(): String { + val task: String + + do { + if (next() % 2 == 0) { + task = "OK" + break + } + } + while (true) + + return task +} diff --git a/compiler/testData/codegen/box/controlStructures/kt12908_2.kt b/compiler/testData/codegen/box/controlStructures/kt12908_2.kt new file mode 100644 index 00000000000..f4fd0e0555e --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/kt12908_2.kt @@ -0,0 +1,20 @@ +var field: Int = 0 + +fun next(): Int { + return ++field +} + + +fun box(): String { + val task: String + + do { + if (next() % 2 == 0) { + task = "OK" + break + } + } + while (!false) + + return task +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index c842ac1134e..2ab6fc248bc 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -3673,6 +3673,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kt12908.kt") + public void testKt12908() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/kt12908.kt"); + doTest(fileName); + } + + @TestMetadata("kt12908_2.kt") + public void testKt12908_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/kt12908_2.kt"); + doTest(fileName); + } + @TestMetadata("kt1441.kt") public void testKt1441() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/kt1441.kt");