Fix for KT-12908: Variable initialization in loop causes VerifyError bad local variable type

#KT-12908 Fixed
This commit is contained in:
Michael Bogdanov
2016-07-08 18:06:10 +03:00
parent 00d651711a
commit 486aa5675f
4 changed files with 60 additions and 2 deletions
@@ -561,6 +561,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> impleme
throw new IllegalStateException("Can't get outer value in " + this + " for " + d);
}
private StackValue generateBlock(
private StackValueWithLeaveTask generateBlock(
@NotNull KtBlockExpression block,
@NotNull List<KtExpression> statements,
boolean isStatement,
@@ -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
}
@@ -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
}
@@ -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");