KT-58 Allow finally around definite returns

This commit is contained in:
svtk
2011-11-08 16:25:04 +04:00
parent f47f462dca
commit dfb17a5f0e
10 changed files with 654 additions and 228 deletions
@@ -18,6 +18,7 @@ public interface JetControlFlowBuilder {
Label createUnboundLabel();
void bindLabel(@NotNull Label label);
void allowDead();
// Jumps
void jump(@NotNull Label label);
@@ -37,6 +37,12 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
builder.bindLabel(label);
}
@Override
public void allowDead() {
assert builder != null;
builder.allowDead();
}
@Override
public void jump(@NotNull Label label) {
assert builder != null;
@@ -5,18 +5,19 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
@@ -356,18 +357,35 @@ public class JetControlFlowProcessor {
});
}
Label onException = builder.createUnboundLabel();
builder.nondeterministicJump(onException);
List<JetCatchClause> catchClauses = expression.getCatchClauses();
final boolean hasCatches = !catchClauses.isEmpty();
Label onException = null;
if (hasCatches) {
onException = builder.createUnboundLabel();
builder.nondeterministicJump(onException);
}
value(expression.getTryBlock(), inCondition);
List<JetCatchClause> catchClauses = expression.getCatchClauses();
if (!catchClauses.isEmpty()) {
if (hasCatches) {
builder.allowDead();
Label afterCatches = builder.createUnboundLabel();
builder.jump(afterCatches);
builder.bindLabel(onException);
for (Iterator<JetCatchClause> iterator = catchClauses.iterator(); iterator.hasNext(); ) {
JetCatchClause catchClause = iterator.next();
LinkedList<Label> catchLabels = Lists.newLinkedList();
int catchClausesSize = catchClauses.size();
for (int i = 0; i < catchClausesSize - 1; i++) {
catchLabels.add(builder.createUnboundLabel());
}
builder.nondeterministicJump(catchLabels);
boolean isFirst = true;
for (JetCatchClause catchClause : catchClauses) {
if (!isFirst) {
builder.bindLabel(catchLabels.remove());
}
else {
isFirst = false;
}
JetParameter catchParameter = catchClause.getCatchParameter();
if (catchParameter != null) {
builder.write(catchParameter, catchParameter);
@@ -376,14 +394,14 @@ public class JetControlFlowProcessor {
if (catchBody != null) {
value(catchBody, false);
}
if (iterator.hasNext()) {
builder.nondeterministicJump(afterCatches);
}
builder.allowDead();
builder.jump(afterCatches);
}
builder.bindLabel(afterCatches);
} else {
builder.bindLabel(onException);
}
else {
builder.allowDead();
}
if (finallyBlock != null) {
@@ -243,6 +243,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
pseudocode.bindLabel(label);
}
@Override
public void allowDead() {
Label allowedDeadLabel = createUnboundLabel();
bindLabel(allowedDeadLabel);
pseudocode.allowDead(allowedDeadLabel);
}
@Override
public void nondeterministicJump(Label label) {
handleJumpInsideTryFinally(label);
@@ -17,7 +17,7 @@ public class NondeterministicJumpInstruction extends InstructionImpl{
private final Map<Label, Instruction> resolvedTargets;
public NondeterministicJumpInstruction(List<Label> targetLabels) {
this.targetLabels = targetLabels;
this.targetLabels = Lists.newArrayList(targetLabels);
resolvedTargets = Maps.newLinkedHashMap();
}
@@ -44,18 +44,20 @@ public class Pseudocode {
@Nullable
private List<Instruction> resolve() {
assert targetInstructionIndex != null;
return instructions.subList(getTargetInstructionIndex(), instructions.size());
return mutableInstructionList.subList(getTargetInstructionIndex(), mutableInstructionList.size());
}
public Instruction resolveToInstruction() {
assert targetInstructionIndex != null;
return instructions.get(targetInstructionIndex);
return mutableInstructionList.get(targetInstructionIndex);
}
}
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
private final List<Instruction> instructions = new ArrayList<Instruction>();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction;
@@ -75,11 +77,21 @@ public class Pseudocode {
labels.add(label);
return label;
}
public void allowDead(Label label) {
allowedDeadLabels.add((PseudocodeLabel) label);
}
@NotNull
public List<Instruction> getInstructions() {
return instructions;
}
@Deprecated //for tests only
@NotNull
public List<Instruction> getMutableInstructionList() {
return mutableInstructionList;
}
@NotNull
public List<Instruction> getDeadInstructions() {
@@ -93,6 +105,7 @@ public class Pseudocode {
}
@Deprecated //for tests only
@NotNull
public List<PseudocodeLabel> getLabels() {
return labels;
}
@@ -110,7 +123,7 @@ public class Pseudocode {
}
public void addInstruction(Instruction instruction) {
instructions.add(instruction);
mutableInstructionList.add(instruction);
instruction.setOwner(this);
}
@@ -127,18 +140,18 @@ public class Pseudocode {
@NotNull
public SubroutineEnterInstruction getEnterInstruction() {
return (SubroutineEnterInstruction) instructions.get(0);
return (SubroutineEnterInstruction) mutableInstructionList.get(0);
}
public void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
}
public void postProcess() {
if (postPrecessed) return;
postPrecessed = true;
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
Instruction instruction = instructions.get(i);
for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) {
Instruction instruction = mutableInstructionList.get(i);
final int currentPosition = i;
instruction.accept(new InstructionVisitor() {
@Override
@@ -198,15 +211,20 @@ public class Pseudocode {
});
}
getExitInstruction().setSink(getSinkInstruction());
removeDeadInstructions();
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
markDeadInstructions();
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions(allowedDeadStartInstructions);
instructions.addAll(mutableInstructionList);
instructions.removeAll(allowedDeadInstructions);
}
private void removeDeadInstructions() {
private void markDeadInstructions() {
boolean hasRemovedInstruction = true;
Collection<Instruction> processedInstructions = Sets.newHashSet();
while (hasRemovedInstruction) {
hasRemovedInstruction = false;
for (Instruction instruction : instructions) {
for (Instruction instruction : mutableInstructionList) {
if (!(instruction instanceof SubroutineEnterInstruction || instruction instanceof SubroutineExitInstruction || instruction instanceof SubroutineSinkInstruction) &&
instruction.getPreviousInstructions().isEmpty() && !processedInstructions.contains(instruction)) {
hasRemovedInstruction = true;
@@ -220,6 +238,36 @@ public class Pseudocode {
}
}
@NotNull
private Set<Instruction> prepareAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
if (allowedDeadInstruction.getPreviousInstructions().isEmpty()) {
allowedDeadStartInstructions.add(allowedDeadInstruction);
}
}
return allowedDeadStartInstructions;
}
@NotNull
private Collection<Instruction> collectAllowedDeadInstructions(@NotNull Set<Instruction> allowedDeadStartInstructions) {
Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions);
}
return allowedDeadInstructions;
}
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet) {
if (allowedDeadInstruction.isDead()) {
instructionSet.add(allowedDeadInstruction);
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
collectAllowedDeadInstructions(instruction, instructionSet);
}
}
}
@NotNull
private Instruction getJumpTarget(@NotNull Label targetLabel) {
return ((PseudocodeLabel)targetLabel).resolveToInstruction();
@@ -228,7 +276,7 @@ public class Pseudocode {
@NotNull
private Instruction getNextPosition(int currentPosition) {
int targetPosition = currentPosition + 1;
assert targetPosition < instructions.size() : currentPosition;
return instructions.get(targetPosition);
assert targetPosition < mutableInstructionList.size() : currentPosition;
return mutableInstructionList.get(targetPosition);
}
}
+382 -191
View File
@@ -8,17 +8,16 @@ fun t1() {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(2)] PREV:[<START>]
l2:
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(1)]
r(2) NEXT:[<END>] PREV:[r(1)]
l1:
<END> NEXT:[<SINK>] PREV:[r(2)]
<END> NEXT:[<SINK>] PREV:[r(2)]
error:
<ERROR> NEXT:[] PREV:[]
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
<SINK> NEXT:[] PREV:[<END>]
=====================
== t2 ==
fun t2() {
@@ -33,22 +32,21 @@ fun t2() {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(2)] PREV:[<START>]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l3)] PREV:[r(>)]
jf(l3) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l1] PREV:[jf(l3)]
r(2 > 3) NEXT:[jf(l2)] PREV:[r(>)]
jf(l2) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l1] PREV:[jf(l2)]
ret l1 NEXT:[<END>] PREV:[r(2)]
* jmp(l4) NEXT:[r(2)] PREV:[]
l3:
read (Unit) NEXT:[r(2)] PREV:[jf(l3)]
* jmp(l3) NEXT:[r(2)] PREV:[]
l2:
read (Unit) NEXT:[r(2)] PREV:[jf(l2)]
l3:
l4:
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
r(2) NEXT:[<END>] PREV:[read (Unit)]
l1:
<END> NEXT:[<SINK>] PREV:[ret l1, r(2)]
error:
@@ -63,20 +61,20 @@ sink:
}
}
---------------------
l4:
l3:
<START> NEXT:[r(2)] PREV:[]
r(2) NEXT:[r(3)] PREV:[<START>]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), ret l5] PREV:[r(2 > 3)]
ret l5 NEXT:[<END>] PREV:[jf(l6)]
* jmp(l7) NEXT:[<END>] PREV:[]
l6:
read (Unit) NEXT:[<END>] PREV:[jf(l6)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
ret l4 NEXT:[<END>] PREV:[jf(l5)]
* jmp(l6) NEXT:[<END>] PREV:[]
l5:
l7:
<END> NEXT:[<SINK>] PREV:[ret l5, read (Unit)]
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
l4:
l6:
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
@@ -97,43 +95,42 @@ fun t3() {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[jmp?(l3)] PREV:[jmp?(l2)]
jmp?(l3) NEXT:[r({ () => if (2 > 3) { retur..), d({ () => if (2 > 3) { retur..)] PREV:[r(1)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[jmp?(l2)] PREV:[<START>]
jmp?(l2) NEXT:[r({ () => if (2 > 3) { retur..), d({ () => if (2 > 3) { retur..)] PREV:[r(1)]
d({ () =>
if (2 > 3) {
return@
}
}) NEXT:[<SINK>] PREV:[jmp?(l3)]
l3:
}) NEXT:[<SINK>] PREV:[jmp?(l2)]
l2:
r({ () =>
if (2 > 3) {
return@
}
}) NEXT:[r(2)] PREV:[jmp?(l3)]
l2:
r(2) NEXT:[<END>] PREV:[jmp?(l2), r({ () => if (2 > 3) { retur..)]
}) NEXT:[r(2)] PREV:[jmp?(l2)]
l7:
r(2) NEXT:[<END>] PREV:[r({ () => if (2 > 3) { retur..)]
l1:
<END> NEXT:[<SINK>] PREV:[r(2)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), <END>]
l4:
l3:
<START> NEXT:[r(2)] PREV:[]
r(2) NEXT:[r(3)] PREV:[<START>]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), ret l5] PREV:[r(2 > 3)]
ret l5 NEXT:[<END>] PREV:[jf(l6)]
* jmp(l7) NEXT:[<END>] PREV:[]
l6:
read (Unit) NEXT:[<END>] PREV:[jf(l6)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
ret l4 NEXT:[<END>] PREV:[jf(l5)]
* jmp(l6) NEXT:[<END>] PREV:[]
l5:
l7:
<END> NEXT:[<SINK>] PREV:[ret l5, read (Unit)]
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
l4:
l6:
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
@@ -152,22 +149,21 @@ sink:
}
---------------------
l3:
<START> NEXT:[jmp?(l5)] PREV:[]
jmp?(l5) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(2)] PREV:[jmp?(l5)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(2)] PREV:[<START>]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l4] PREV:[jf(l6)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l4] PREV:[jf(l5)]
ret l4 NEXT:[<END>] PREV:[r(2)]
* jmp(l7) NEXT:[r(2)] PREV:[]
l6:
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
* jmp(l6) NEXT:[r(2)] PREV:[]
l5:
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
l6:
l7:
r(2) NEXT:[<END>] PREV:[jmp?(l5), read (Unit)]
r(2) NEXT:[<END>] PREV:[read (Unit)]
l4:
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
error:
@@ -220,22 +216,21 @@ error:
sink:
<SINK> NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), <END>]
l3:
<START> NEXT:[jmp?(l5)] PREV:[]
jmp?(l5) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(2)] PREV:[jmp?(l5)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(2)] PREV:[<START>]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l4] PREV:[jf(l6)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l4] PREV:[jf(l5)]
ret l4 NEXT:[<END>] PREV:[r(2)]
* jmp(l7) NEXT:[r(2)] PREV:[]
l6:
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
* jmp(l6) NEXT:[r(2)] PREV:[]
l5:
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
l6:
l7:
r(2) NEXT:[<END>] PREV:[jmp?(l5), read (Unit)]
r(2) NEXT:[<END>] PREV:[read (Unit)]
l4:
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
error:
@@ -258,36 +253,35 @@ fun t5() {
}
---------------------
l0:
<START> NEXT:[r(true)] PREV:[]
<START> NEXT:[r(true)] PREV:[]
l2:
l5:
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
jf(l3) NEXT:[read (Unit), jmp?(l6)] PREV:[r(true)]
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
l4:
jmp?(l6) NEXT:[r(2), r(1)] PREV:[jf(l3)]
r(1) NEXT:[r(2)] PREV:[jmp?(l6)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
jf(l7) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[jmp(l3)] PREV:[jf(l7)]
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
* jmp(l8) NEXT:[r(2)] PREV:[]
l7:
read (Unit) NEXT:[r(2)] PREV:[jf(l7)]
r(1) NEXT:[r(2)] PREV:[jf(l3)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[jmp(l3)] PREV:[jf(l6)]
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
* jmp(l7) NEXT:[r(2)] PREV:[]
l6:
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
l7:
l8:
r(2) NEXT:[jmp(l2)] PREV:[jmp?(l6), read (Unit)]
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
r(2) NEXT:[jmp(l2)] PREV:[read (Unit)]
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
l3:
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)]
<END> NEXT:[<SINK>] PREV:[read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
<SINK> NEXT:[] PREV:[<END>]
=====================
== t6 ==
fun t6() {
@@ -305,30 +299,29 @@ fun t6() {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(true)] PREV:[<START>]
l3:
l6:
r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)]
jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)]
<START> NEXT:[r(true)] PREV:[]
l2:
l5:
r(1) NEXT:[r(2)] PREV:[jf(l4)]
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
l4:
r(1) NEXT:[r(2)] PREV:[jf(l3)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
jf(l7) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
jmp(l4) NEXT:[read (Unit)] PREV:[jf(l7)]
* jmp(l8) NEXT:[jmp(l3)] PREV:[]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), jmp(l3)] PREV:[r(2 > 3)]
jmp(l3) NEXT:[read (Unit)] PREV:[jf(l6)]
* jmp(l7) NEXT:[jmp(l2)] PREV:[]
l6:
read (Unit) NEXT:[jmp(l2)] PREV:[jf(l6)]
l7:
read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)]
l8:
jmp(l3) NEXT:[r(true)] PREV:[read (Unit)]
l4:
read (Unit) NEXT:[r(5)] PREV:[jf(l4), jmp(l4)]
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
l3:
read (Unit) NEXT:[r(5)] PREV:[jf(l3), jmp(l3)]
r(5) NEXT:[r(2)] PREV:[read (Unit)]
l2:
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(5)]
l8:
r(2) NEXT:[<END>] PREV:[r(5)]
l1:
<END> NEXT:[<SINK>] PREV:[r(2)]
error:
@@ -351,29 +344,28 @@ fun t7() {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(true)] PREV:[<START>]
l3:
l6:
r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)]
jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)]
<START> NEXT:[r(true)] PREV:[]
l2:
l5:
r(1) NEXT:[r(2)] PREV:[jf(l4)]
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
l4:
r(1) NEXT:[r(2)] PREV:[jf(l3)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
jf(l7) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
jmp(l4) NEXT:[read (Unit)] PREV:[jf(l7)]
* jmp(l8) NEXT:[jmp(l3)] PREV:[]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), jmp(l3)] PREV:[r(2 > 3)]
jmp(l3) NEXT:[read (Unit)] PREV:[jf(l6)]
* jmp(l7) NEXT:[jmp(l2)] PREV:[]
l6:
read (Unit) NEXT:[jmp(l2)] PREV:[jf(l6)]
l7:
read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)]
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
l3:
read (Unit) NEXT:[r(2)] PREV:[jf(l3), jmp(l3)]
l8:
jmp(l3) NEXT:[r(true)] PREV:[read (Unit)]
l4:
read (Unit) NEXT:[r(2)] PREV:[jf(l4), jmp(l4)]
l2:
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
r(2) NEXT:[<END>] PREV:[read (Unit)]
l1:
<END> NEXT:[<SINK>] PREV:[r(2)]
error:
@@ -396,40 +388,39 @@ fun t8(a : Int) {
}
---------------------
l0:
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(a)] PREV:[<START>]
r(a) NEXT:[r(..)] PREV:[r(1)]
r(..) NEXT:[r(1..a)] PREV:[r(a)]
r(1..a) NEXT:[w(i)] PREV:[r(..)]
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(a)] PREV:[<START>]
r(a) NEXT:[r(..)] PREV:[r(1)]
r(..) NEXT:[r(1..a)] PREV:[r(a)]
r(1..a) NEXT:[w(i)] PREV:[r(..)]
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
l3:
jmp?(l2) NEXT:[read (Unit), jmp?(l6)] PREV:[w(i)]
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
l4:
l5:
jmp?(l6) NEXT:[r(2), r(1)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
r(1) NEXT:[r(2)] PREV:[jmp?(l6)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
jf(l7) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[jmp(l4)] PREV:[jf(l7)]
jmp(l4) NEXT:[jmp?(l6)] PREV:[r(2)]
* jmp(l8) NEXT:[r(2)] PREV:[]
l7:
read (Unit) NEXT:[r(2)] PREV:[jf(l7)]
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[jmp(l4)] PREV:[jf(l6)]
jmp(l4) NEXT:[r(1)] PREV:[r(2)]
* jmp(l7) NEXT:[r(2)] PREV:[]
l6:
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
l7:
l8:
r(2) NEXT:[jmp?(l4)] PREV:[jmp?(l6), read (Unit)]
jmp?(l4) NEXT:[jmp?(l6), read (Unit)] PREV:[r(2)]
r(2) NEXT:[jmp?(l4)] PREV:[read (Unit)]
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[r(2)]
l2:
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)]
<END> NEXT:[<SINK>] PREV:[read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
<SINK> NEXT:[] PREV:[<END>]
=====================
== t9 ==
fun t9(a : Int) {
@@ -447,34 +438,33 @@ fun t9(a : Int) {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(a)] PREV:[jmp?(l2)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(a)] PREV:[<START>]
r(a) NEXT:[r(..)] PREV:[r(1)]
r(..) NEXT:[r(1..a)] PREV:[r(a)]
r(1..a) NEXT:[w(i)] PREV:[r(..)]
w(i) NEXT:[jmp?(l3)] PREV:[r(1..a)]
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
l3:
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
l4:
jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[w(i)]
l5:
l6:
r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)]
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
jf(l7) NEXT:[read (Unit), jmp(l5)] PREV:[r(2 > 3)]
jmp(l5) NEXT:[r(1)] PREV:[jf(l7)]
* jmp(l8) NEXT:[jmp?(l5)] PREV:[]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
jmp(l4) NEXT:[r(1)] PREV:[jf(l6)]
* jmp(l7) NEXT:[jmp?(l4)] PREV:[]
l6:
read (Unit) NEXT:[jmp?(l4)] PREV:[jf(l6)]
l7:
read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)]
l8:
jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
l3:
read (Unit) NEXT:[r(5)] PREV:[jmp?(l3), jmp?(l5)]
r(5) NEXT:[r(2)] PREV:[read (Unit)]
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
l2:
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(5)]
read (Unit) NEXT:[r(5)] PREV:[jmp?(l2), jmp?(l4)]
r(5) NEXT:[r(2)] PREV:[read (Unit)]
l8:
r(2) NEXT:[<END>] PREV:[r(5)]
l1:
<END> NEXT:[<SINK>] PREV:[r(2)]
error:
@@ -497,33 +487,32 @@ fun t10(a : Int) {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(a)] PREV:[jmp?(l2)]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(a)] PREV:[<START>]
r(a) NEXT:[r(..)] PREV:[r(1)]
r(..) NEXT:[r(1..a)] PREV:[r(a)]
r(1..a) NEXT:[w(i)] PREV:[r(..)]
w(i) NEXT:[jmp?(l3)] PREV:[r(1..a)]
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
l3:
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
l4:
jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[w(i)]
l5:
l6:
r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)]
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
jf(l7) NEXT:[read (Unit), jmp(l5)] PREV:[r(2 > 3)]
jmp(l5) NEXT:[r(1)] PREV:[jf(l7)]
* jmp(l8) NEXT:[jmp?(l5)] PREV:[]
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
jf(l6) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
jmp(l4) NEXT:[r(1)] PREV:[jf(l6)]
* jmp(l7) NEXT:[jmp?(l4)] PREV:[]
l6:
read (Unit) NEXT:[jmp?(l4)] PREV:[jf(l6)]
l7:
read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)]
l8:
jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
l3:
read (Unit) NEXT:[r(2)] PREV:[jmp?(l3), jmp?(l5)]
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
l2:
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
read (Unit) NEXT:[r(2)] PREV:[jmp?(l2), jmp?(l4)]
l8:
r(2) NEXT:[<END>] PREV:[read (Unit)]
l1:
<END> NEXT:[<SINK>] PREV:[r(2)]
error:
@@ -542,19 +531,221 @@ fun t11() {
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
r(2) NEXT:[ret(*) l1] PREV:[r(1)]
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
* ret(*) l1 NEXT:[<END>] PREV:[]
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(2)] PREV:[<START>]
r(2) NEXT:[ret(*) l1] PREV:[r(1)]
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
* ret(*) l1 NEXT:[<END>] PREV:[]
l2:
r(2) NEXT:[ret(*) l1] PREV:[jmp?(l2)]
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
R r(2) NEXT:[ret(*) l1] PREV:[]
R ret(*) l1 NEXT:[<END>] PREV:[]
l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
error:
<ERROR> NEXT:[] PREV:[]
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
<SINK> NEXT:[] PREV:[<END>]
=====================
== t12 ==
fun t12() : Int {
try {
return 1
}
finally {
doSmth(3)
}
}
---------------------
l0:
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[r(3)] PREV:[<START>]
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
l2:
R r(3) NEXT:[r(doSmth)] PREV:[]
R r(doSmth) NEXT:[r(doSmth(3))] PREV:[]
R r(doSmth(3)) NEXT:[<END>] PREV:[]
l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== t13 ==
fun t13() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
doSmth(2)
}
finally {
doSmth(3)
}
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
r(1) NEXT:[r(3)] PREV:[jmp?(l2)]
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
l3:
R jmp(l4) NEXT:[r(3)] PREV:[]
l2:
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
w(e) NEXT:[r(2)] PREV:[jmp?()]
r(2) NEXT:[r(doSmth)] PREV:[w(e)]
r(doSmth) NEXT:[r(doSmth(2))] PREV:[r(2)]
r(doSmth(2)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
l5:
jmp(l4) NEXT:[r(3)] PREV:[r(doSmth(2))]
l4:
r(3) NEXT:[r(doSmth)] PREV:[jmp(l4)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[<END>] PREV:[r(doSmth)]
l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== t14 ==
fun t14() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
doSmth(2)
}
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
r(1) NEXT:[ret(*) l1] PREV:[jmp?(l2)]
ret(*) l1 NEXT:[<END>] PREV:[r(1)]
l3:
R jmp(l4) NEXT:[<END>] PREV:[]
l2:
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
w(e) NEXT:[r(2)] PREV:[jmp?()]
r(2) NEXT:[r(doSmth)] PREV:[w(e)]
r(doSmth) NEXT:[r(doSmth(2))] PREV:[r(2)]
r(doSmth(2)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
l5:
jmp(l4) NEXT:[<END>] PREV:[r(doSmth(2))]
l1:
l4:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, jmp(l4)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== t15 ==
fun t15() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
return 2
}
finally {
doSmth(3)
}
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
r(1) NEXT:[r(3)] PREV:[jmp?(l2)]
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
l3:
R jmp(l4) NEXT:[r(3)] PREV:[]
l2:
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
w(e) NEXT:[r(2)] PREV:[jmp?()]
r(2) NEXT:[r(3)] PREV:[w(e)]
r(3) NEXT:[r(doSmth)] PREV:[r(2)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
l5:
R jmp(l4) NEXT:[r(3)] PREV:[]
l4:
R r(3) NEXT:[r(doSmth)] PREV:[]
R r(doSmth) NEXT:[r(doSmth(3))] PREV:[]
R r(doSmth(3)) NEXT:[<END>] PREV:[]
l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== t16 ==
fun t16() : Int {
try {
doSmth(1)
}
catch (e: UnsupportedOperationException) {
return 2
}
finally {
doSmth(3)
}
}
---------------------
l0:
<START> NEXT:[jmp?(l2)] PREV:[]
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
r(1) NEXT:[r(doSmth)] PREV:[jmp?(l2)]
r(doSmth) NEXT:[r(doSmth(1))] PREV:[r(1)]
r(doSmth(1)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
l3:
jmp(l4) NEXT:[r(3)] PREV:[r(doSmth(1))]
l2:
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
w(e) NEXT:[r(2)] PREV:[jmp?()]
r(2) NEXT:[r(3)] PREV:[w(e)]
r(3) NEXT:[r(doSmth)] PREV:[r(2)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
l5:
R jmp(l4) NEXT:[r(3)] PREV:[]
l4:
r(3) NEXT:[r(doSmth)] PREV:[jmp(l4)]
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
r(doSmth(3)) NEXT:[<END>] PREV:[r(doSmth)]
l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== doSmth ==
fun doSmth(i: Int) {
}
---------------------
l0:
<START> NEXT:[read (Unit)] PREV:[]
read (Unit) NEXT:[<END>] PREV:[<START>]
l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
+58
View File
@@ -130,4 +130,62 @@ fun t11() {
finally {
return 2
}
}
fun t12() : Int {
try {
return 1
}
finally {
doSmth(3)
}
}
fun t13() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
doSmth(2)
}
finally {
doSmth(3)
}
}
fun t14() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
doSmth(2)
}
}
fun t15() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
return 2
}
finally {
doSmth(3)
}
}
fun t16() : Int {
try {
doSmth(1)
}
catch (e: UnsupportedOperationException) {
return 2
}
finally {
doSmth(3)
}
}
fun doSmth(i: Int) {
}
@@ -0,0 +1,91 @@
//KT-58 Allow finally around definite returns
namespace kt58
import java.util.concurrent.locks.Lock
fun lock<T>(lock : Lock, body : fun () : T) : T {
lock.lock()
try {
return body()
}
finally {
lock.unlock(); // we report an error, but we chouldn't
}
}
//more tests
fun t1() : Int {
try {
<!UNREACHABLE_CODE!>return 1<!>
}
finally {
return 2
}
}
fun t2() : Int {
try {
return 1
}
finally {
doSmth(3)
}
}
fun t3() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
doSmth(2)
}
finally {
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(3)<!>
}
}
fun t4() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(2)<!>
}
}
fun t5() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
return 2
}
}
fun t6() : Int {
try {
return 1
}
catch (e: UnsupportedOperationException) {
return 2
}
finally {
doSmth(3)
}
}
fun t7() : Int {
try {
doSmth(1)
}
catch (e: UnsupportedOperationException) {
return 2
}
finally {
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(3)<!>
}
}
fun doSmth(i: Int) {
}
@@ -3,6 +3,7 @@
*/
package org.jetbrains.jet.cfg;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import junit.framework.Test;
@@ -125,7 +126,7 @@ public class JetControlFlowTest extends JetLiteFixture {
instructionDump.append("=====================\n");
//check edges directions
Collection<Instruction> instructions = pseudocode.getInstructions();
Collection<Instruction> instructions = pseudocode.getMutableInstructionList();
for (Instruction instruction : instructions) {
if (!instruction.isDead()) {
for (Instruction nextInstruction : instruction.getNextInstructions()) {
@@ -157,7 +158,7 @@ public class JetControlFlowTest extends JetLiteFixture {
}
public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
dfsDump(nodes, edges, pseudocode.getInstructions().get(0), nodeNames);
dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames);
}
private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) {
@@ -172,9 +173,10 @@ public class JetControlFlowTest extends JetLiteFixture {
throw new UnsupportedOperationException(); // TODO
}
private static String formatInstruction(Instruction instruction, int maxLength) {
private static String formatInstruction(Instruction instruction, int maxLength, Set<Instruction> remainedAfterPostProcessInstructions) {
String[] parts = instruction.toString().split("\n");
String prefix = instruction.isDead() ? "* " : " ";
boolean isRemovedThroughPostProcess = !remainedAfterPostProcessInstructions.contains(instruction);
String prefix = isRemovedThroughPostProcess ? "R " : instruction.isDead() ? "* " : " ";
if (parts.length == 1) {
return prefix + String.format("%1$-" + maxLength + "s", instruction);
}
@@ -218,7 +220,8 @@ public class JetControlFlowTest extends JetLiteFixture {
}
public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) {
List<Instruction> instructions = pseudocode.getInstructions();
List<Instruction> instructions = pseudocode.getMutableInstructionList();
Set<Instruction> remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions());
List<Pseudocode.PseudocodeLabel> labels = pseudocode.getLabels();
List<Pseudocode> locals = new ArrayList<Pseudocode>();
int maxLength = 0;
@@ -257,7 +260,7 @@ public class JetControlFlowTest extends JetLiteFixture {
}
}
out.append(formatInstruction(instruction, maxLength)).
out.append(formatInstruction(instruction, maxLength, remainedAfterPostProcessInstructions)).
append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))).
append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n");
}
@@ -273,7 +276,7 @@ public class JetControlFlowTest extends JetLiteFixture {
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
int index = count[0];
// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getInstructions().get(0)), null);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getMutableInstructionList().get(0)), null);
visitInstructionWithNext(instruction);
}
@@ -336,7 +339,7 @@ public class JetControlFlowTest extends JetLiteFixture {
}
}
public void dumpNodes(List<Instruction> instructions, PrintStream out, int[] count, Map<Instruction, String> nodeToName) {
public void dumpNodes(List<Instruction> instructions, PrintStream out, int[] count, Map<Instruction, String> nodeToName, Set<Instruction> remainedAfterPostProcessInstructions) {
for (Instruction node : instructions) {
String name = "n" + count[0]++;
nodeToName.put(node, name);
@@ -361,6 +364,9 @@ public class JetControlFlowTest extends JetLiteFixture {
else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) {
shape = "roundrect, style=rounded";
}
if (!remainedAfterPostProcessInstructions.contains(node)) {
shape += "box, fillcolor=grey, style=filled";
}
out.println(name + "[label=\"" + text + "\", shape=" + shape + "];");
}
}
@@ -385,7 +391,7 @@ public class JetControlFlowTest extends JetLiteFixture {
int[] count = new int[1];
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
for (Pseudocode pseudocode : pseudocodes) {
dumpNodes(pseudocode.getInstructions(), out, count, nodeToName);
dumpNodes(pseudocode.getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions()));
}
int i = 0;
for (Pseudocode pseudocode : pseudocodes) {
@@ -401,7 +407,7 @@ public class JetControlFlowTest extends JetLiteFixture {
out.println("subgraph cluster_" + i + " {\n" +
"label=\"" + label + "\";\n" +
"color=blue;\n");
dumpEdges(pseudocode.getInstructions(), out, count, nodeToName);
dumpEdges(pseudocode.getMutableInstructionList(), out, count, nodeToName);
out.println("}");
i++;
}