fix KT-5645: 'continue' inside 'do...while' statement works as goto to the beginning of the loop (not checking loop condition)

#KT-5645 Fixed
This commit is contained in:
Michael Nedzelsky
2014-08-26 16:47:22 +04:00
committed by Svetlana Isakova
parent 3d7c22f242
commit 25a0854dbd
7 changed files with 60 additions and 6 deletions
@@ -424,10 +424,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitDoWhileExpression(@NotNull JetDoWhileExpression expression, StackValue receiver) {
Label continueLabel = new Label();
v.mark(continueLabel);
Label beginLoopLabel = new Label();
v.mark(beginLoopLabel);
Label breakLabel = new Label();
Label continueLabel = new Label();
blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression)));
@@ -444,17 +445,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
statements.addAll(doWhileStatements);
statements.add(condition);
conditionValue = generateBlock(statements, true);
conditionValue = generateBlock(statements, true, continueLabel);
}
else {
if (body != null) {
gen(body, Type.VOID_TYPE);
}
v.mark(continueLabel);
conditionValue = gen(condition);
}
conditionValue.condJump(continueLabel, false, v);
conditionValue.condJump(beginLoopLabel, false, v);
v.mark(breakLabel);
blockStackElements.pop();
@@ -1411,6 +1412,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) {
return generateBlock(statements, lastStatementIsExpression, null);
}
private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression, Label labelBeforeLastExpression) {
Label blockEnd = new Label();
List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList();
@@ -1443,6 +1448,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
boolean isExpression = !iterator.hasNext() && lastStatementIsExpression;
if (isExpression && labelBeforeLastExpression != null) {
v.mark(labelBeforeLastExpression);
}
StackValue result = isExpression ? gen(statement) : genStatement(statement);
@@ -52,6 +52,8 @@ public interface JetControlFlowBuilder {
Label getEntryPoint(@NotNull JetElement labelElement);
@NotNull
Label getExitPoint(@NotNull JetElement labelElement);
@NotNull
Label getConditionEntryPoint(@NotNull JetElement labelElement);
// Declarations
void declareParameter(@NotNull JetParameter parameter);
@@ -183,6 +183,12 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
return getDelegateBuilder().getExitPoint(labelElement);
}
@NotNull
@Override
public Label getConditionEntryPoint(@NotNull JetElement labelElement) {
return getDelegateBuilder().getConditionEntryPoint(labelElement);
}
@Override
public LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, Label conditionEntryPoint) {
return getDelegateBuilder().enterLoop(expression, loopExitPoint, conditionEntryPoint);
@@ -953,7 +953,11 @@ public class JetControlFlowProcessor {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
builder.jump(builder.getEntryPoint(loop), expression);
if (loop instanceof JetDoWhileExpression) {
builder.jump(builder.getConditionEntryPoint(loop), expression);
} else {
builder.jump(builder.getEntryPoint(loop), expression);
}
}
}
@@ -200,6 +200,14 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
return elementToBlockInfo.get(labelElement).getEntryPoint();
}
@NotNull
@Override
public Label getConditionEntryPoint(@NotNull JetElement labelElement) {
BreakableBlockInfo blockInfo = elementToBlockInfo.get(labelElement);
assert blockInfo instanceof LoopInfo : "expected LoopInfo for " + labelElement.getText() ;
return ((LoopInfo)blockInfo).getConditionEntryPoint();
}
@NotNull
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
@@ -0,0 +1,21 @@
fun box(): String {
var i = 0
do {
if (i++ > 100) break;
continue;
} while(false)
if (i != 1) return "Fail 1, expected 1, but $i"
i = 0
do {
if (i++ > 100) break;
continue;
} while(i<10)
if (i != 10) return "Fail 2, expected 10, but $i"
i = 0
do continue while(i++<10)
if (i != 11) return "Fail 3, expected 11, but $i"
return "OK"
}
@@ -1468,6 +1468,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/controlStructures/doWhileFib.kt");
}
@TestMetadata("doWhileWithContinue.kt")
public void testDoWhileWithContinue() throws Exception {
doTest("compiler/testData/codegen/box/controlStructures/doWhileWithContinue.kt");
}
@TestMetadata("emptyDoWhile.kt")
public void testEmptyDoWhile() throws Exception {
doTest("compiler/testData/codegen/box/controlStructures/emptyDoWhile.kt");