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:
committed by
Svetlana Isakova
parent
3d7c22f242
commit
25a0854dbd
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user