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
|
@Override
|
||||||
public StackValue visitDoWhileExpression(@NotNull JetDoWhileExpression expression, StackValue receiver) {
|
public StackValue visitDoWhileExpression(@NotNull JetDoWhileExpression expression, StackValue receiver) {
|
||||||
Label continueLabel = new Label();
|
Label beginLoopLabel = new Label();
|
||||||
v.mark(continueLabel);
|
v.mark(beginLoopLabel);
|
||||||
|
|
||||||
Label breakLabel = new Label();
|
Label breakLabel = new Label();
|
||||||
|
Label continueLabel = new Label();
|
||||||
|
|
||||||
blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression)));
|
blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression)));
|
||||||
|
|
||||||
@@ -444,17 +445,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
statements.addAll(doWhileStatements);
|
statements.addAll(doWhileStatements);
|
||||||
statements.add(condition);
|
statements.add(condition);
|
||||||
|
|
||||||
conditionValue = generateBlock(statements, true);
|
conditionValue = generateBlock(statements, true, continueLabel);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
gen(body, Type.VOID_TYPE);
|
gen(body, Type.VOID_TYPE);
|
||||||
}
|
}
|
||||||
|
v.mark(continueLabel);
|
||||||
conditionValue = gen(condition);
|
conditionValue = gen(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
conditionValue.condJump(continueLabel, false, v);
|
conditionValue.condJump(beginLoopLabel, false, v);
|
||||||
v.mark(breakLabel);
|
v.mark(breakLabel);
|
||||||
|
|
||||||
blockStackElements.pop();
|
blockStackElements.pop();
|
||||||
@@ -1411,6 +1412,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) {
|
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();
|
Label blockEnd = new Label();
|
||||||
|
|
||||||
List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList();
|
List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList();
|
||||||
@@ -1443,6 +1448,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isExpression = !iterator.hasNext() && lastStatementIsExpression;
|
boolean isExpression = !iterator.hasNext() && lastStatementIsExpression;
|
||||||
|
if (isExpression && labelBeforeLastExpression != null) {
|
||||||
|
v.mark(labelBeforeLastExpression);
|
||||||
|
}
|
||||||
|
|
||||||
StackValue result = isExpression ? gen(statement) : genStatement(statement);
|
StackValue result = isExpression ? gen(statement) : genStatement(statement);
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ public interface JetControlFlowBuilder {
|
|||||||
Label getEntryPoint(@NotNull JetElement labelElement);
|
Label getEntryPoint(@NotNull JetElement labelElement);
|
||||||
@NotNull
|
@NotNull
|
||||||
Label getExitPoint(@NotNull JetElement labelElement);
|
Label getExitPoint(@NotNull JetElement labelElement);
|
||||||
|
@NotNull
|
||||||
|
Label getConditionEntryPoint(@NotNull JetElement labelElement);
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
void declareParameter(@NotNull JetParameter parameter);
|
void declareParameter(@NotNull JetParameter parameter);
|
||||||
|
|||||||
@@ -183,6 +183,12 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
|||||||
return getDelegateBuilder().getExitPoint(labelElement);
|
return getDelegateBuilder().getExitPoint(labelElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Label getConditionEntryPoint(@NotNull JetElement labelElement) {
|
||||||
|
return getDelegateBuilder().getConditionEntryPoint(labelElement);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, Label conditionEntryPoint) {
|
public LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, Label conditionEntryPoint) {
|
||||||
return getDelegateBuilder().enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
return getDelegateBuilder().enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
||||||
|
|||||||
@@ -953,7 +953,11 @@ public class JetControlFlowProcessor {
|
|||||||
JetElement loop = getCorrespondingLoop(expression);
|
JetElement loop = getCorrespondingLoop(expression);
|
||||||
if (loop != null) {
|
if (loop != null) {
|
||||||
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
|
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();
|
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
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Label getExitPoint(@NotNull JetElement labelElement) {
|
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");
|
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")
|
@TestMetadata("emptyDoWhile.kt")
|
||||||
public void testEmptyDoWhile() throws Exception {
|
public void testEmptyDoWhile() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/controlStructures/emptyDoWhile.kt");
|
doTest("compiler/testData/codegen/box/controlStructures/emptyDoWhile.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user