diff --git a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionGenerator.kt b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionGenerator.kt index 1a09affd0be..d1cce279f01 100644 --- a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionGenerator.kt @@ -102,6 +102,30 @@ class FunctionGenerator(val function: IrFunction) { return expression } + override fun visitWhen(expression: IrWhen, data: Boolean): IrElement? { + if (data) { + builder.add(expression) + } + val whenExit = MergeCfgElement(expression, "When exit") + val branches = expression.branches + for (branch in branches) { + val condition = branch.condition + condition.process(includeSelf = false) + builder.jump(condition) + } + for (branch in branches) { + val result = branch.result + builder.move(branch.condition) + if (!result.process().isNothing()) { + builder.jump(whenExit) + } + else { + builder.move(branch.condition) + } + } + return whenExit + } + override fun visitElement(element: IrElement, data: Boolean): IrElement? { TODO("not implemented") } diff --git a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/GeneralConnectorBuilder.kt b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/GeneralConnectorBuilder.kt index 0b77c1d69e2..0586a5def9e 100644 --- a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/GeneralConnectorBuilder.kt +++ b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/GeneralConnectorBuilder.kt @@ -36,9 +36,9 @@ class GeneralConnectorBuilder(private val element: IrElement) : BlockConnectorBu } override fun build() = when { - next.size == 1 -> JoinBlockConnector(previous.toReadOnlyList(), element, next.single()) + next.size <= 1 -> JoinBlockConnector(previous.toReadOnlyList(), element, next.firstOrNull()) previous.size == 1 -> SplitBlockConnector(previous.single(), element, next.toReadOnlyList()) - else -> throw AssertionError("Connector should have either exactly one previous block or exactly one next block, " + + else -> throw AssertionError("Connector should have either exactly one previous block or no more than one next block, " + "actual previous = ${previous.size}, next = ${next.size}") } } \ No newline at end of file diff --git a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/JoinBlockConnector.kt b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/JoinBlockConnector.kt index 94cf86e4c4b..750f2b0e277 100644 --- a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/JoinBlockConnector.kt +++ b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/JoinBlockConnector.kt @@ -23,8 +23,8 @@ import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector class JoinBlockConnector( override val previousBlocks: List, override val element: IrElement, - next: BasicBlock + next: BasicBlock? ) : BlockConnector { - override val nextBlocks = listOf(next) + override val nextBlocks = listOfNotNull(next) } \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/when/cascadeIf.kt b/compiler/testData/ir/irCfg/when/cascadeIf.kt new file mode 100644 index 00000000000..736e63eb7c0 --- /dev/null +++ b/compiler/testData/ir/irCfg/when/cascadeIf.kt @@ -0,0 +1 @@ +fun compare(x: Int, y: Int) = if (x > y) 1 else if (x < y) -1 else 0 \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/when/cascadeIf.txt b/compiler/testData/ir/irCfg/when/cascadeIf.txt new file mode 100644 index 00000000000..f18fdeeacce --- /dev/null +++ b/compiler/testData/ir/irCfg/when/cascadeIf.txt @@ -0,0 +1,53 @@ +// FILE: /cascadeIf.kt +// FUN: compare +BB 0 +CONTENT + 1 FUN public fun compare(x: kotlin.Int, y: kotlin.Int): kotlin.Int + 2 WHEN type=kotlin.Int origin=WHEN +OUTGOING -> BB 1, 3 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +BB 1 +INCOMING <- BB 0 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +CONTENT +OUTGOING -> BB 2, 4 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +BB 2 +INCOMING <- BB 1 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT +OUTGOING -> BB 5 + CONST Boolean type=kotlin.Boolean value='true' +BB 3 +INCOMING <- BB 0 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +CONTENT + 1 CONST Int type=kotlin.Int value='1' +OUTGOING -> BB 6 + When exit: WHEN type=kotlin.Int origin=WHEN +BB 4 +INCOMING <- BB 1 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT + 1 CONST Int type=kotlin.Int value='-1' +OUTGOING -> BB 6 + When exit: WHEN type=kotlin.Int origin=WHEN +BB 5 +INCOMING <- BB 2 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 CONST Int type=kotlin.Int value='0' +OUTGOING -> BB 6 + When exit: WHEN type=kotlin.Int origin=WHEN +BB 6 +INCOMING <- BB 3, 4, 5 + When exit: WHEN type=kotlin.Int origin=WHEN +CONTENT + 1 RETURN type=kotlin.Nothing from='compare(Int, Int): Int' +OUTGOING -> NONE + Function exit: FUN public fun compare(x: kotlin.Int, y: kotlin.Int): kotlin.Int + +// END FUN: compare + +// END FILE: /cascadeIf.kt + diff --git a/compiler/testData/ir/irCfg/when/emptyWhen.kt b/compiler/testData/ir/irCfg/when/emptyWhen.kt new file mode 100644 index 00000000000..98c25237275 --- /dev/null +++ b/compiler/testData/ir/irCfg/when/emptyWhen.kt @@ -0,0 +1,3 @@ +fun empty() = when { + else -> 42 +} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/when/emptyWhen.txt b/compiler/testData/ir/irCfg/when/emptyWhen.txt new file mode 100644 index 00000000000..4ac02015210 --- /dev/null +++ b/compiler/testData/ir/irCfg/when/emptyWhen.txt @@ -0,0 +1,27 @@ +// FILE: /emptyWhen.kt +// FUN: empty +BB 0 +CONTENT + 1 FUN public fun empty(): kotlin.Int + 2 WHEN type=kotlin.Int origin=WHEN +OUTGOING -> BB 1 + CONST Boolean type=kotlin.Boolean value='true' +BB 1 +INCOMING <- BB 0 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 CONST Int type=kotlin.Int value='42' +OUTGOING -> BB 2 + When exit: WHEN type=kotlin.Int origin=WHEN +BB 2 +INCOMING <- BB 1 + When exit: WHEN type=kotlin.Int origin=WHEN +CONTENT + 1 RETURN type=kotlin.Nothing from='empty(): Int' +OUTGOING -> NONE + Function exit: FUN public fun empty(): kotlin.Int + +// END FUN: empty + +// END FILE: /emptyWhen.kt + diff --git a/compiler/testData/ir/irCfg/when/expressionIf.kt b/compiler/testData/ir/irCfg/when/expressionIf.kt new file mode 100644 index 00000000000..575dc2f31fd --- /dev/null +++ b/compiler/testData/ir/irCfg/when/expressionIf.kt @@ -0,0 +1 @@ +fun max(x: Int, y: Int) = if (x > y) x else y \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/when/expressionIf.txt b/compiler/testData/ir/irCfg/when/expressionIf.txt new file mode 100644 index 00000000000..e9a440ddcc3 --- /dev/null +++ b/compiler/testData/ir/irCfg/when/expressionIf.txt @@ -0,0 +1,40 @@ +// FILE: /expressionIf.kt +// FUN: max +BB 0 +CONTENT + 1 FUN public fun max(x: kotlin.Int, y: kotlin.Int): kotlin.Int + 2 WHEN type=kotlin.Int origin=null +OUTGOING -> BB 1, 2 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +BB 1 +INCOMING <- BB 0 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +CONTENT +OUTGOING -> BB 3 + CONST Boolean type=kotlin.Boolean value='true' +BB 2 +INCOMING <- BB 0 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +CONTENT + 1 GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=null +OUTGOING -> BB 4 + When exit: WHEN type=kotlin.Int origin=null +BB 3 +INCOMING <- BB 1 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 GET_VAR 'value-parameter y: Int' type=kotlin.Int origin=null +OUTGOING -> BB 4 + When exit: WHEN type=kotlin.Int origin=null +BB 4 +INCOMING <- BB 2, 3 + When exit: WHEN type=kotlin.Int origin=null +CONTENT + 1 RETURN type=kotlin.Nothing from='max(Int, Int): Int' +OUTGOING -> NONE + Function exit: FUN public fun max(x: kotlin.Int, y: kotlin.Int): kotlin.Int + +// END FUN: max + +// END FILE: /expressionIf.kt + diff --git a/compiler/testData/ir/irCfg/when/ifChain.kt b/compiler/testData/ir/irCfg/when/ifChain.kt new file mode 100644 index 00000000000..6ea0fc912ef --- /dev/null +++ b/compiler/testData/ir/irCfg/when/ifChain.kt @@ -0,0 +1,14 @@ +fun minBiRoot(a: Double, b: Double, c: Double): Double { + if (a == 0.0) { + if (b == 0.0) return 1.0 + val bc = -c / b + if (bc < 0.0) return 2.0 + return -bc + } + val d = b * b - 4 * a * c + if (d < 0.0) return 3.0 + val y1 = (-b + d) / (2 * a) + val y2 = (-b - d) / (2 * a) + val y3 = if (y1 > y2) y1 else y2 + return if (y3 < 0.0) 4.0 else -y3 +} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/when/ifChain.txt b/compiler/testData/ir/irCfg/when/ifChain.txt new file mode 100644 index 00000000000..fb6bb644a70 --- /dev/null +++ b/compiler/testData/ir/irCfg/when/ifChain.txt @@ -0,0 +1,136 @@ +// FILE: /ifChain.kt +// FUN: minBiRoot +BB 0 +CONTENT + 1 FUN public fun minBiRoot(a: kotlin.Double, b: kotlin.Double, c: kotlin.Double): kotlin.Double + 2 WHEN type=kotlin.Unit origin=null +OUTGOING -> BB 1, 6 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +BB 1 +INCOMING <- BB 0 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 WHEN type=kotlin.Unit origin=null +OUTGOING -> BB 2, 3 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +BB 2 +INCOMING <- BB 1 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CONST Double type=kotlin.Double value='1.0' + 2 RETURN type=kotlin.Nothing from='minBiRoot(Double, Double, Double): Double' +OUTGOING -> NONE + Function exit: FUN public fun minBiRoot(a: kotlin.Double, b: kotlin.Double, c: kotlin.Double): kotlin.Double +BB 3 +INCOMING <- BB 1 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CALL 'div(Double): Double' type=kotlin.Double origin=DIV + 2 VAR val bc: kotlin.Double + 3 WHEN type=kotlin.Unit origin=null +OUTGOING -> BB 4, 5 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +BB 4 +INCOMING <- BB 3 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT + 1 CONST Double type=kotlin.Double value='2.0' + 2 RETURN type=kotlin.Nothing from='minBiRoot(Double, Double, Double): Double' +OUTGOING -> NONE + Function exit: FUN public fun minBiRoot(a: kotlin.Double, b: kotlin.Double, c: kotlin.Double): kotlin.Double +BB 5 +INCOMING <- BB 3 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT + 1 CALL 'unaryMinus(): Double' type=kotlin.Double origin=UMINUS + 2 RETURN type=kotlin.Nothing from='minBiRoot(Double, Double, Double): Double' +OUTGOING -> NONE + Function exit: FUN public fun minBiRoot(a: kotlin.Double, b: kotlin.Double, c: kotlin.Double): kotlin.Double +BB 6 +INCOMING <- BB 0 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CALL 'minus(Double): Double' type=kotlin.Double origin=MINUS + 2 VAR val d: kotlin.Double + 3 WHEN type=kotlin.Unit origin=null +OUTGOING -> BB 7, 8 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +BB 7 +INCOMING <- BB 6 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT + 1 CONST Double type=kotlin.Double value='3.0' + 2 RETURN type=kotlin.Nothing from='minBiRoot(Double, Double, Double): Double' +OUTGOING -> NONE + Function exit: FUN public fun minBiRoot(a: kotlin.Double, b: kotlin.Double, c: kotlin.Double): kotlin.Double +BB 8 +INCOMING <- BB 6 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT + 1 CALL 'div(Double): Double' type=kotlin.Double origin=DIV + 2 VAR val y1: kotlin.Double + 3 CALL 'div(Double): Double' type=kotlin.Double origin=DIV + 4 VAR val y2: kotlin.Double + 5 WHEN type=kotlin.Double origin=null +OUTGOING -> BB 9, 10 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +BB 9 +INCOMING <- BB 8 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +CONTENT +OUTGOING -> BB 11 + CONST Boolean type=kotlin.Boolean value='true' +BB 10 +INCOMING <- BB 8 + CALL 'GT0(Int): Boolean' type=kotlin.Boolean origin=GT +CONTENT + 1 GET_VAR 'y1: Double' type=kotlin.Double origin=null +OUTGOING -> BB 12 + When exit: WHEN type=kotlin.Double origin=null +BB 11 +INCOMING <- BB 9 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 GET_VAR 'y2: Double' type=kotlin.Double origin=null +OUTGOING -> BB 12 + When exit: WHEN type=kotlin.Double origin=null +BB 12 +INCOMING <- BB 10, 11 + When exit: WHEN type=kotlin.Double origin=null +CONTENT + 1 VAR val y3: kotlin.Double + 2 WHEN type=kotlin.Double origin=null +OUTGOING -> BB 13, 14 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +BB 13 +INCOMING <- BB 12 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT +OUTGOING -> BB 15 + CONST Boolean type=kotlin.Boolean value='true' +BB 14 +INCOMING <- BB 12 + CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT +CONTENT + 1 CONST Double type=kotlin.Double value='4.0' +OUTGOING -> BB 16 + When exit: WHEN type=kotlin.Double origin=null +BB 15 +INCOMING <- BB 13 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 CALL 'unaryMinus(): Double' type=kotlin.Double origin=UMINUS +OUTGOING -> BB 16 + When exit: WHEN type=kotlin.Double origin=null +BB 16 +INCOMING <- BB 14, 15 + When exit: WHEN type=kotlin.Double origin=null +CONTENT + 1 RETURN type=kotlin.Nothing from='minBiRoot(Double, Double, Double): Double' +OUTGOING -> NONE + Function exit: FUN public fun minBiRoot(a: kotlin.Double, b: kotlin.Double, c: kotlin.Double): kotlin.Double + +// END FUN: minBiRoot + +// END FILE: /ifChain.kt + diff --git a/compiler/testData/ir/irCfg/when/whenReturn.kt b/compiler/testData/ir/irCfg/when/whenReturn.kt new file mode 100644 index 00000000000..b692e1f2dab --- /dev/null +++ b/compiler/testData/ir/irCfg/when/whenReturn.kt @@ -0,0 +1,10 @@ +fun toString(grade: String): String { + when (grade) { + "A" -> return "Excellent" + "B" -> return "Good" + "C" -> return "Mediocre" + "D" -> return "Fair" + else -> return "Failure" + } + return "???" +} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/when/whenReturn.txt b/compiler/testData/ir/irCfg/when/whenReturn.txt new file mode 100644 index 00000000000..a8c8157a1ad --- /dev/null +++ b/compiler/testData/ir/irCfg/when/whenReturn.txt @@ -0,0 +1,87 @@ +// FILE: /whenReturn.kt +// FUN: toString +BB 0 +CONTENT + 1 FUN public fun toString(grade: kotlin.String): kotlin.String + 2 GET_VAR 'value-parameter grade: String' type=kotlin.String origin=null + 3 VAR IR_TEMPORARY_VARIABLE val tmp0_subject: kotlin.String + 4 WHEN type=kotlin.Nothing origin=WHEN +OUTGOING -> BB 1, 5 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +BB 1 +INCOMING <- BB 0 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT +OUTGOING -> BB 2, 6 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +BB 2 +INCOMING <- BB 1 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT +OUTGOING -> BB 3, 7 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +BB 3 +INCOMING <- BB 2 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT +OUTGOING -> BB 4, 8 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +BB 4 +INCOMING <- BB 3 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT +OUTGOING -> BB 9, 10 + CONST Boolean type=kotlin.Boolean value='true' +BB 5 +INCOMING <- BB 0 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CONST String type=kotlin.String value='Excellent' + 2 RETURN type=kotlin.Nothing from='toString(String): String' +OUTGOING -> NONE + Function exit: FUN public fun toString(grade: kotlin.String): kotlin.String +BB 6 +INCOMING <- BB 1 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CONST String type=kotlin.String value='Good' + 2 RETURN type=kotlin.Nothing from='toString(String): String' +OUTGOING -> NONE + Function exit: FUN public fun toString(grade: kotlin.String): kotlin.String +BB 7 +INCOMING <- BB 2 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CONST String type=kotlin.String value='Mediocre' + 2 RETURN type=kotlin.Nothing from='toString(String): String' +OUTGOING -> NONE + Function exit: FUN public fun toString(grade: kotlin.String): kotlin.String +BB 8 +INCOMING <- BB 3 + CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ +CONTENT + 1 CONST String type=kotlin.String value='Fair' + 2 RETURN type=kotlin.Nothing from='toString(String): String' +OUTGOING -> NONE + Function exit: FUN public fun toString(grade: kotlin.String): kotlin.String +BB 9 +INCOMING <- BB 4 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 CONST String type=kotlin.String value='Failure' + 2 RETURN type=kotlin.Nothing from='toString(String): String' +OUTGOING -> NONE + Function exit: FUN public fun toString(grade: kotlin.String): kotlin.String +BB 10 +INCOMING <- BB 4 + CONST Boolean type=kotlin.Boolean value='true' +CONTENT + 1 CONST String type=kotlin.String value='???' + 2 RETURN type=kotlin.Nothing from='toString(String): String' +OUTGOING -> NONE + Function exit: FUN public fun toString(grade: kotlin.String): kotlin.String + +// END FUN: toString + +// END FILE: /whenReturn.kt + diff --git a/compiler/testData/ir/irText/expressions/whenReturn.kt b/compiler/testData/ir/irText/expressions/whenReturn.kt new file mode 100644 index 00000000000..b692e1f2dab --- /dev/null +++ b/compiler/testData/ir/irText/expressions/whenReturn.kt @@ -0,0 +1,10 @@ +fun toString(grade: String): String { + when (grade) { + "A" -> return "Excellent" + "B" -> return "Good" + "C" -> return "Mediocre" + "D" -> return "Fair" + else -> return "Failure" + } + return "???" +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/whenReturn.txt b/compiler/testData/ir/irText/expressions/whenReturn.txt new file mode 100644 index 00000000000..eca3f4385bd --- /dev/null +++ b/compiler/testData/ir/irText/expressions/whenReturn.txt @@ -0,0 +1,37 @@ +FILE /whenReturn.kt + FUN public fun toString(grade: kotlin.String): kotlin.String + BLOCK_BODY + BLOCK type=kotlin.Nothing origin=WHEN + VAR IR_TEMPORARY_VARIABLE val tmp0_subject: kotlin.String + GET_VAR 'value-parameter grade: String' type=kotlin.String origin=null + WHEN type=kotlin.Nothing origin=WHEN + BRANCH + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_subject: String' type=kotlin.String origin=null + arg1: CONST String type=kotlin.String value='A' + then: RETURN type=kotlin.Nothing from='toString(String): String' + CONST String type=kotlin.String value='Excellent' + BRANCH + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_subject: String' type=kotlin.String origin=null + arg1: CONST String type=kotlin.String value='B' + then: RETURN type=kotlin.Nothing from='toString(String): String' + CONST String type=kotlin.String value='Good' + BRANCH + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_subject: String' type=kotlin.String origin=null + arg1: CONST String type=kotlin.String value='C' + then: RETURN type=kotlin.Nothing from='toString(String): String' + CONST String type=kotlin.String value='Mediocre' + BRANCH + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_subject: String' type=kotlin.String origin=null + arg1: CONST String type=kotlin.String value='D' + then: RETURN type=kotlin.Nothing from='toString(String): String' + CONST String type=kotlin.String value='Fair' + BRANCH + if: CONST Boolean type=kotlin.Boolean value='true' + then: RETURN type=kotlin.Nothing from='toString(String): String' + CONST String type=kotlin.String value='Failure' + RETURN type=kotlin.Nothing from='toString(String): String' + CONST String type=kotlin.String value='???' diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java index 704fb54c424..0c46977f6fd 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java @@ -70,4 +70,43 @@ public class IrCfgTestCaseGenerated extends AbstractIrCfgTestCase { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/simpleReturn.kt"); doTest(fileName); } + + @TestMetadata("compiler/testData/ir/irCfg/when") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class When extends AbstractIrCfgTestCase { + public void testAllFilesPresentInWhen() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irCfg/when"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("cascadeIf.kt") + public void testCascadeIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/when/cascadeIf.kt"); + doTest(fileName); + } + + @TestMetadata("emptyWhen.kt") + public void testEmptyWhen() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/when/emptyWhen.kt"); + doTest(fileName); + } + + @TestMetadata("expressionIf.kt") + public void testExpressionIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/when/expressionIf.kt"); + doTest(fileName); + } + + @TestMetadata("ifChain.kt") + public void testIfChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/when/ifChain.kt"); + doTest(fileName); + } + + @TestMetadata("whenReturn.kt") + public void testWhenReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/when/whenReturn.kt"); + doTest(fileName); + } + } } diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 2353efc3814..c771f997f3e 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -658,6 +658,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("whenReturn.kt") + public void testWhenReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/whenReturn.kt"); + doTest(fileName); + } + @TestMetadata("whileDoWhile.kt") public void testWhileDoWhile() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/whileDoWhile.kt");