ControlFlowBuilder.getExitPoint() now can return null if nothing was found #KT-10823 Fixed
Also #EA-73355 Fixed
This commit is contained in:
@@ -39,7 +39,7 @@ interface ControlFlowBuilder {
|
|||||||
|
|
||||||
fun exitLexicalScope(element: KtElement)
|
fun exitLexicalScope(element: KtElement)
|
||||||
|
|
||||||
fun getExitPoint(labelElement: KtElement): Label
|
fun getExitPoint(labelElement: KtElement): Label?
|
||||||
fun getConditionEntryPoint(labelElement: KtElement): Label
|
fun getConditionEntryPoint(labelElement: KtElement): Label
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
|
|||||||
delegateBuilder.throwException(throwExpression, thrownValue)
|
delegateBuilder.throwException(throwExpression, thrownValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExitPoint(labelElement: KtElement): Label {
|
override fun getExitPoint(labelElement: KtElement): Label? {
|
||||||
return delegateBuilder.getExitPoint(labelElement)
|
return delegateBuilder.getExitPoint(labelElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -785,7 +785,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
|||||||
val loop = getCorrespondingLoop(expression)
|
val loop = getCorrespondingLoop(expression)
|
||||||
if (loop != null) {
|
if (loop != null) {
|
||||||
checkJumpDoesNotCrossFunctionBoundary(expression, loop)
|
checkJumpDoesNotCrossFunctionBoundary(expression, loop)
|
||||||
builder.jump(builder.getExitPoint(loop), expression)
|
builder.getExitPoint(loop)?.let { builder.jump(it, expression) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -171,9 +171,9 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
return (blockInfo as LoopInfo).conditionEntryPoint
|
return (blockInfo as LoopInfo).conditionEntryPoint
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExitPoint(labelElement: KtElement): Label {
|
override fun getExitPoint(labelElement: KtElement): Label? {
|
||||||
val blockInfo = elementToBlockInfo[labelElement] ?: error(labelElement.text)
|
// It's quite possible to have null here, e.g. for non-local returns (see KT-10823)
|
||||||
return blockInfo.exitPoint
|
return elementToBlockInfo[labelElement]?.exitPoint
|
||||||
}
|
}
|
||||||
|
|
||||||
private val currentScope: LexicalScope
|
private val currentScope: LexicalScope
|
||||||
@@ -217,7 +217,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun exitSubroutine(subroutine: KtElement): Pseudocode {
|
override fun exitSubroutine(subroutine: KtElement): Pseudocode {
|
||||||
bindLabel(getExitPoint(subroutine))
|
getExitPoint(subroutine)?.let { bindLabel(it) }
|
||||||
pseudocode.addExitInstruction(SubroutineExitInstruction(subroutine, currentScope, false))
|
pseudocode.addExitInstruction(SubroutineExitInstruction(subroutine, currentScope, false))
|
||||||
bindLabel(error)
|
bindLabel(error)
|
||||||
pseudocode.addErrorInstruction(SubroutineExitInstruction(subroutine, currentScope, true))
|
pseudocode.addErrorInstruction(SubroutineExitInstruction(subroutine, currentScope, true))
|
||||||
@@ -245,13 +245,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
|
override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
|
||||||
val exitPoint = getExitPoint(subroutine)
|
val exitPoint = getExitPoint(subroutine) ?: return
|
||||||
handleJumpInsideTryFinally(exitPoint)
|
handleJumpInsideTryFinally(exitPoint)
|
||||||
add(ReturnValueInstruction(returnExpression, currentScope, exitPoint, returnValue))
|
add(ReturnValueInstruction(returnExpression, currentScope, exitPoint, returnValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun returnNoValue(returnExpression: KtReturnExpression, subroutine: KtElement) {
|
override fun returnNoValue(returnExpression: KtReturnExpression, subroutine: KtElement) {
|
||||||
val exitPoint = getExitPoint(subroutine)
|
val exitPoint = getExitPoint(subroutine) ?: return
|
||||||
handleJumpInsideTryFinally(exitPoint)
|
handleJumpInsideTryFinally(exitPoint)
|
||||||
add(ReturnNoValueInstruction(returnExpression, currentScope, 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);
|
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")
|
@TestMetadata("kt1156.kt")
|
||||||
public void testKt1156() throws Exception {
|
public void testKt1156() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1156.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1156.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user