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 ccc6f7f7871..1a09affd0be 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 @@ -45,7 +45,7 @@ class FunctionGenerator(val function: IrFunction) { if (data) { builder.add(declaration) } - val result = declaration.body?.process() + val result = declaration.body?.process() ?: if (data) declaration else null if (result != null && !result.isNothing()) { builder.jump(exit, from = result) } @@ -63,7 +63,7 @@ class FunctionGenerator(val function: IrFunction) { private fun IrElement?.isNothing() = this is IrExpression && KotlinBuiltIns.isNothing(type) override fun visitBlockBody(body: IrBlockBody, data: Boolean): IrElement? { - return body.process() ?: body + return body.process() } override fun visitBlock(expression: IrBlock, data: Boolean): IrElement? { diff --git a/compiler/testData/ir/irCfg/expressionFun.kt b/compiler/testData/ir/irCfg/expressionFun.kt new file mode 100644 index 00000000000..4ce098c4774 --- /dev/null +++ b/compiler/testData/ir/irCfg/expressionFun.kt @@ -0,0 +1 @@ +fun foo(arg: Int) = arg \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/expressionFun.txt b/compiler/testData/ir/irCfg/expressionFun.txt new file mode 100644 index 00000000000..f7f80b28a8d --- /dev/null +++ b/compiler/testData/ir/irCfg/expressionFun.txt @@ -0,0 +1,14 @@ +// FILE: /expressionFun.kt +// FUN: foo +BB 0 +CONTENT + 1 FUN public fun foo(arg: kotlin.Int): kotlin.Int + 2 GET_VAR 'value-parameter arg: Int' type=kotlin.Int origin=null + 3 RETURN type=kotlin.Nothing from='foo(Int): Int' +OUTGOING -> NONE + Function exit: FUN public fun foo(arg: kotlin.Int): kotlin.Int + +// END FUN: foo + +// END FILE: /expressionFun.kt + diff --git a/compiler/testData/ir/irCfg/expressionUnit.kt b/compiler/testData/ir/irCfg/expressionUnit.kt new file mode 100644 index 00000000000..44ce3c5bd0a --- /dev/null +++ b/compiler/testData/ir/irCfg/expressionUnit.kt @@ -0,0 +1 @@ +fun foo() = Unit \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/expressionUnit.txt b/compiler/testData/ir/irCfg/expressionUnit.txt new file mode 100644 index 00000000000..4f4b004993b --- /dev/null +++ b/compiler/testData/ir/irCfg/expressionUnit.txt @@ -0,0 +1,14 @@ +// FILE: /expressionUnit.kt +// FUN: foo +BB 0 +CONTENT + 1 FUN public fun foo(): kotlin.Unit + 2 GET_OBJECT 'Unit' type=kotlin.Unit + 3 RETURN type=kotlin.Nothing from='foo(): Unit' +OUTGOING -> NONE + Function exit: FUN public fun foo(): kotlin.Unit + +// END FUN: foo + +// END FILE: /expressionUnit.kt + diff --git a/compiler/testData/ir/irCfg/returnUnit.kt b/compiler/testData/ir/irCfg/returnUnit.kt new file mode 100644 index 00000000000..e3b44cd6a51 --- /dev/null +++ b/compiler/testData/ir/irCfg/returnUnit.kt @@ -0,0 +1,3 @@ +fun foo() { + return Unit +} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/returnUnit.txt b/compiler/testData/ir/irCfg/returnUnit.txt new file mode 100644 index 00000000000..7e2f46aef2d --- /dev/null +++ b/compiler/testData/ir/irCfg/returnUnit.txt @@ -0,0 +1,14 @@ +// FILE: /returnUnit.kt +// FUN: foo +BB 0 +CONTENT + 1 FUN public fun foo(): kotlin.Unit + 2 GET_OBJECT 'Unit' type=kotlin.Unit + 3 RETURN type=kotlin.Nothing from='foo(): Unit' +OUTGOING -> NONE + Function exit: FUN public fun foo(): kotlin.Unit + +// END FUN: foo + +// END FILE: /returnUnit.kt + diff --git a/compiler/testData/ir/irCfg/sequentialFun.kt b/compiler/testData/ir/irCfg/sequentialFun.kt new file mode 100644 index 00000000000..940d511eeb7 --- /dev/null +++ b/compiler/testData/ir/irCfg/sequentialFun.kt @@ -0,0 +1,4 @@ +fun foo(arg: Int): Int { + val dbl = arg * 2 + return dbl +} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/sequentialFun.txt b/compiler/testData/ir/irCfg/sequentialFun.txt new file mode 100644 index 00000000000..b26a71f2edd --- /dev/null +++ b/compiler/testData/ir/irCfg/sequentialFun.txt @@ -0,0 +1,16 @@ +// FILE: /sequentialFun.kt +// FUN: foo +BB 0 +CONTENT + 1 FUN public fun foo(arg: kotlin.Int): kotlin.Int + 2 CALL 'times(Int): Int' type=kotlin.Int origin=MUL + 3 VAR val dbl: kotlin.Int + 4 GET_VAR 'dbl: Int' type=kotlin.Int origin=null + 5 RETURN type=kotlin.Nothing from='foo(Int): Int' +OUTGOING -> NONE + Function exit: FUN public fun foo(arg: kotlin.Int): kotlin.Int + +// END FUN: foo + +// END FILE: /sequentialFun.kt + diff --git a/compiler/testData/ir/irCfg/simpleFun.kt b/compiler/testData/ir/irCfg/simpleFun.kt new file mode 100644 index 00000000000..59281f1b0bb --- /dev/null +++ b/compiler/testData/ir/irCfg/simpleFun.kt @@ -0,0 +1 @@ +fun foo() {} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/simpleFun.txt b/compiler/testData/ir/irCfg/simpleFun.txt new file mode 100644 index 00000000000..540fccda2ea --- /dev/null +++ b/compiler/testData/ir/irCfg/simpleFun.txt @@ -0,0 +1,12 @@ +// FILE: /simpleFun.kt +// FUN: foo +BB 0 +CONTENT + 1 FUN public fun foo(): kotlin.Unit +OUTGOING -> NONE + Function exit: FUN public fun foo(): kotlin.Unit + +// END FUN: foo + +// END FILE: /simpleFun.kt + diff --git a/compiler/testData/ir/irCfg/simpleReturn.kt b/compiler/testData/ir/irCfg/simpleReturn.kt new file mode 100644 index 00000000000..0083baaa06a --- /dev/null +++ b/compiler/testData/ir/irCfg/simpleReturn.kt @@ -0,0 +1,3 @@ +fun foo() { + return +} \ No newline at end of file diff --git a/compiler/testData/ir/irCfg/simpleReturn.txt b/compiler/testData/ir/irCfg/simpleReturn.txt new file mode 100644 index 00000000000..42b933f7828 --- /dev/null +++ b/compiler/testData/ir/irCfg/simpleReturn.txt @@ -0,0 +1,14 @@ +// FILE: /simpleReturn.kt +// FUN: foo +BB 0 +CONTENT + 1 FUN public fun foo(): kotlin.Unit + 2 GET_OBJECT 'Unit' type=kotlin.Unit + 3 RETURN type=kotlin.Nothing from='foo(): Unit' +OUTGOING -> NONE + Function exit: FUN public fun foo(): kotlin.Unit + +// END FUN: foo + +// END FILE: /simpleReturn.kt + diff --git a/compiler/tests/compiler-tests.iml b/compiler/tests/compiler-tests.iml index f26b8a69ced..58d10f71102 100644 --- a/compiler/tests/compiler-tests.iml +++ b/compiler/tests/compiler-tests.iml @@ -71,5 +71,6 @@ + \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrCfgTestCase.kt b/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrCfgTestCase.kt new file mode 100644 index 00000000000..14cdf0649aa --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/ir/AbstractIrCfgTestCase.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2016 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.kotlin.ir + +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.name +import org.jetbrains.kotlin.ir2cfg.generators.FunctionGenerator +import org.jetbrains.kotlin.ir2cfg.util.dump +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +abstract class AbstractIrCfgTestCase : AbstractIrGeneratorTestCase() { + + private val IrFunction.name: String get() = this.descriptor.name.asString() + + private fun IrFile.cfgDump(): String { + val builder = StringBuilder() + for (declaration in this.declarations) { + if (declaration is IrFunction) { + builder.appendln("// FUN: ${declaration.name}") + val cfg = FunctionGenerator(declaration).generate() + builder.appendln(cfg.dump()) + builder.appendln("// END FUN: ${declaration.name}") + } + } + return builder.toString() + } + + private fun IrModuleFragment.cfgDump(): String { + val builder = StringBuilder() + for (file in this.files) { + builder.appendln("// FILE: ${file.name}") + builder.appendln(file.cfgDump()) + builder.appendln("// END FILE: ${file.name}") + builder.appendln() + } + return builder.toString() + } + + override fun doTest(wholeFile: File, testFiles: List) { + val irModule = generateIrModule(false) + val irModuleDump = irModule.cfgDump() + val expectedPath = wholeFile.canonicalPath.replace(".kt", ".txt") + val expectedFile = File(expectedPath) + KotlinTestUtils.assertEqualsToFile(expectedFile, irModuleDump) + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java new file mode 100644 index 00000000000..704fb54c424 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrCfgTestCaseGenerated.java @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2016 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.kotlin.ir; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/ir/irCfg") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class IrCfgTestCaseGenerated extends AbstractIrCfgTestCase { + public void testAllFilesPresentInIrCfg() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irCfg"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("expressionFun.kt") + public void testExpressionFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/expressionFun.kt"); + doTest(fileName); + } + + @TestMetadata("expressionUnit.kt") + public void testExpressionUnit() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/expressionUnit.kt"); + doTest(fileName); + } + + @TestMetadata("returnUnit.kt") + public void testReturnUnit() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/returnUnit.kt"); + doTest(fileName); + } + + @TestMetadata("sequentialFun.kt") + public void testSequentialFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/sequentialFun.kt"); + doTest(fileName); + } + + @TestMetadata("simpleFun.kt") + public void testSimpleFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/simpleFun.kt"); + doTest(fileName); + } + + @TestMetadata("simpleReturn.kt") + public void testSimpleReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irCfg/simpleReturn.kt"); + doTest(fileName); + } +} diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index b258150fa7e..2c28f9e42cd 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -122,10 +122,7 @@ import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest import org.jetbrains.kotlin.idea.stubs.AbstractStubBuilderTest import org.jetbrains.kotlin.integration.AbstractAntTaskTest -import org.jetbrains.kotlin.ir.AbstractClosureAnnotatorTestCase -import org.jetbrains.kotlin.ir.AbstractIrTextTestCase -import org.jetbrains.kotlin.ir.AbstractPsi2IrBoxTestCase -import org.jetbrains.kotlin.ir.AbstractPsi2IrDiagnosticsTest +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterForWebDemoTest import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterMultiFileTest import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest @@ -252,6 +249,10 @@ fun main(args: Array) { model("ir/irText") } + testClass() { + model("ir/irCfg") + } + // Uncomment the following lines to generate IR generator tests based on existing compiler tests. // // testClass() {