More cases for nullability analysis

This commit is contained in:
Andrey Breslav
2011-06-10 19:07:23 +04:00
parent 9d3abf782c
commit 49b60c3af8
16 changed files with 347 additions and 114 deletions
@@ -0,0 +1,6 @@
package org.jetbrains.jet.lang.cfg;
/**
* @author abreslav
*/
public abstract class BlockInfo {}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.lang.cfg;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class BreakableBlockInfo extends BlockInfo {
private final JetElement element;
private final Label entryPoint;
private final Label exitPoint;
public BreakableBlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
this.element = element;
this.entryPoint = entryPoint;
this.exitPoint = exitPoint;
}
public JetElement getElement() {
return element;
}
public Label getEntryPoint() {
return entryPoint;
}
public Label getExitPoint() {
return exitPoint;
}
}
@@ -31,7 +31,7 @@ public interface JetControlFlowBuilder {
Label getExitPoint(@NotNull JetElement labelElement); Label getExitPoint(@NotNull JetElement labelElement);
// Loops // Loops
Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint); LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, @Nullable Label conditionEntryPoint);
void exitLoop(@NotNull JetExpression expression); void exitLoop(@NotNull JetExpression expression);
@Nullable @Nullable
@@ -73,8 +73,8 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
} }
@Override @Override
public Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) { public LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) {
return builder.enterLoop(expression, loopExitPoint); return builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
} }
@Override @Override
@@ -350,35 +350,40 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitWhileExpression(JetWhileExpression expression) { public void visitWhileExpression(JetWhileExpression expression) {
Label loopExitPoint = builder.createUnboundLabel(); LoopInfo loopInfo = builder.enterLoop(expression, null, null);
Label loopEntryPoint = builder.enterLoop(expression, loopExitPoint);
builder.bindLabel(loopInfo.getConditionEntryPoint());
JetExpression condition = expression.getCondition(); JetExpression condition = expression.getCondition();
if (condition != null) { if (condition != null) {
value(condition, false, true); value(condition, false, true);
} }
builder.jumpOnFalse(loopExitPoint); builder.jumpOnFalse(loopInfo.getExitPoint());
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody(); JetExpression body = expression.getBody();
if (body != null) { if (body != null) {
value(body, true, false); value(body, true, false);
} }
builder.jump(loopEntryPoint); builder.jump(loopInfo.getEntryPoint());
builder.exitLoop(expression); builder.exitLoop(expression);
builder.readUnit(expression); builder.readUnit(expression);
} }
@Override @Override
public void visitDoWhileExpression(JetDoWhileExpression expression) { public void visitDoWhileExpression(JetDoWhileExpression expression) {
Label loopExitPoint = builder.createUnboundLabel(); LoopInfo loopInfo = builder.enterLoop(expression, null, null);
Label loopEntryPoint = builder.enterLoop(expression, loopExitPoint);
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody(); JetExpression body = expression.getBody();
if (body != null) { if (body != null) {
value(body, true, false); value(body, true, false);
} }
builder.bindLabel(loopInfo.getConditionEntryPoint());
JetExpression condition = expression.getCondition(); JetExpression condition = expression.getCondition();
if (condition != null) { if (condition != null) {
value(condition, false, true); value(condition, false, true);
} }
builder.jumpOnTrue(loopEntryPoint); builder.jumpOnTrue(loopInfo.getEntryPoint());
builder.exitLoop(expression); builder.exitLoop(expression);
builder.readUnit(expression); builder.readUnit(expression);
} }
@@ -391,13 +396,20 @@ public class JetControlFlowProcessor {
} }
// TODO : primitive cases // TODO : primitive cases
Label loopExitPoint = builder.createUnboundLabel(); Label loopExitPoint = builder.createUnboundLabel();
Label conditionEntryPoint = builder.createUnboundLabel();
builder.bindLabel(conditionEntryPoint);
builder.nondeterministicJump(loopExitPoint); builder.nondeterministicJump(loopExitPoint);
Label loopEntryPoint = builder.enterLoop(expression, loopExitPoint);
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody(); JetExpression body = expression.getBody();
if (body != null) { if (body != null) {
value(body, true, false); value(body, true, false);
} }
builder.nondeterministicJump(loopEntryPoint);
builder.nondeterministicJump(loopInfo.getEntryPoint());
builder.exitLoop(expression); builder.exitLoop(expression);
builder.readUnit(expression); builder.readUnit(expression);
} }
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetLoopExpression;
import java.util.Collection; import java.util.Collection;
@@ -25,6 +26,12 @@ public interface JetFlowInformationProvider {
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) { public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isBreakable(JetLoopExpression loop) {
throw new UnsupportedOperationException();
}
}; };
JetFlowInformationProvider NONE = new JetFlowInformationProvider() { JetFlowInformationProvider NONE = new JetFlowInformationProvider() {
@@ -42,6 +49,12 @@ public interface JetFlowInformationProvider {
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) { public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
} }
@Override
public boolean isBreakable(JetLoopExpression loop) {
return false;
}
}; };
void collectReturnedInformation( void collectReturnedInformation(
@@ -56,4 +69,6 @@ public interface JetFlowInformationProvider {
void collectDominatedExpressions( void collectDominatedExpressions(
@NotNull JetExpression dominator, @NotNull JetExpression dominator,
@NotNull Collection<JetElement> dominated); @NotNull Collection<JetElement> dominated);
boolean isBreakable(JetLoopExpression loop);
} }
@@ -0,0 +1,25 @@
package org.jetbrains.jet.lang.cfg;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class LoopInfo extends BreakableBlockInfo {
private final Label bodyEntryPoint;
private final Label conditionEntryPoint;
public LoopInfo(JetElement element, Label entryPoint, Label exitPoint, Label bodyEntryPoint, Label conditionEntryPoint) {
super(element, entryPoint, exitPoint);
this.bodyEntryPoint = bodyEntryPoint;
this.conditionEntryPoint = conditionEntryPoint;
}
public Label getBodyEntryPoint() {
return bodyEntryPoint;
}
public Label getConditionEntryPoint() {
return conditionEntryPoint;
}
}
@@ -1,10 +1,7 @@
package org.jetbrains.jet.lang.cfg.pseudocode; package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.GenerationTrigger; import org.jetbrains.jet.lang.cfg.*;
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilder;
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilderAdapter;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
@@ -101,14 +98,20 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
} }
@Override @Override
public final Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) { public final LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) {
Label label = createUnboundLabel(); Label label = createUnboundLabel();
bindLabel(label); bindLabel(label);
BreakableBlockInfo blockInfo = new BreakableBlockInfo(expression, label, loopExitPoint); LoopInfo blockInfo = new LoopInfo(
expression,
label,
loopExitPoint != null ? loopExitPoint : createUnboundLabel(),
createUnboundLabel(),
conditionEntryPoint != null ? conditionEntryPoint : createUnboundLabel());
loopInfo.push(blockInfo); loopInfo.push(blockInfo);
elementToBlockInfo.put(expression, blockInfo); elementToBlockInfo.put(expression, blockInfo);
allBlocks.push(blockInfo); allBlocks.push(blockInfo);
return label; trace.recordLoopInfo(expression, blockInfo);
return blockInfo;
} }
@Override @Override
@@ -265,9 +268,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
} }
} }
private static abstract class BlockInfo {} public static class TryFinallyBlockInfo extends BlockInfo {
private static class TryFinallyBlockInfo extends BlockInfo {
private final GenerationTrigger finallyBlock; private final GenerationTrigger finallyBlock;
private TryFinallyBlockInfo(GenerationTrigger finallyBlock) { private TryFinallyBlockInfo(GenerationTrigger finallyBlock) {
@@ -279,27 +280,4 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
} }
} }
private static class BreakableBlockInfo extends BlockInfo {
private final JetElement element;
private final Label entryPoint;
private final Label exitPoint;
private BreakableBlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
this.element = element;
this.entryPoint = entryPoint;
this.exitPoint = exitPoint;
}
public JetElement getElement() {
return element;
}
public Label getEntryPoint() {
return entryPoint;
}
public Label getExitPoint() {
return exitPoint;
}
}
} }
@@ -1,7 +1,9 @@
package org.jetbrains.jet.lang.cfg.pseudocode; package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
/** /**
* @author abreslav * @author abreslav
@@ -21,10 +23,16 @@ public interface JetPseudocodeTrace {
@Override @Override
public void close() { public void close() {
} }
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
}
}; };
void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode); void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode);
void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction); void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction);
void close(); void close();
void recordLoopInfo(JetExpression expression, LoopInfo blockInfo);
} }
@@ -46,6 +46,11 @@ public class Pseudocode {
return instructions.subList(getTargetInstructionIndex(), instructions.size()); return instructions.subList(getTargetInstructionIndex(), instructions.size());
} }
public Instruction resolveToInstruction() {
assert targetInstructionIndex != null;
return instructions.get(targetInstructionIndex);
}
} }
private final List<Instruction> instructions = new ArrayList<Instruction>(); private final List<Instruction> instructions = new ArrayList<Instruction>();
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -9,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
@@ -721,6 +723,7 @@ public class ClassDescriptorResolver {
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration); final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration);
final Map<JetElement, Pseudocode> pseudocodeMap = new HashMap<JetElement, Pseudocode>(); final Map<JetElement, Pseudocode> pseudocodeMap = new HashMap<JetElement, Pseudocode>();
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>(); final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() { JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() {
@Override @Override
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
@@ -732,6 +735,13 @@ public class ClassDescriptorResolver {
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
Instruction oldValue = representativeInstructions.put(element, instruction); Instruction oldValue = representativeInstructions.put(element, instruction);
// assert oldValue == null : element.getText(); // assert oldValue == null : element.getText();
pseudocodeTrace.recordRepresentativeInstruction(element, instruction);
}
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
loopInfo.put(expression, blockInfo);
pseudocodeTrace.recordLoopInfo(expression, blockInfo);
} }
@Override @Override
@@ -762,7 +772,7 @@ public class ClassDescriptorResolver {
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
Set<Instruction> visited = new HashSet<Instruction>(); Set<Instruction> visited = new HashSet<Instruction>();
collectReachable(enterInstruction, visited); collectReachable(enterInstruction, visited, null);
for (Instruction instruction : pseudocode.getInstructions()) { for (Instruction instruction : pseudocode.getInstructions()) {
if (!visited.contains(instruction) && if (!visited.contains(instruction) &&
@@ -783,11 +793,11 @@ public class ClassDescriptorResolver {
SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction(); SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction();
Set<Instruction> reachable = new HashSet<Instruction>(); Set<Instruction> reachable = new HashSet<Instruction>();
collectReachable(enterInstruction, reachable); collectReachable(enterInstruction, reachable, null);
Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>(); Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>();
reachableWithDominatorProhibited.add(dominatorInstruction); reachableWithDominatorProhibited.add(dominatorInstruction);
collectReachable(enterInstruction, reachableWithDominatorProhibited); collectReachable(enterInstruction, reachableWithDominatorProhibited, null);
for (Instruction instruction : reachable) { for (Instruction instruction : reachable) {
if (instruction instanceof JetElementInstruction if (instruction instanceof JetElementInstruction
@@ -798,15 +808,39 @@ public class ClassDescriptorResolver {
} }
} }
} }
@Override
public boolean isBreakable(JetLoopExpression loop) {
LoopInfo info = loopInfo.get(loop);
Pseudocode.PseudocodeLabel bodyEntryPoint = (Pseudocode.PseudocodeLabel) info.getBodyEntryPoint();
Pseudocode.PseudocodeLabel exitPoint = (Pseudocode.PseudocodeLabel) info.getExitPoint();
HashSet<Instruction> visited = Sets.newHashSet();
Pseudocode.PseudocodeLabel conditionEntryPoint = (Pseudocode.PseudocodeLabel) info.getConditionEntryPoint();
visited.add(conditionEntryPoint.resolveToInstruction());
return collectReachable(bodyEntryPoint.resolveToInstruction(), visited, exitPoint.resolveToInstruction());
}
public boolean isReachable(JetExpression from, JetExpression to) {
Instruction fromInstr = representativeInstructions.get(from);
assert fromInstr != null : "No representative instruction for " + from.getText();
Instruction toInstr = representativeInstructions.get(to);
assert toInstr != null : "No representative instruction for " + to.getText();
return collectReachable(fromInstr, Sets.<Instruction>newHashSet(), toInstr);
}
}; };
} }
private void collectReachable(Instruction current, Set<Instruction> visited) { private boolean collectReachable(Instruction current, Set<Instruction> visited, @Nullable Instruction lookFor) {
if (!visited.add(current)) return; if (!visited.add(current)) return false;
if (current == lookFor) return true;
for (Instruction nextInstruction : current.getNextInstructions()) { for (Instruction nextInstruction : current.getNextInstructions()) {
collectReachable(nextInstruction, visited); if (collectReachable(nextInstruction, visited, lookFor)) {
return true;
}
} }
return false;
} }
private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) { private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
@@ -1307,12 +1307,16 @@ public class JetTypeInferrer {
} }
} }
else if (thenBranch == null) { else if (thenBranch == null) {
getType(scope, elseBranch, true, elseInfo); JetType type = getType(scope, elseBranch, true, elseInfo);
if (type != null && JetStandardClasses.isNothing(type)) {
resultDataFlowInfo = thenInfo;
}
result = JetStandardClasses.getUnitType(); result = JetStandardClasses.getUnitType();
} }
else { else {
JetType thenType = getType(scope, thenBranch, true, thenInfo); JetType thenType = getType(scope, thenBranch, true, thenInfo);
JetType elseType = getType(scope, elseBranch, true, elseInfo); JetType elseType = getType(scope, elseBranch, true, elseInfo);
if (thenType == null) { if (thenType == null) {
result = elseType; result = elseType;
} }
@@ -1322,10 +1326,22 @@ public class JetTypeInferrer {
else { else {
result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType)); result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
} }
boolean jumpInThen = thenType != null && JetStandardClasses.isNothing(thenType);
boolean jumpInElse = elseType != null && JetStandardClasses.isNothing(elseType);
if (jumpInThen && !jumpInElse) {
resultDataFlowInfo = elseInfo;
}
else if (jumpInElse && !jumpInThen) {
resultDataFlowInfo = thenInfo;
}
} }
} }
private DataFlowInfo extractDataFlowInfoFromCondition(@NotNull JetExpression condition, final boolean conditionValue) { private DataFlowInfo extractDataFlowInfoFromCondition(@Nullable JetExpression condition, final boolean conditionValue) {
if (condition == null) return dataFlowInfo;
final DataFlowInfo[] result = new DataFlowInfo[] {dataFlowInfo}; final DataFlowInfo[] result = new DataFlowInfo[] {dataFlowInfo};
condition.accept(new JetVisitor() { condition.accept(new JetVisitor() {
@Override @Override
@@ -1410,7 +1426,9 @@ public class JetTypeInferrer {
DataFlowInfo conditionInfo = condition == null ? dataFlowInfo : extractDataFlowInfoFromCondition(condition, true); DataFlowInfo conditionInfo = condition == null ? dataFlowInfo : extractDataFlowInfoFromCondition(condition, true);
getType(scope, body, true, conditionInfo); getType(scope, body, true, conditionInfo);
} }
resultDataFlowInfo = condition == null ? null : extractDataFlowInfoFromCondition(condition, false); if (!flowInformationProvider.isBreakable(expression)) {
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false);
}
result = JetStandardClasses.getUnitType(); result = JetStandardClasses.getUnitType();
} }
@@ -1434,7 +1452,11 @@ public class JetTypeInferrer {
conditionScope = writableScope; conditionScope = writableScope;
getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), dataFlowInfo); getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), dataFlowInfo);
} }
checkCondition(conditionScope, expression.getCondition()); JetExpression condition = expression.getCondition();
checkCondition(conditionScope, condition);
if (!flowInformationProvider.isBreakable(expression)) {
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false);
}
result = JetStandardClasses.getUnitType(); result = JetStandardClasses.getUnitType();
} }
@@ -1918,6 +1940,7 @@ public class JetTypeInferrer {
if (receiverType != null) { if (receiverType != null) {
FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true); FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true);
if (functionDescriptor != null) { if (functionDescriptor != null) {
// checkNullSafety(receiverType, expression.getIndexExpressions().get(0).getNode(), functionDescriptor);
result = functionDescriptor.getUnsubstitutedReturnType(); result = functionDescriptor.getUnsubstitutedReturnType();
} }
} }
+64 -52
View File
@@ -224,26 +224,28 @@ fun t3() {
--------------------- ---------------------
l0: l0:
<START> <START>
l3: l2:
l5:
r(true) r(true)
jf(l2) jf(l3)
jmp?(l4) l4:
jmp?(l6)
r(1) r(1)
r(2) r(2)
r(3) r(3)
r(>) r(>)
r(2 > 3) r(2 > 3)
jf(l5) jf(l7)
r(2)
jmp(l2)
jmp(l6)
l5:
read (Unit)
l4:
l6:
r(2) r(2)
jmp(l3) jmp(l3)
l2: jmp(l8)
l7:
read (Unit)
l6:
l8:
r(2)
jmp(l2)
l3:
read (Unit) read (Unit)
l1: l1:
<END> <END>
@@ -268,22 +270,24 @@ fun t3() {
l0: l0:
<START> <START>
jmp?(l2) jmp?(l2)
l4: l3:
l6:
r(true) r(true)
jf(l3) jf(l4)
l5:
r(1) r(1)
r(2) r(2)
r(3) r(3)
r(>) r(>)
r(2 > 3) r(2 > 3)
jf(l5) jf(l7)
jmp(l3)
jmp(l6)
l5:
read (Unit)
l6:
jmp(l4) jmp(l4)
l3: jmp(l8)
l7:
read (Unit)
l8:
jmp(l3)
l4:
read (Unit) read (Unit)
r(5) r(5)
l2: l2:
@@ -310,22 +314,24 @@ fun t3() {
l0: l0:
<START> <START>
jmp?(l2) jmp?(l2)
l4: l3:
l6:
r(true) r(true)
jf(l3) jf(l4)
l5:
r(1) r(1)
r(2) r(2)
r(3) r(3)
r(>) r(>)
r(2 > 3) r(2 > 3)
jf(l5) jf(l7)
jmp(l3)
jmp(l6)
l5:
read (Unit)
l6:
jmp(l4) jmp(l4)
l3: jmp(l8)
l7:
read (Unit)
l8:
jmp(l3)
l4:
read (Unit) read (Unit)
l2: l2:
r(2) r(2)
@@ -354,24 +360,26 @@ l0:
r(a) r(a)
r(..) r(..)
r(1..a) r(1..a)
jmp?(l2)
l3: l3:
jmp?(l4) jmp?(l2)
l4:
l5:
jmp?(l6)
r(1) r(1)
r(2) r(2)
r(3) r(3)
r(>) r(>)
r(2 > 3) r(2 > 3)
jf(l5) jf(l7)
r(2) r(2)
jmp(l3) jmp(l4)
jmp(l6) jmp(l8)
l5: l7:
read (Unit) read (Unit)
l4:
l6: l6:
l8:
r(2) r(2)
jmp?(l3) jmp?(l4)
l2: l2:
read (Unit) read (Unit)
l1: l1:
@@ -401,20 +409,22 @@ l0:
r(a) r(a)
r(..) r(..)
r(1..a) r(1..a)
jmp?(l3)
l4: l4:
jmp?(l3)
l5:
l6:
r(1) r(1)
r(2) r(2)
r(3) r(3)
r(>) r(>)
r(2 > 3) r(2 > 3)
jf(l5) jf(l7)
jmp(l4) jmp(l5)
jmp(l6) jmp(l8)
l5: l7:
read (Unit) read (Unit)
l6: l8:
jmp?(l4) jmp?(l5)
l3: l3:
read (Unit) read (Unit)
r(5) r(5)
@@ -446,20 +456,22 @@ l0:
r(a) r(a)
r(..) r(..)
r(1..a) r(1..a)
jmp?(l3)
l4: l4:
jmp?(l3)
l5:
l6:
r(1) r(1)
r(2) r(2)
r(3) r(3)
r(>) r(>)
r(2 > 3) r(2 > 3)
jf(l5) jf(l7)
jmp(l4) jmp(l5)
jmp(l6) jmp(l8)
l5: l7:
read (Unit) read (Unit)
l6: l8:
jmp?(l4) jmp?(l5)
l3: l3:
read (Unit) read (Unit)
l2: l2:
@@ -7,15 +7,17 @@ fun main() {
--------------------- ---------------------
l0: l0:
<START> <START>
l3: l2:
l5:
r(1) r(1)
r(0) r(0)
r(>) r(>)
r(1 > 0) r(1 > 0)
jf(l2) jf(l3)
l4:
r(2) r(2)
jmp(l3) jmp(l2)
l2: l3:
read (Unit) read (Unit)
l1: l1:
<END> <END>
@@ -30,14 +32,16 @@ fun dowhile() {
--------------------- ---------------------
l0: l0:
<START> <START>
l3: l2:
l4:
ret l1 ret l1
l5:
r(1) r(1)
r(0) r(0)
r(>) r(>)
r(1 > 0) r(1 > 0)
jt(l3) jt(l2)
l2: l3:
read (Unit) read (Unit)
l1: l1:
<END> <END>
+75
View File
@@ -139,3 +139,78 @@ fun test() {
out.println() out.println()
} }
fun f(out : String?) {
out?.get(0)
if (out != null) else return;
out.get(0)
}
fun f1(out : String?) {
out?.get(0)
if (out != null) else {
1 + 2
return;
}
out.get(0)
}
fun f2(out : String?) {
out?.get(0)
if (out == null) {
1 + 2
return;
}
out.get(0)
}
fun f3(out : String?) {
out?.get(0)
if (out == null) {
1 + 2
return;
}
else {
1 + 2
}
out.get(0)
}
fun f4(s : String?) {
s?.get(0)
while (1 < 2 && s != null) {
s.get(0)
}
s?.get(0)
while (s == null || 1 < 2) {
s?.get(0)
}
s.get(0)
}
fun f5(s : String?) {
s?.get(0)
while (1 < 2 && s != null) {
s.get(0)
}
s?.get(0)
while (s == null || 1 < 2) {
if (1 > 2) break
s?.get(0)
}
s?.get(0);
}
fun f6(s : String?) {
s?.get(0)
do {
s?.get(0)
if (1 < 2) break;
} while (s == null)
s?.get(0)
do {
s?.get(0)
} while (s == null)
s.get(0)
}
@@ -8,11 +8,13 @@ import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; import org.jetbrains.jet.lang.cfg.pseudocode.Instruction;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.cfg.pseudocode.JetPseudocodeTrace; import org.jetbrains.jet.lang.cfg.pseudocode.JetPseudocodeTrace;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration; import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
@@ -55,6 +57,10 @@ public class JetControlFlowTest extends JetTestCaseBase {
} }
} }
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
}
@Override @Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
} }