Handle unresolved break/continue expressions as error expressions.
This commit is contained in:
committed by
Dmitry Petrov
parent
c0ac607a1d
commit
0da4c08520
+9
-5
@@ -47,14 +47,18 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
|
||||
}
|
||||
|
||||
fun generateBreak(ktBreak: KtBreakExpression): IrExpression {
|
||||
val parentLoop = findParentLoop(ktBreak)
|
||||
val parentLoop = findParentLoop(ktBreak) ?:
|
||||
return ErrorExpressionGenerator(statementGenerator).generateErrorExpression(
|
||||
ktBreak, RuntimeException("Loop not found for break expression: ${ktBreak.text}"))
|
||||
return IrBreakImpl(ktBreak.startOffset, ktBreak.endOffset, context.builtIns.nothingType, parentLoop).apply {
|
||||
label = ktBreak.getLabelName()
|
||||
}
|
||||
}
|
||||
|
||||
fun generateContinue(ktContinue: KtContinueExpression): IrExpression {
|
||||
val parentLoop = findParentLoop(ktContinue)
|
||||
val parentLoop = findParentLoop(ktContinue) ?:
|
||||
return ErrorExpressionGenerator(statementGenerator).generateErrorExpression(
|
||||
ktContinue, RuntimeException("Loop not found for continue expression: ${ktContinue.text}"))
|
||||
return IrContinueImpl(ktContinue.startOffset, ktContinue.endOffset, context.builtIns.nothingType, parentLoop).apply {
|
||||
label = ktContinue.getLabelName()
|
||||
}
|
||||
@@ -63,10 +67,10 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
|
||||
private fun getLoopLabel(ktLoop: KtLoopExpression): String? =
|
||||
(ktLoop.parent as? KtLabeledExpression)?.getLabelName()
|
||||
|
||||
private fun findParentLoop(ktWithLabel: KtExpressionWithLabel): IrLoop =
|
||||
private fun findParentLoop(ktWithLabel: KtExpressionWithLabel): IrLoop? =
|
||||
findParentLoop(ktWithLabel, ktWithLabel.getLabelName())
|
||||
|
||||
private fun findParentLoop(ktExpression: KtExpression, targetLabel: String?): IrLoop {
|
||||
private fun findParentLoop(ktExpression: KtExpression, targetLabel: String?): IrLoop? {
|
||||
var finger: KtExpression? = ktExpression
|
||||
while (finger != null) {
|
||||
finger = finger.getParentOfType<KtLoopExpression>(true)
|
||||
@@ -86,7 +90,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
|
||||
}
|
||||
}
|
||||
}
|
||||
throw AssertionError("No parent loop for break/continue @$targetLabel")
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getLoop(ktLoop: KtLoopExpression): IrLoop? {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// !IGNORE_ERRORS
|
||||
|
||||
fun test1() {
|
||||
break
|
||||
continue
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
L1@ while (true) {
|
||||
break@ERROR
|
||||
continue@ERROR
|
||||
}
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
L1@ while (true) {
|
||||
val lambda = {
|
||||
break@L1
|
||||
continue@L1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
while (break) {}
|
||||
while (continue) {}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
FILE /badBreakContinue.kt
|
||||
FUN public fun test1(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||
FUN public fun test2(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
WHILE label=L1 operator=WHILE_LOOP
|
||||
condition: CONST Boolean type=kotlin.Boolean value='true'
|
||||
body: BLOCK type=kotlin.Nothing operator=null
|
||||
ERROR_EXPR 'Loop not found for break expression: break@ERROR' type=kotlin.Nothing
|
||||
ERROR_EXPR 'Loop not found for continue expression: continue@ERROR' type=kotlin.Nothing
|
||||
FUN public fun test3(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
WHILE label=L1 operator=WHILE_LOOP
|
||||
condition: CONST Boolean type=kotlin.Boolean value='true'
|
||||
body: BLOCK type=kotlin.Unit operator=null
|
||||
VAR val lambda: () -> kotlin.Nothing
|
||||
BLOCK type=() -> kotlin.Nothing operator=LAMBDA
|
||||
FUN local final fun <anonymous>(): kotlin.Nothing
|
||||
BLOCK_BODY
|
||||
ERROR_EXPR 'Loop not found for break expression: break@L1' type=kotlin.Nothing
|
||||
ERROR_EXPR 'Loop not found for continue expression: continue@L1' type=kotlin.Nothing
|
||||
CALLABLE_REFERENCE '<anonymous>(): Nothing' type=() -> kotlin.Nothing operator=LAMBDA
|
||||
FUN public fun test4(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
WHILE label=null operator=WHILE_LOOP
|
||||
condition: ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||
body: BLOCK type=kotlin.Unit operator=null
|
||||
WHILE label=null operator=WHILE_LOOP
|
||||
condition: ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||
body: BLOCK type=kotlin.Unit operator=null
|
||||
@@ -280,6 +280,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("badBreakContinue.kt")
|
||||
public void testBadBreakContinue() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("bangbang.kt")
|
||||
public void testBangbang() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/bangbang.kt");
|
||||
|
||||
Reference in New Issue
Block a user