diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index a1f1e69dbac..8c175f880aa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -77,9 +77,12 @@ public interface JetControlFlowBuilder { JetElement getCurrentSubroutine(); @Nullable JetElement getReturnSubroutine(); + void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine); void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine); + + void throwException(@NotNull JetThrowExpression throwExpression); void write(@NotNull JetElement assignment, @NotNull JetElement lValue); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java index dcc16c88dc6..8c067737546 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -119,6 +119,11 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { } @Override + public void throwException(@NotNull JetThrowExpression throwExpression) { + assert builder != null; + builder.throwException(throwExpression); + } + public Label getEntryPoint(@NotNull JetElement labelElement) { assert builder != null; return builder.getEntryPoint(labelElement); @@ -131,7 +136,7 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { } @Override - public LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) { + public LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, Label conditionEntryPoint) { assert builder != null; return builder.enterLoop(expression, loopExitPoint, conditionEntryPoint); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 2d9dde278e2..cc2a4facd96 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -418,7 +418,9 @@ public class JetControlFlowProcessor { for (int i = 0; i < catchClausesSize - 1; i++) { catchLabels.add(builder.createUnboundLabel("catch " + i)); } - builder.nondeterministicJump(catchLabels); + if (!catchLabels.isEmpty()) { + builder.nondeterministicJump(catchLabels); + } boolean isFirst = true; for (JetCatchClause catchClause : catchClauses) { if (!isFirst) { @@ -781,7 +783,7 @@ public class JetControlFlowProcessor { if (thrownExpression != null) { value(thrownExpression, false); } - builder.jumpToError(); + builder.throwException(expression); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionVisitor.java index 4261abf3549..a34b0b747e7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionVisitor.java @@ -48,6 +48,10 @@ public class InstructionVisitor { visitJump(instruction); } + public void visitThrowExceptionInstruction(ThrowExceptionInstruction instruction) { + visitJump(instruction); + } + public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { visitInstruction(instruction); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index 42ce80f3e2a..0af9647a4ba 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.*; import org.jetbrains.jet.lang.psi.*; @@ -184,7 +185,8 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd BlockInfo blockInfo = allBlocks.get(i); if (blockInfo instanceof BreakableBlockInfo) { BreakableBlockInfo breakableBlockInfo = (BreakableBlockInfo) blockInfo; - if (jumpTarget == breakableBlockInfo.getExitPoint() || jumpTarget == breakableBlockInfo.getEntryPoint()) { + if (jumpTarget == breakableBlockInfo.getExitPoint() || jumpTarget == breakableBlockInfo.getEntryPoint() + || jumpTarget == error) { for (int j = finallyBlocks.size() - 1; j >= 0; j--) { finallyBlocks.get(j).generateFinallyBlock(); } @@ -310,15 +312,21 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd @Override public void jumpToError() { + handleJumpInsideTryFinally(error); add(new UnconditionalJumpInstruction(error)); } - + @Override public void enterTryFinally(@NotNull GenerationTrigger generationTrigger) { allBlocks.push(new TryFinallyBlockInfo(generationTrigger)); } @Override + public void throwException(@NotNull JetThrowExpression expression) { + handleJumpInsideTryFinally(error); + add(new ThrowExceptionInstruction(expression, error)); + } + public void exitTryFinally() { BlockInfo pop = allBlocks.pop(); assert pop instanceof TryFinallyBlockInfo; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/ThrowExceptionInstruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/ThrowExceptionInstruction.java new file mode 100644 index 00000000000..cffe808f581 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/ThrowExceptionInstruction.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.cfg.pseudocode; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.cfg.Label; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetThrowExpression; + +public class ThrowExceptionInstruction extends AbstractJumpInstruction implements JetElementInstruction { + private final JetThrowExpression expression; + + public ThrowExceptionInstruction(@NotNull JetThrowExpression expression, @NotNull Label errorLabel) { + super(errorLabel); + this.expression = expression; + } + + @NotNull + @Override + public JetExpression getElement() { + return expression; + } + + @Override + public String toString() { + return "throw (" + expression.getText() + ")"; + } + + @Override + public void accept(InstructionVisitor visitor) { + visitor.visitThrowExceptionInstruction(this); + } + + @Override + protected AbstractJumpInstruction createCopy(@NotNull Label newLabel) { + return new ThrowExceptionInstruction(expression, newLabel); + } +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.kt b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.kt index 82e21b339ff..e90ce7eb897 100644 --- a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.kt +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.kt @@ -5,5 +5,5 @@ fun foo() { if (x == null) throw bar(x) throw bar(x) - throw bar(x) -} + throw bar(x) +} \ No newline at end of file