Pseudocode: Track PSI elements which correspond to jump instructions

This commit is contained in:
Alexey Sedunov
2014-04-07 17:41:55 +04:00
parent 103165d674
commit 3952a121fb
15 changed files with 135 additions and 119 deletions
@@ -63,12 +63,12 @@ public interface JetControlFlowBuilder {
void bindLabel(@NotNull Label label);
// Jumps
void jump(@NotNull Label label);
void jumpOnFalse(@NotNull Label label);
void jumpOnTrue(@NotNull Label label);
void nondeterministicJump(@NotNull Label label); // Maybe, jump to label
void nondeterministicJump(@NotNull List<Label> label);
void jumpToError();
void jump(@NotNull Label label, @NotNull JetElement element);
void jumpOnFalse(@NotNull Label label, @NotNull JetElement element);
void jumpOnTrue(@NotNull Label label, @NotNull JetElement element);
void nondeterministicJump(@NotNull Label label, @NotNull JetElement element); // Maybe, jump to label
void nondeterministicJump(@NotNull List<Label> label, @NotNull JetElement element);
void jumpToError(@NotNull JetElement element);
void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine);
void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine);
@@ -100,33 +100,33 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
}
@Override
public void jump(@NotNull Label label) {
getDelegateBuilder().jump(label);
public void jump(@NotNull Label label, @NotNull JetElement element) {
getDelegateBuilder().jump(label, element);
}
@Override
public void jumpOnFalse(@NotNull Label label) {
getDelegateBuilder().jumpOnFalse(label);
public void jumpOnFalse(@NotNull Label label, @NotNull JetElement element) {
getDelegateBuilder().jumpOnFalse(label, element);
}
@Override
public void jumpOnTrue(@NotNull Label label) {
getDelegateBuilder().jumpOnTrue(label);
public void jumpOnTrue(@NotNull Label label, @NotNull JetElement element) {
getDelegateBuilder().jumpOnTrue(label, element);
}
@Override
public void nondeterministicJump(@NotNull Label label) {
getDelegateBuilder().nondeterministicJump(label);
public void nondeterministicJump(@NotNull Label label, @NotNull JetElement element) {
getDelegateBuilder().nondeterministicJump(label, element);
}
@Override
public void nondeterministicJump(@NotNull List<Label> labels) {
getDelegateBuilder().nondeterministicJump(labels);
public void nondeterministicJump(@NotNull List<Label> labels, @NotNull JetElement element) {
getDelegateBuilder().nondeterministicJump(labels, element);
}
@Override
public void jumpToError() {
getDelegateBuilder().jumpToError();
public void jumpToError(@NotNull JetElement element) {
getDelegateBuilder().jumpToError(element);
}
@Override
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
@@ -92,8 +93,12 @@ public class JetControlFlowProcessor {
}
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
JetElement parent = PsiTreeUtil.getParentOfType(subroutine, JetElement.class);
assert parent != null;
Label afterDeclaration = builder.createUnboundLabel();
builder.nondeterministicJump(afterDeclaration);
builder.nondeterministicJump(afterDeclaration, parent);
generate(subroutine);
builder.bindLabel(afterDeclaration);
}
@@ -157,7 +162,10 @@ public class JetControlFlowProcessor {
private void checkNothingType(JetElement element) {
if (!(element instanceof JetExpression)) return;
JetExpression expression = JetPsiUtil.deparenthesize((JetExpression) element);
if (expression == null) return;
if (expression instanceof JetStatementExpression || expression instanceof JetTryExpression
|| expression instanceof JetIfExpression || expression instanceof JetWhenExpression) {
return;
@@ -165,7 +173,7 @@ public class JetControlFlowProcessor {
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
builder.jumpToError();
builder.jumpToError(expression);
}
}
@@ -245,7 +253,7 @@ public class JetControlFlowProcessor {
if (operationType == ANDAND) {
generateInstructions(expression.getLeft(), IN_CONDITION);
Label resultLabel = builder.createUnboundLabel();
builder.jumpOnFalse(resultLabel);
builder.jumpOnFalse(resultLabel, expression);
if (right != null) {
generateInstructions(right, IN_CONDITION);
}
@@ -257,7 +265,7 @@ public class JetControlFlowProcessor {
else if (operationType == OROR) {
generateInstructions(expression.getLeft(), IN_CONDITION);
Label resultLabel = builder.createUnboundLabel();
builder.jumpOnTrue(resultLabel);
builder.jumpOnTrue(resultLabel, expression);
if (right != null) {
generateInstructions(right, IN_CONDITION);
}
@@ -287,7 +295,7 @@ public class JetControlFlowProcessor {
else if (operationType == ELVIS) {
generateInstructions(expression.getLeft(), NOT_IN_CONDITION);
Label afterElvis = builder.createUnboundLabel();
builder.jumpOnTrue(afterElvis);
builder.jumpOnTrue(afterElvis, expression);
if (right != null) {
generateInstructions(right, NOT_IN_CONDITION);
}
@@ -398,7 +406,7 @@ public class JetControlFlowProcessor {
generateInstructions(condition, IN_CONDITION);
}
Label elseLabel = builder.createUnboundLabel();
builder.jumpOnFalse(elseLabel);
builder.jumpOnFalse(elseLabel, expression);
JetExpression thenBranch = expression.getThen();
if (thenBranch != null) {
generateInstructions(thenBranch, context);
@@ -407,7 +415,7 @@ public class JetControlFlowProcessor {
builder.loadUnit(expression);
}
Label resultLabel = builder.createUnboundLabel();
builder.jump(resultLabel);
builder.jump(resultLabel, expression);
builder.bindLabel(elseLabel);
JetExpression elseBranch = expression.getElse();
if (elseBranch != null) {
@@ -472,18 +480,18 @@ public class JetControlFlowProcessor {
Label onException = null;
if (hasCatches) {
onException = builder.createUnboundLabel("onException");
builder.nondeterministicJump(onException);
builder.nondeterministicJump(onException, expression);
}
Label onExceptionToFinallyBlock = null;
if (finallyBlock != null) {
onExceptionToFinallyBlock = builder.createUnboundLabel("onExceptionToFinallyBlock");
builder.nondeterministicJump(onExceptionToFinallyBlock);
builder.nondeterministicJump(onExceptionToFinallyBlock, expression);
}
generateInstructions(expression.getTryBlock(), context);
if (hasCatches) {
Label afterCatches = builder.createUnboundLabel("afterCatches");
builder.jump(afterCatches);
builder.jump(afterCatches, expression);
builder.bindLabel(onException);
LinkedList<Label> catchLabels = Lists.newLinkedList();
@@ -492,7 +500,7 @@ public class JetControlFlowProcessor {
catchLabels.add(builder.createUnboundLabel("catch " + i));
}
if (!catchLabels.isEmpty()) {
builder.nondeterministicJump(catchLabels);
builder.nondeterministicJump(catchLabels, expression);
}
boolean isFirst = true;
for (JetCatchClause catchClause : catchClauses) {
@@ -512,7 +520,7 @@ public class JetControlFlowProcessor {
if (catchBody != null) {
generateInstructions(catchBody, NOT_IN_CONDITION);
}
builder.jump(afterCatches);
builder.jump(afterCatches, expression);
builder.exitLexicalScope(catchClause);
}
@@ -523,10 +531,10 @@ public class JetControlFlowProcessor {
builder.exitTryFinally();
Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
builder.jump(skipFinallyToErrorBlock);
builder.jump(skipFinallyToErrorBlock, expression);
builder.bindLabel(onExceptionToFinallyBlock);
finallyBlockGenerator.generate();
builder.jumpToError();
builder.jumpToError(expression);
builder.bindLabel(skipFinallyToErrorBlock);
finallyBlockGenerator.generate();
@@ -545,7 +553,7 @@ public class JetControlFlowProcessor {
}
boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true);
if (!conditionIsTrueConstant) {
builder.jumpOnFalse(loopInfo.getExitPoint());
builder.jumpOnFalse(loopInfo.getExitPoint(), expression);
}
builder.bindLabel(loopInfo.getBodyEntryPoint());
@@ -553,7 +561,7 @@ public class JetControlFlowProcessor {
if (body != null) {
generateInstructions(body, NOT_IN_CONDITION);
}
builder.jump(loopInfo.getEntryPoint());
builder.jump(loopInfo.getEntryPoint(), expression);
builder.exitLoop(expression);
builder.loadUnit(expression);
}
@@ -574,7 +582,7 @@ public class JetControlFlowProcessor {
if (condition != null) {
generateInstructions(condition, IN_CONDITION);
}
builder.jumpOnTrue(loopInfo.getEntryPoint());
builder.jumpOnTrue(loopInfo.getEntryPoint(), expression);
builder.exitLoop(expression);
builder.loadUnit(expression);
builder.exitLexicalScope(expression);
@@ -595,7 +603,7 @@ public class JetControlFlowProcessor {
Label conditionEntryPoint = builder.createUnboundLabel();
builder.bindLabel(conditionEntryPoint);
builder.nondeterministicJump(loopExitPoint);
builder.nondeterministicJump(loopExitPoint, expression);
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
@@ -607,7 +615,7 @@ public class JetControlFlowProcessor {
generateInstructions(body, NOT_IN_CONDITION);
}
builder.nondeterministicJump(loopInfo.getEntryPoint());
builder.nondeterministicJump(loopInfo.getEntryPoint(), expression);
builder.exitLoop(expression);
builder.loadUnit(expression);
builder.exitLexicalScope(expression);
@@ -642,7 +650,7 @@ public class JetControlFlowProcessor {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
builder.jump(builder.getExitPoint(loop));
builder.jump(builder.getExitPoint(loop), expression);
}
}
@@ -651,7 +659,7 @@ public class JetControlFlowProcessor {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
builder.jump(builder.getEntryPoint(loop));
builder.jump(builder.getEntryPoint(loop), expression);
}
}
@@ -921,18 +929,18 @@ public class JetControlFlowProcessor {
JetWhenCondition condition = conditions[i];
condition.accept(conditionVisitor, context);
if (i + 1 < conditions.length) {
builder.nondeterministicJump(bodyLabel);
builder.nondeterministicJump(bodyLabel, expression);
}
}
if (!isElse) {
nextLabel = builder.createUnboundLabel();
builder.nondeterministicJump(nextLabel);
builder.nondeterministicJump(nextLabel, expression);
}
builder.bindLabel(bodyLabel);
generateInstructions(whenEntry.getExpression(), context);
builder.jump(doneLabel);
builder.jump(doneLabel, expression);
if (!isElse) {
builder.bindLabel(nextLabel);
@@ -243,10 +243,19 @@ public class JetFlowInformationProvider {
private Set<JetElement> collectUnreachableCode() {
Collection<JetElement> unreachableElements = Lists.newArrayList();
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
if (deadInstruction instanceof JetElementInstruction &&
!(deadInstruction instanceof LoadUnitValueInstruction)) {
unreachableElements.add(((JetElementInstruction) deadInstruction).getElement());
if (!(deadInstruction instanceof JetElementInstruction) || deadInstruction instanceof LoadUnitValueInstruction) continue;
JetElement element = ((JetElementInstruction) deadInstruction).getElement();
if (deadInstruction instanceof JumpInstruction) {
boolean isJumpElement = element instanceof JetBreakExpression
|| element instanceof JetContinueExpression
|| element instanceof JetReturnExpression
|| element instanceof JetThrowExpression;
if (!isJumpElement) continue;
}
unreachableElements.add(element);
}
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
return JetPsiUtil.findRootExpressions(unreachableElements);
@@ -18,16 +18,17 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.Collection;
import java.util.Collections;
public abstract class AbstractJumpInstruction extends InstructionImpl {
public abstract class AbstractJumpInstruction extends JetElementInstructionImpl implements JumpInstruction {
private final Label targetLabel;
private Instruction resolvedTarget;
public AbstractJumpInstruction(Label targetLabel, LexicalScope lexicalScope) {
super(lexicalScope);
public AbstractJumpInstruction(@NotNull JetElement element, Label targetLabel, LexicalScope lexicalScope) {
super(element, lexicalScope);
this.targetLabel = targetLabel;
}
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.Arrays;
import java.util.Collection;
@@ -27,8 +28,8 @@ public class ConditionalJumpInstruction extends AbstractJumpInstruction {
private Instruction nextOnTrue;
private Instruction nextOnFalse;
public ConditionalJumpInstruction(boolean onTrue, LexicalScope lexicalScope, Label targetLabel) {
super(targetLabel, lexicalScope);
public ConditionalJumpInstruction(@NotNull JetElement element, boolean onTrue, LexicalScope lexicalScope, Label targetLabel) {
super(element, targetLabel, lexicalScope);
this.onTrue = onTrue;
}
@@ -76,6 +77,6 @@ public class ConditionalJumpInstruction extends AbstractJumpInstruction {
@Override
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
return new ConditionalJumpInstruction(onTrue, lexicalScope, newLabel);
return new ConditionalJumpInstruction(element, onTrue, lexicalScope, newLabel);
}
}
@@ -298,21 +298,21 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
}
@Override
public void jump(@NotNull Label label) {
public void jump(@NotNull Label label, @NotNull JetElement element) {
handleJumpInsideTryFinally(label);
add(new UnconditionalJumpInstruction(label, getCurrentScope()));
add(new UnconditionalJumpInstruction(element, label, getCurrentScope()));
}
@Override
public void jumpOnFalse(@NotNull Label label) {
public void jumpOnFalse(@NotNull Label label, @NotNull JetElement element) {
handleJumpInsideTryFinally(label);
add(new ConditionalJumpInstruction(false, getCurrentScope(), label));
add(new ConditionalJumpInstruction(element, false, getCurrentScope(), label));
}
@Override
public void jumpOnTrue(@NotNull Label label) {
public void jumpOnTrue(@NotNull Label label, @NotNull JetElement element) {
handleJumpInsideTryFinally(label);
add(new ConditionalJumpInstruction(true, getCurrentScope(), label));
add(new ConditionalJumpInstruction(element, true, getCurrentScope(), label));
}
@Override
@@ -321,22 +321,22 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
}
@Override
public void nondeterministicJump(@NotNull Label label) {
public void nondeterministicJump(@NotNull Label label, @NotNull JetElement element) {
handleJumpInsideTryFinally(label);
add(new NondeterministicJumpInstruction(label, getCurrentScope()));
add(new NondeterministicJumpInstruction(element, label, getCurrentScope()));
}
@Override
public void nondeterministicJump(@NotNull List<Label> labels) {
public void nondeterministicJump(@NotNull List<Label> labels, @NotNull JetElement element) {
//todo
//handleJumpInsideTryFinally(label);
add(new NondeterministicJumpInstruction(labels, getCurrentScope()));
add(new NondeterministicJumpInstruction(element, labels, getCurrentScope()));
}
@Override
public void jumpToError() {
public void jumpToError(@NotNull JetElement element) {
handleJumpInsideTryFinally(error);
add(new UnconditionalJumpInstruction(error, getCurrentScope()));
add(new UnconditionalJumpInstruction(element, error, getCurrentScope()));
}
@Override
@@ -350,6 +350,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
add(new ThrowExceptionInstruction(expression, getCurrentScope(), error));
}
@Override
public void exitTryFinally() {
BlockInfo pop = allBlocks.pop();
assert pop instanceof TryFinallyBlockInfo;
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg.pseudocode;/**/
public interface JumpInstruction extends Instruction {
}
@@ -20,22 +20,23 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.*;
public class NondeterministicJumpInstruction extends InstructionImpl{
public class NondeterministicJumpInstruction extends JetElementInstructionImpl implements JumpInstruction {
private Instruction next;
private final List<Label> targetLabels;
private final Map<Label, Instruction> resolvedTargets;
public NondeterministicJumpInstruction(List<Label> targetLabels, LexicalScope lexicalScope) {
super(lexicalScope);
public NondeterministicJumpInstruction(@NotNull JetElement element, List<Label> targetLabels, LexicalScope lexicalScope) {
super(element, lexicalScope);
this.targetLabels = Lists.newArrayList(targetLabels);
resolvedTargets = Maps.newLinkedHashMap();
}
public NondeterministicJumpInstruction(Label targetLabel, LexicalScope lexicalScope) {
this(Lists.newArrayList(targetLabel), lexicalScope);
public NondeterministicJumpInstruction(@NotNull JetElement element, Label targetLabel, LexicalScope lexicalScope) {
this(element, Lists.newArrayList(targetLabel), lexicalScope);
}
public List<Label> getTargetLabels() {
@@ -103,6 +104,6 @@ public class NondeterministicJumpInstruction extends InstructionImpl{
}
private Instruction createCopy(@NotNull List<Label> newTargetLabels) {
return new NondeterministicJumpInstruction(newTargetLabels, lexicalScope);
return new NondeterministicJumpInstruction(getElement(), newTargetLabels, lexicalScope);
}
}
@@ -21,18 +21,8 @@ import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
public class ReturnNoValueInstruction extends AbstractJumpInstruction implements ReturnInstruction {
private final JetElement element;
public ReturnNoValueInstruction(@NotNull JetElement element, LexicalScope lexicalScope, Label targetLabel) {
super(targetLabel, lexicalScope);
this.element = element;
}
@NotNull
@Override
public JetElement getElement() {
return element;
super(element, targetLabel, lexicalScope);
}
@Override
@@ -18,20 +18,18 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
public class ReturnValueInstruction extends AbstractJumpInstruction implements ReturnInstruction {
private final JetElement element;
public ReturnValueInstruction(@NotNull JetExpression returnExpression, @NotNull LexicalScope lexicalScope, @NotNull Label targetLabel) {
super(targetLabel, lexicalScope);
this.element = returnExpression;
public ReturnValueInstruction(
@NotNull JetExpression returnExpression,
@NotNull LexicalScope lexicalScope,
@NotNull Label targetLabel) {
super(returnExpression, targetLabel, lexicalScope);
}
@Override
public void accept(InstructionVisitor visitor) {
public void accept(@NotNull InstructionVisitor visitor) {
visitor.visitReturnValue(this);
}
@@ -45,12 +43,6 @@ public class ReturnValueInstruction extends AbstractJumpInstruction implements R
return "ret(*) " + getTargetLabel();
}
@NotNull
@Override
public JetElement getElement() {
return element;
}
@Override
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
return new ReturnValueInstruction((JetExpression) element, lexicalScope, newLabel);
@@ -18,26 +18,20 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetThrowExpression;
public class ThrowExceptionInstruction extends AbstractJumpInstruction implements JetElementInstruction {
private final JetThrowExpression expression;
public ThrowExceptionInstruction(@NotNull JetThrowExpression expression, @NotNull LexicalScope lexicalScope, @NotNull Label errorLabel) {
super(errorLabel, lexicalScope);
this.expression = expression;
}
@NotNull
@Override
public JetExpression getElement() {
return expression;
public class ThrowExceptionInstruction extends AbstractJumpInstruction {
public ThrowExceptionInstruction(
@NotNull JetThrowExpression expression,
@NotNull LexicalScope lexicalScope,
@NotNull Label errorLabel
) {
super(expression, errorLabel, lexicalScope);
}
@Override
public String toString() {
return "throw (" + expression.getText() + ")";
return "throw (" + element.getText() + ")";
}
@Override
@@ -52,6 +46,6 @@ public class ThrowExceptionInstruction extends AbstractJumpInstruction implement
@Override
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
return new ThrowExceptionInstruction(expression, lexicalScope, newLabel);
return new ThrowExceptionInstruction((JetThrowExpression) element, lexicalScope, newLabel);
}
}
@@ -18,12 +18,11 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement;
public class UnconditionalJumpInstruction extends AbstractJumpInstruction {
public UnconditionalJumpInstruction(Label targetLabel, @NotNull LexicalScope lexicalScope) {
super(targetLabel, lexicalScope);
public UnconditionalJumpInstruction(@NotNull JetElement element, Label targetLabel, @NotNull LexicalScope lexicalScope) {
super(element, targetLabel, lexicalScope);
}
@Override
@@ -43,6 +42,6 @@ public class UnconditionalJumpInstruction extends AbstractJumpInstruction {
@Override
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
return new UnconditionalJumpInstruction(newLabel, lexicalScope);
return new UnconditionalJumpInstruction(element, newLabel, lexicalScope);
}
}
@@ -5,7 +5,7 @@ class C {
@a {
<!NOT_A_LOOP_LABEL!>break@f<!>
break
break@b
<!UNREACHABLE_CODE!>break@b<!>
<!NOT_A_LOOP_LABEL!>break@a<!>
})
@@ -15,7 +15,7 @@ class C {
@a {
<!NOT_A_LOOP_LABEL!>continue@f<!>
continue
continue@b
<!UNREACHABLE_CODE!>continue@b<!>
<!NOT_A_LOOP_LABEL!>continue@a<!>
})
@@ -82,4 +82,4 @@ class C {
}
a<!UNSAFE_CALL!>.<!>compareTo("2")
}
}
}
+2 -2
View File
@@ -5,7 +5,7 @@ class C {
@a {
<error>break@f</error>
break
break@b
<warning>break@b</warning>
<error>break@a</error>
})
@@ -15,7 +15,7 @@ class C {
@a {
<error>continue@f</error>
continue
continue@b
<warning>continue@b</warning>
<error>continue@a</error>
})