Mark expressions for correct recognition by "unreachable code"
This commit is contained in:
@@ -85,6 +85,8 @@ public interface JetControlFlowBuilder {
|
|||||||
void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel);
|
void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel);
|
||||||
|
|
||||||
// Reading values
|
// Reading values
|
||||||
|
void mark(@NotNull JetElement element);
|
||||||
|
|
||||||
void loadUnit(@NotNull JetExpression expression);
|
void loadUnit(@NotNull JetExpression expression);
|
||||||
void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant);
|
void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant);
|
||||||
void createAnonymousObject(@NotNull JetObjectLiteralExpression expression);
|
void createAnonymousObject(@NotNull JetObjectLiteralExpression expression);
|
||||||
|
|||||||
@@ -234,4 +234,9 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
|||||||
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
|
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
|
||||||
getDelegateBuilder().repeatPseudocode(startLabel, finishLabel);
|
getDelegateBuilder().repeatPseudocode(startLabel, finishLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mark(@NotNull JetElement element) {
|
||||||
|
getDelegateBuilder().mark(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.cfg;
|
package org.jetbrains.jet.lang.cfg;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.util.Ref;
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
@@ -53,17 +54,17 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
|||||||
import org.jetbrains.jet.lexer.JetToken;
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.cfg.JetControlFlowBuilder.PredefinedOperation.*;
|
import static org.jetbrains.jet.lang.cfg.JetControlFlowBuilder.PredefinedOperation.*;
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||||
|
|
||||||
public class JetControlFlowProcessor {
|
public class JetControlFlowProcessor {
|
||||||
|
|
||||||
private final JetControlFlowBuilder builder;
|
private final JetControlFlowBuilder builder;
|
||||||
private final BindingTrace trace;
|
private final BindingTrace trace;
|
||||||
|
private final Set<PsiElement> marked = new HashSet<PsiElement>();
|
||||||
|
|
||||||
public JetControlFlowProcessor(BindingTrace trace) {
|
public JetControlFlowProcessor(BindingTrace trace) {
|
||||||
this.builder = new JetControlFlowInstructionsGenerator();
|
this.builder = new JetControlFlowInstructionsGenerator();
|
||||||
@@ -140,6 +141,11 @@ public class JetControlFlowProcessor {
|
|||||||
this.inCondition = inCondition;
|
this.inCondition = inCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mark(JetElement element) {
|
||||||
|
if (!marked.add(element)) return;
|
||||||
|
builder.mark(element);
|
||||||
|
}
|
||||||
|
|
||||||
public void generateInstructions(@Nullable JetElement element) {
|
public void generateInstructions(@Nullable JetElement element) {
|
||||||
generateInstructions(element, inCondition);
|
generateInstructions(element, inCondition);
|
||||||
}
|
}
|
||||||
@@ -173,6 +179,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) {
|
public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetExpression innerExpression = expression.getExpression();
|
JetExpression innerExpression = expression.getExpression();
|
||||||
if (innerExpression != null) {
|
if (innerExpression != null) {
|
||||||
generateInstructions(innerExpression, inCondition);
|
generateInstructions(innerExpression, inCondition);
|
||||||
@@ -243,8 +250,11 @@ public class JetControlFlowProcessor {
|
|||||||
public void visitBinaryExpression(@NotNull JetBinaryExpression expression) {
|
public void visitBinaryExpression(@NotNull JetBinaryExpression expression) {
|
||||||
JetSimpleNameExpression operationReference = expression.getOperationReference();
|
JetSimpleNameExpression operationReference = expression.getOperationReference();
|
||||||
IElementType operationType = operationReference.getReferencedNameElementType();
|
IElementType operationType = operationReference.getReferencedNameElementType();
|
||||||
|
if (!ImmutableSet.of(ANDAND, OROR, EQ, ELVIS).contains(operationType)) {
|
||||||
|
mark(expression);
|
||||||
|
}
|
||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
if (operationType == JetTokens.ANDAND) {
|
if (operationType == ANDAND) {
|
||||||
generateInstructions(expression.getLeft(), true);
|
generateInstructions(expression.getLeft(), true);
|
||||||
Label resultLabel = builder.createUnboundLabel();
|
Label resultLabel = builder.createUnboundLabel();
|
||||||
builder.jumpOnFalse(resultLabel);
|
builder.jumpOnFalse(resultLabel);
|
||||||
@@ -256,7 +266,7 @@ public class JetControlFlowProcessor {
|
|||||||
builder.predefinedOperation(expression, AND);
|
builder.predefinedOperation(expression, AND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (operationType == JetTokens.OROR) {
|
else if (operationType == OROR) {
|
||||||
generateInstructions(expression.getLeft(), true);
|
generateInstructions(expression.getLeft(), true);
|
||||||
Label resultLabel = builder.createUnboundLabel();
|
Label resultLabel = builder.createUnboundLabel();
|
||||||
builder.jumpOnTrue(resultLabel);
|
builder.jumpOnTrue(resultLabel);
|
||||||
@@ -268,7 +278,7 @@ public class JetControlFlowProcessor {
|
|||||||
builder.predefinedOperation(expression, OR);
|
builder.predefinedOperation(expression, OR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (operationType == JetTokens.EQ) {
|
else if (operationType == EQ) {
|
||||||
visitAssignment(expression.getLeft(), right, expression);
|
visitAssignment(expression.getLeft(), right, expression);
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||||
@@ -286,7 +296,7 @@ public class JetControlFlowProcessor {
|
|||||||
generateBothArguments(expression);
|
generateBothArguments(expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (operationType == JetTokens.ELVIS) {
|
else if (operationType == ELVIS) {
|
||||||
generateInstructions(expression.getLeft(), false);
|
generateInstructions(expression.getLeft(), false);
|
||||||
Label afterElvis = builder.createUnboundLabel();
|
Label afterElvis = builder.createUnboundLabel();
|
||||||
builder.jumpOnTrue(afterElvis);
|
builder.jumpOnTrue(afterElvis);
|
||||||
@@ -379,6 +389,7 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> setResolvedCall) {
|
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> setResolvedCall) {
|
||||||
|
mark(arrayAccessExpression);
|
||||||
if (!checkAndGenerateCall(arrayAccessExpression, setResolvedCall)) {
|
if (!checkAndGenerateCall(arrayAccessExpression, setResolvedCall)) {
|
||||||
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
||||||
generateInstructions(index, false);
|
generateInstructions(index, false);
|
||||||
@@ -390,6 +401,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitUnaryExpression(@NotNull JetUnaryExpression expression) {
|
public void visitUnaryExpression(@NotNull JetUnaryExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
JetExpression baseExpression = expression.getBaseExpression();
|
JetExpression baseExpression = expression.getBaseExpression();
|
||||||
@@ -422,6 +434,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitIfExpression(@NotNull JetIfExpression expression) {
|
public void visitIfExpression(@NotNull JetIfExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetExpression condition = expression.getCondition();
|
JetExpression condition = expression.getCondition();
|
||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
generateInstructions(condition, true);
|
generateInstructions(condition, true);
|
||||||
@@ -476,6 +489,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTryExpression(@NotNull JetTryExpression expression) {
|
public void visitTryExpression(@NotNull JetTryExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||||
final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
|
final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
@@ -559,6 +573,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitWhileExpression(@NotNull JetWhileExpression expression) {
|
public void visitWhileExpression(@NotNull JetWhileExpression expression) {
|
||||||
|
mark(expression);
|
||||||
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
||||||
|
|
||||||
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
||||||
@@ -589,6 +604,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) {
|
public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) {
|
||||||
|
mark(expression);
|
||||||
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
||||||
|
|
||||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||||
@@ -608,6 +624,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitForExpression(@NotNull JetForExpression expression) {
|
public void visitForExpression(@NotNull JetForExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetExpression loopRange = expression.getLoopRange();
|
JetExpression loopRange = expression.getLoopRange();
|
||||||
if (loopRange != null) {
|
if (loopRange != null) {
|
||||||
generateInstructions(loopRange, false);
|
generateInstructions(loopRange, false);
|
||||||
@@ -728,6 +745,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitBlockExpression(@NotNull JetBlockExpression expression) {
|
public void visitBlockExpression(@NotNull JetBlockExpression expression) {
|
||||||
|
mark(expression);
|
||||||
List<JetElement> statements = expression.getStatements();
|
List<JetElement> statements = expression.getStatements();
|
||||||
for (JetElement statement : statements) {
|
for (JetElement statement : statements) {
|
||||||
generateInstructions(statement, false);
|
generateInstructions(statement, false);
|
||||||
@@ -744,6 +762,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) {
|
public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||||
processLocalDeclaration(functionLiteral);
|
processLocalDeclaration(functionLiteral);
|
||||||
builder.createFunctionLiteral(expression);
|
builder.createFunctionLiteral(expression);
|
||||||
@@ -751,6 +770,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) {
|
public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||||
if (selectorExpression != null) {
|
if (selectorExpression != null) {
|
||||||
final Ref<Boolean> error = new Ref<Boolean>(false);
|
final Ref<Boolean> error = new Ref<Boolean>(false);
|
||||||
@@ -777,6 +797,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitCallExpression(@NotNull JetCallExpression expression) {
|
public void visitCallExpression(@NotNull JetCallExpression expression) {
|
||||||
|
mark(expression);
|
||||||
if (!generateCall(expression.getCalleeExpression())) {
|
if (!generateCall(expression.getCalleeExpression())) {
|
||||||
for (ValueArgument argument : expression.getValueArguments()) {
|
for (ValueArgument argument : expression.getValueArguments()) {
|
||||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||||
@@ -834,6 +855,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression) {
|
public void visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression) {
|
||||||
|
mark(expression);
|
||||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||||
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
|
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
|
||||||
generateInstructions(expression.getLeft(), false);
|
generateInstructions(expression.getLeft(), false);
|
||||||
@@ -845,6 +867,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitThrowExpression(@NotNull JetThrowExpression expression) {
|
public void visitThrowExpression(@NotNull JetThrowExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetExpression thrownExpression = expression.getThrownExpression();
|
JetExpression thrownExpression = expression.getThrownExpression();
|
||||||
if (thrownExpression != null) {
|
if (thrownExpression != null) {
|
||||||
generateInstructions(thrownExpression, false);
|
generateInstructions(thrownExpression, false);
|
||||||
@@ -854,6 +877,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
|
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
|
||||||
|
mark(expression);
|
||||||
if (!generateCall(expression)) {
|
if (!generateCall(expression)) {
|
||||||
generateArrayAccess(expression, getResolvedCall(expression));
|
generateArrayAccess(expression, getResolvedCall(expression));
|
||||||
}
|
}
|
||||||
@@ -861,11 +885,13 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitIsExpression(@NotNull JetIsExpression expression) {
|
public void visitIsExpression(@NotNull JetIsExpression expression) {
|
||||||
|
mark(expression);
|
||||||
generateInstructions(expression.getLeftHandSide(), inCondition);
|
generateInstructions(expression.getLeftHandSide(), inCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitWhenExpression(@NotNull JetWhenExpression expression) {
|
public void visitWhenExpression(@NotNull JetWhenExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetExpression subjectExpression = expression.getSubjectExpression();
|
JetExpression subjectExpression = expression.getSubjectExpression();
|
||||||
if (subjectExpression != null) {
|
if (subjectExpression != null) {
|
||||||
generateInstructions(subjectExpression, inCondition);
|
generateInstructions(subjectExpression, inCondition);
|
||||||
@@ -877,6 +903,7 @@ public class JetControlFlowProcessor {
|
|||||||
Label nextLabel = null;
|
Label nextLabel = null;
|
||||||
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
|
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
|
||||||
JetWhenEntry whenEntry = iterator.next();
|
JetWhenEntry whenEntry = iterator.next();
|
||||||
|
mark(whenEntry);
|
||||||
|
|
||||||
boolean isElse = whenEntry.isElse();
|
boolean isElse = whenEntry.isElse();
|
||||||
if (isElse) {
|
if (isElse) {
|
||||||
@@ -917,6 +944,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression) {
|
public void visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression) {
|
||||||
|
mark(expression);
|
||||||
JetObjectDeclaration declaration = expression.getObjectDeclaration();
|
JetObjectDeclaration declaration = expression.getObjectDeclaration();
|
||||||
generateInstructions(declaration, inCondition);
|
generateInstructions(declaration, inCondition);
|
||||||
|
|
||||||
@@ -940,6 +968,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression) {
|
public void visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression) {
|
||||||
|
mark(expression);
|
||||||
for (JetStringTemplateEntry entry : expression.getEntries()) {
|
for (JetStringTemplateEntry entry : expression.getEntries()) {
|
||||||
if (entry instanceof JetStringTemplateEntryWithExpression) {
|
if (entry instanceof JetStringTemplateEntryWithExpression) {
|
||||||
JetStringTemplateEntryWithExpression entryWithExpression = (JetStringTemplateEntryWithExpression) entry;
|
JetStringTemplateEntryWithExpression entryWithExpression = (JetStringTemplateEntryWithExpression) entry;
|
||||||
|
|||||||
@@ -109,6 +109,11 @@ public class JetFlowInformationProvider {
|
|||||||
redirectToPrevInstructions(instruction);
|
redirectToPrevInstructions(instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMarkInstruction(MarkInstruction instruction) {
|
||||||
|
redirectToPrevInstructions(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitInstruction(Instruction instruction) {
|
public void visitInstruction(Instruction instruction) {
|
||||||
if (instruction instanceof JetElementInstruction) {
|
if (instruction instanceof JetElementInstruction) {
|
||||||
|
|||||||
@@ -95,4 +95,9 @@ public class InstructionVisitor {
|
|||||||
public void visitCompilationErrorInstruction(CompilationErrorInstruction instruction) {
|
public void visitCompilationErrorInstruction(CompilationErrorInstruction instruction) {
|
||||||
visitInstructionWithNext(instruction);
|
visitInstructionWithNext(instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitMarkInstruction(MarkInstruction instruction) {
|
||||||
|
visitInstructionWithNext(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -229,6 +229,11 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
return pseudocode;
|
return pseudocode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mark(@NotNull JetElement element) {
|
||||||
|
add(new MarkInstruction(element));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine) {
|
public void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine) {
|
||||||
Label exitPoint = getExitPoint(subroutine);
|
Label exitPoint = getExitPoint(subroutine);
|
||||||
|
|||||||
@@ -46,4 +46,20 @@ class CompilationErrorInstruction(
|
|||||||
override fun createCopy() = CompilationErrorInstruction(element, message)
|
override fun createCopy() = CompilationErrorInstruction(element, message)
|
||||||
|
|
||||||
override fun toString() = "error(${render(element)}, $message)"
|
override fun toString() = "error(${render(element)}, $message)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// This instruciton is used to let the dead code detector know the syntactic structure of unreachable code
|
||||||
|
// otherwise only individual parts of expression would be reported as unreachable
|
||||||
|
// e.g. for (i in foo) {} -- only i and foo would be marked unreachable
|
||||||
|
class MarkInstruction(
|
||||||
|
element: JetElement
|
||||||
|
) : InstructionWithNext(element) {
|
||||||
|
|
||||||
|
override fun accept(visitor: InstructionVisitor) {
|
||||||
|
visitor.visitMarkInstruction(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createCopy() = MarkInstruction(element)
|
||||||
|
|
||||||
|
override fun toString() = "mark(${render(element)})"
|
||||||
}
|
}
|
||||||
@@ -2,32 +2,28 @@
|
|||||||
fun illegalWhenBlock(a: Any): Any {
|
fun illegalWhenBlock(a: Any): Any {
|
||||||
when(a) {
|
when(a) {
|
||||||
is Int -> return a
|
is Int -> return a
|
||||||
is String -> return a
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
L0:
|
L0:
|
||||||
<START>
|
<START>
|
||||||
v(a: Any)
|
v(a: Any)
|
||||||
w(a)
|
w(a)
|
||||||
r(a)
|
mark({ when(a) { is Int -> return a } })
|
||||||
jmp?(L4) NEXT:[jmp?(L6), r(a)]
|
mark(when(a) { is Int -> return a })
|
||||||
|
r(a)
|
||||||
|
mark(is Int -> return a)
|
||||||
|
jmp?(L4) NEXT:[<END>, r(a)]
|
||||||
L3:
|
L3:
|
||||||
r(a)
|
r(a)
|
||||||
ret(*) L1 NEXT:[<END>]
|
ret(*) L1 NEXT:[<END>]
|
||||||
- jmp(L2) NEXT:[<END>] PREV:[]
|
- jmp(L2) PREV:[]
|
||||||
L4:
|
|
||||||
jmp?(L6) NEXT:[<END>, r(a)] PREV:[jmp?(L4)]
|
|
||||||
L5:
|
|
||||||
r(a)
|
|
||||||
ret(*) L1 NEXT:[<END>]
|
|
||||||
- jmp(L2) PREV:[]
|
|
||||||
L1:
|
L1:
|
||||||
L2:
|
L2:
|
||||||
L6:
|
L4:
|
||||||
<END> NEXT:[<SINK>] PREV:[ret(*) L1, jmp?(L6), ret(*) L1]
|
<END> NEXT:[<SINK>] PREV:[jmp?(L4), ret(*) L1]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
fun illegalWhenBlock(a: Any): Any {
|
fun illegalWhenBlock(a: Any): Any {
|
||||||
when(a) {
|
when(a) {
|
||||||
is Int -> return a
|
is Int -> return a
|
||||||
is String -> return a
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,9 +137,9 @@ fun tf() : Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun failtest(<!UNUSED_PARAMETER!>a<!> : Int) : Int {
|
fun failtest(<!UNUSED_PARAMETER!>a<!> : Int) : Int {
|
||||||
if (fail() || <!UNREACHABLE_CODE!>true<!>) {
|
if (fail() || <!UNREACHABLE_CODE!>true<!>) <!UNREACHABLE_CODE!>{
|
||||||
|
|
||||||
}
|
}<!>
|
||||||
<!UNREACHABLE_CODE!>return 1<!>
|
<!UNREACHABLE_CODE!>return 1<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
fun foo(<!UNUSED_PARAMETER!>a<!>: Any) {}
|
||||||
|
fun bar(<!UNUSED_PARAMETER!>a<!>: Any, <!UNUSED_PARAMETER!>b<!>: Any) {}
|
||||||
|
|
||||||
|
fun test(arr: Array<Int>) {
|
||||||
|
while (true) {
|
||||||
|
<!UNREACHABLE_CODE!>foo<!>(break)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
<!UNREACHABLE_CODE!>bar<!>(arr, break)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
<!UNREACHABLE_CODE!>arr[break]<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
<!UNREACHABLE_CODE!>arr[1]<!> = break
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
break
|
||||||
|
<!UNREACHABLE_CODE!>foo(1)<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var <!UNUSED_VARIABLE!>x<!> = 1
|
||||||
|
break
|
||||||
|
<!UNREACHABLE_CODE!>x = 2<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var <!UNUSED_VARIABLE!>x<!> = 1
|
||||||
|
<!UNREACHABLE_CODE!>x = break<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: bug, should be fixed in CFA
|
||||||
|
while (true) {
|
||||||
|
if (1 > 2 && break && 2 > 3) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: bug, should be fixed in CFA
|
||||||
|
while (true) {
|
||||||
|
if (1 > 2 || break || 2 > 3) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
<!USELESS_ELVIS!>break<!> ?: <!UNREACHABLE_CODE!>null<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,5 +7,4 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback is unused due to KT-4233
|
fun test<R>(callback: (R) -> Unit):Unit = <!UNREACHABLE_CODE!>callback<!>(null!!)
|
||||||
fun test<R>(<!UNUSED_PARAMETER!>callback<!>: (R) -> Unit):Unit = <!UNREACHABLE_CODE!>callback(null!!)<!>
|
|
||||||
@@ -9,9 +9,9 @@ fun test(a: Int) {
|
|||||||
bar(a, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
bar(a, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||||
}
|
}
|
||||||
fun test1(a: Int) {
|
fun test1(a: Int) {
|
||||||
<!UNREACHABLE_CODE!>foo(a, throw Exception())<!>
|
<!UNREACHABLE_CODE!>foo<!>(a, throw Exception())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2(a: Int) {
|
fun test2(a: Int) {
|
||||||
<!UNREACHABLE_CODE!>bar(a, throw Exception())<!>
|
<!UNREACHABLE_CODE!>bar<!>(a, throw Exception())
|
||||||
}
|
}
|
||||||
@@ -1562,6 +1562,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninitializedInLocalDeclarations.kt");
|
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninitializedInLocalDeclarations.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unreachableCode.kt")
|
||||||
|
public void testUnreachableCode() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/controlStructures")
|
@TestMetadata("compiler/testData/diagnostics/tests/controlStructures")
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ fun tf() : Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun failtest(<warning>a</warning> : Int) : Int {
|
fun failtest(<warning>a</warning> : Int) : Int {
|
||||||
if (fail() || <warning>true</warning>) {
|
if (fail() || <warning>true</warning>) <warning>{
|
||||||
|
|
||||||
}
|
}</warning>
|
||||||
<warning>return 1</warning>
|
<warning>return 1</warning>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user