ControlFlowBuilder.getExitPoint() now can return null if nothing was found #KT-10823 Fixed

Also #EA-73355 Fixed
This commit is contained in:
Mikhail Glukhikh
2016-01-27 13:43:42 +03:00
parent c5d6e8edb4
commit 26a2319d7c
7 changed files with 54 additions and 9 deletions
@@ -39,7 +39,7 @@ interface ControlFlowBuilder {
fun exitLexicalScope(element: KtElement)
fun getExitPoint(labelElement: KtElement): Label
fun getExitPoint(labelElement: KtElement): Label?
fun getConditionEntryPoint(labelElement: KtElement): Label
// Declarations
@@ -123,7 +123,7 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
delegateBuilder.throwException(throwExpression, thrownValue)
}
override fun getExitPoint(labelElement: KtElement): Label {
override fun getExitPoint(labelElement: KtElement): Label? {
return delegateBuilder.getExitPoint(labelElement)
}
@@ -785,7 +785,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val loop = getCorrespondingLoop(expression)
if (loop != null) {
checkJumpDoesNotCrossFunctionBoundary(expression, loop)
builder.jump(builder.getExitPoint(loop), expression)
builder.getExitPoint(loop)?.let { builder.jump(it, expression) }
}
}
@@ -171,9 +171,9 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
return (blockInfo as LoopInfo).conditionEntryPoint
}
override fun getExitPoint(labelElement: KtElement): Label {
val blockInfo = elementToBlockInfo[labelElement] ?: error(labelElement.text)
return blockInfo.exitPoint
override fun getExitPoint(labelElement: KtElement): Label? {
// It's quite possible to have null here, e.g. for non-local returns (see KT-10823)
return elementToBlockInfo[labelElement]?.exitPoint
}
private val currentScope: LexicalScope
@@ -217,7 +217,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
}
override fun exitSubroutine(subroutine: KtElement): Pseudocode {
bindLabel(getExitPoint(subroutine))
getExitPoint(subroutine)?.let { bindLabel(it) }
pseudocode.addExitInstruction(SubroutineExitInstruction(subroutine, currentScope, false))
bindLabel(error)
pseudocode.addErrorInstruction(SubroutineExitInstruction(subroutine, currentScope, true))
@@ -245,13 +245,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
}
override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
val exitPoint = getExitPoint(subroutine)
val exitPoint = getExitPoint(subroutine) ?: return
handleJumpInsideTryFinally(exitPoint)
add(ReturnValueInstruction(returnExpression, currentScope, exitPoint, returnValue))
}
override fun returnNoValue(returnExpression: KtReturnExpression, subroutine: KtElement) {
val exitPoint = getExitPoint(subroutine)
val exitPoint = getExitPoint(subroutine) ?: return
handleJumpInsideTryFinally(exitPoint)
add(ReturnNoValueInstruction(returnExpression, currentScope, exitPoint))
}
@@ -0,0 +1,33 @@
fun find2(): Any? {
fun visit(element: Any) {
<!RETURN_NOT_ALLOWED!>return@find2 element<!>
}
return null
}
// For find(): AssertionError at ControlFlowInstructionsGeneratorWorker.getExitPoint()
fun find(): Any? {
object : Any() {
fun visit(element: Any) {
<!RETURN_NOT_ALLOWED!>return@find element<!>
}
}
return null
}
fun find4(): Any? {
<!NOT_YET_SUPPORTED_IN_INLINE!>inline fun visit(element: Any) {
<!RETURN_NOT_ALLOWED!>return@find4 element<!>
}<!>
return null
}
fun find3(): Any? {
object : Any() {
<!NOTHING_TO_INLINE!>inline<!> fun visit(element: Any) {
<!RETURN_NOT_ALLOWED!>return@find3 element<!>
}
}
return null
}
@@ -0,0 +1,6 @@
package
public fun find(): kotlin.Any?
public fun find2(): kotlin.Any?
public fun find3(): kotlin.Any?
public fun find4(): kotlin.Any?
@@ -2889,6 +2889,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("kt10823.kt")
public void testKt10823() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt");
doTest(fileName);
}
@TestMetadata("kt1156.kt")
public void testKt1156() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1156.kt");