提交 96526603 编写于 作者: A Andrey Breslav

Basic tests for dead code detection

上级 69ef281d
......@@ -16,7 +16,6 @@
<option name="VM_PARAMETERS" value="" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="FORK_MODE" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
......
......@@ -3,7 +3,6 @@ package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunction;
import java.util.Collection;
......@@ -13,10 +12,16 @@ import java.util.Collection;
public interface JetFlowInformationProvider {
JetFlowInformationProvider ERROR = new JetFlowInformationProvider() {
@Override
public void collectReturnedInformation(@NotNull JetFunction function, Collection<JetExpression> returnedExpressions, Collection<JetElement> elementsReturningUnit) {
public void collectReturnedInformation(@NotNull JetElement subroutine, Collection<JetExpression> returnedExpressions, Collection<JetElement> elementsReturningUnit) {
throw new UnsupportedOperationException();
}
@Override
public void collectUnreachableExpressions(@NotNull JetElement subroutine, Collection<JetElement> unreachableElements) {
throw new UnsupportedOperationException();
}
};
void collectReturnedInformation(@NotNull JetFunction function, Collection<JetExpression> returnedExpressions, Collection<JetElement> elementsReturningUnit);
void collectReturnedInformation(@NotNull JetElement subroutine, Collection<JetExpression> returnedExpressions, Collection<JetElement> elementsReturningUnit);
void collectUnreachableExpressions(@NotNull JetElement subroutine, Collection<JetElement> unreachableElements);
}
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
......@@ -21,6 +25,12 @@ public abstract class AbstractJumpInstruction extends Instruction {
return resolvedTarget;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Collections.singleton(getResolvedTarget());
}
public void setResolvedTarget(Instruction resolvedTarget) {
this.resolvedTarget = outgoingEdgeTo(resolvedTarget);
}
......
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import java.util.Arrays;
import java.util.Collection;
/**
* @author abreslav
*/
......@@ -35,6 +39,12 @@ public class ConditionalJumpInstruction extends AbstractJumpInstruction {
this.nextOnFalse = outgoingEdgeTo(nextOnFalse);
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Arrays.asList(getNextOnFalse(), getNextOnTrue());
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitConditionalJump(this);
......
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
......@@ -15,6 +16,9 @@ public abstract class Instruction {
return previousInstructions;
}
@NotNull
public abstract Collection<Instruction> getNextInstructions();
@Nullable
protected Instruction outgoingEdgeTo(@Nullable Instruction target) {
if (target != null) {
......
......@@ -3,6 +3,9 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
......@@ -17,6 +20,12 @@ public abstract class InstructionWithNext extends JetElementInstruction {
return next;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Collections.singleton(next);
}
public void setNext(Instruction next) {
this.next = outgoingEdgeTo(next);
}
......
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.Label;
import java.util.Arrays;
import java.util.Collection;
/**
* @author abreslav
*/
......@@ -26,6 +30,12 @@ public class NondeterministicJumpInstruction extends AbstractJumpInstruction {
this.next = next;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Arrays.asList(getResolvedTarget(), getNext());
}
@Override
public String toString() {
return "jmp?(" + getTargetLabel().getName() + ")";
......
......@@ -69,6 +69,11 @@ public class Pseudocode {
return label;
}
@NotNull
public Collection<Instruction> getInstructions() {
return instructions;
}
public void addInstruction(Instruction instruction) {
instructions.add(instruction);
if (instruction instanceof SubroutineExitInstruction) {
......@@ -83,6 +88,11 @@ public class Pseudocode {
return exitInstruction;
}
@NotNull
public SubroutineEnterInstruction getEnterInstruction() {
return (SubroutineEnterInstruction) instructions.get(0);
}
public void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
}
......
......@@ -27,6 +27,6 @@ public class ReturnNoValueInstruction extends AbstractJumpInstruction {
@Override
public String toString() {
return "ret";
return "ret " + getTargetLabel();
}
}
......@@ -18,6 +18,6 @@ public class ReturnValueInstruction extends AbstractJumpInstruction {
@Override
public String toString() {
return "ret(*)";
return "ret(*) " + getTargetLabel();
}
}
......@@ -3,6 +3,9 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
......@@ -17,6 +20,12 @@ public class SubroutineExitInstruction extends Instruction {
return subroutine;
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
return Collections.emptyList();
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitSubroutineExit(this);
......
......@@ -268,21 +268,27 @@ public class TopDownAnalyzer {
JetFunction function = (JetFunction) declaration;
FunctionDescriptorImpl functionDescriptorImpl = (FunctionDescriptorImpl) descriptor;
if (bodyExpression != null) {
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider);
assert readyToProcessExpressions : "Must be ready collecting types";
if (function.getReturnTypeRef() != null) {
typeInferrer.checkFunctionReturnType(declaringScope, function, descriptor);
typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptorImpl);
}
else {
JetType returnType = typeInferrer.getFunctionReturnType(declaringScope, function, descriptor);
JetType returnType = typeInferrer.getFunctionReturnType(declaringScope, function, functionDescriptorImpl);
if (returnType == null) {
returnType = ErrorUtils.createErrorType("Unable to infer body type");
}
functionDescriptorImpl.setUnsubstitutedReturnType(returnType);
}
List<JetElement> unreachableElements = new ArrayList<JetElement>();
flowInformationProvider.collectUnreachableExpressions(function, unreachableElements);
for (JetElement unreachableElement : unreachableElements) {
semanticServices.getErrorHandler().genericError(unreachableElement.getNode(), "Unreachable code");
}
}
else {
if (function.getReturnTypeRef() == null) {
......@@ -327,17 +333,44 @@ public class TopDownAnalyzer {
wrappedTrace.close();
return new JetFlowInformationProvider() {
@Override
public void collectReturnedInformation(@NotNull JetFunction function, Collection<JetExpression> returnedExpressions, Collection<JetElement> elementsReturningUnit) {
Pseudocode pseudocode = pseudocodeMap.get(function);
public void collectReturnedInformation(@NotNull JetElement subroutine, Collection<JetExpression> returnedExpressions, Collection<JetElement> elementsReturningUnit) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
processPreviousInstructions(exitInstruction, returnedExpressions, elementsReturningUnit);
processPreviousInstructions(exitInstruction, new HashSet<Instruction>(), returnedExpressions, elementsReturningUnit);
}
@Override
public void collectUnreachableExpressions(@NotNull JetElement subroutine, Collection<JetElement> unreachableElements) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
Set<Instruction> visited = new HashSet<Instruction>();
collectReachable(enterInstruction, visited);
for (Instruction instruction : pseudocode.getInstructions()) {
if (!visited.contains(instruction) && instruction instanceof JetElementInstruction) {
unreachableElements.add(((JetElementInstruction) instruction).getElement());
}
}
}
};
}
private void processPreviousInstructions(Instruction previousFor, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
private void collectReachable(Instruction current, Set<Instruction> visited) {
if (!visited.add(current)) return;
for (Instruction nextInstruction : current.getNextInstructions()) {
collectReachable(nextInstruction, visited);
}
}
private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
if (!visited.add(previousFor)) return;
Collection<Instruction> previousInstructions = previousFor.getPreviousInstructions();
InstructionVisitor visitor = new InstructionVisitor() {
@Override
......@@ -347,7 +380,7 @@ public class TopDownAnalyzer {
@Override
public void visitReturnValue(ReturnValueInstruction instruction) {
processPreviousInstructions(instruction, returnedExpressions, elementsReturningUnit);
processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
}
@Override
......@@ -372,7 +405,7 @@ public class TopDownAnalyzer {
@Override
public void visitJump(AbstractJumpInstruction instruction) {
processPreviousInstructions(instruction, returnedExpressions, elementsReturningUnit);
processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
}
@Override
......
......@@ -348,7 +348,9 @@ public class JetTypeInferrer {
}
private JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block) {
assert !block.isEmpty();
if (block.isEmpty()) {
return JetStandardClasses.getUnitType();
}
TypeInferrerVisitorWithWritableScope blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true);
......
......@@ -9,7 +9,7 @@ l6:
r(b)
jf(l8)
r(1)
ret(*)
ret(*) l5
jmp(l9)
l8:
read (Unit)
......@@ -32,7 +32,7 @@ l4:
<START>
r(2)
r(5)
ret(*)
ret(*) l5
l5:
<END>
=====================
......@@ -60,7 +60,7 @@ l0:
r(a)
jf(l2)
r(1)
ret(*)
ret(*) l1
jmp(l3)
l2:
read (Unit)
......@@ -84,7 +84,7 @@ l4:
<START>
r(2)
r(5)
ret(*)
ret(*) l5
l5:
<END>
=====================
== blockAndAndMismatch ==
fun blockAndAndMismatch() : Boolean {
(return true) || (return false)
false || (return false)
}
---------------------
l0:
<START>
r(true)
ret(*)
r(false)
jt(l2)
r(false)
ret(*)
ret(*) l1
l2:
r((return true) || (return false))
r(false || (return false))
l1:
<END>
=====================
fun blockAndAndMismatch() : Boolean {
(return true) || (return false)
false || (return false)
}
fun t1() {
return
<error>1</error>
}
fun t2() {
if (1 > 2)
return
else return
<error>1</error>
}
fun t3() {
if (1 > 2)
return 2
else return ""
<error>1</error>
}
fun t4(a : Boolean) {
do {
return
}
while (<error>a</error>)
<error>1</error>
}
//fun t5() {
// do {
// return
// }
// while (1 > 2)
// 1
//}
//fun blockAndAndMismatch() : Boolean {
// (return true) || (return false)
//}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册