From 4570872bfd2d22561ad81aff0cbe775a46e870bd Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 23 Apr 2015 18:09:27 +0300 Subject: [PATCH] Postfix expression code generation fixed as per KT-7561. A set of tests for KT-7561 on codegen side, including exotic inc() functions(). #KT-7561 Fixed. --- .../kotlin/codegen/ExpressionCodegen.java | 6 +- .../box/increment/assignPlusOnSmartCast.kt | 8 ++ .../postfixIncrementDoubleSmartCast.kt | 10 ++ .../box/increment/postfixIncrementOnClass.kt | 12 +++ .../postfixIncrementOnClassSmartCast.kt | 11 +++ .../postfixIncrementOnShortSmartCast.kt | 8 ++ .../increment/postfixIncrementOnSmartCast.kt | 9 ++ .../increment/postfixNotnullClassIncrement.kt | 12 +++ .../postfixNullableClassIncrement.kt | 11 +++ .../box/increment/postfixNullableIncrement.kt | 10 ++ .../box/increment/prefixIncrementOnClass.kt | 12 +++ .../prefixIncrementOnClassSmartCast.kt | 11 +++ .../increment/prefixIncrementOnSmartCast.kt | 8 ++ .../increment/prefixNotnullClassIncrement.kt | 12 +++ .../increment/prefixNullableClassIncrement.kt | 11 +++ .../box/increment/prefixNullableIncrement.kt | 10 ++ .../BlackBoxCodegenTestGenerated.java | 99 +++++++++++++++++++ 17 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/increment/assignPlusOnSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/postfixIncrementDoubleSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/postfixIncrementOnClass.kt create mode 100644 compiler/testData/codegen/box/increment/postfixIncrementOnClassSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/postfixIncrementOnShortSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/postfixIncrementOnSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/postfixNotnullClassIncrement.kt create mode 100644 compiler/testData/codegen/box/increment/postfixNullableClassIncrement.kt create mode 100644 compiler/testData/codegen/box/increment/postfixNullableIncrement.kt create mode 100644 compiler/testData/codegen/box/increment/prefixIncrementOnClass.kt create mode 100644 compiler/testData/codegen/box/increment/prefixIncrementOnClassSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/prefixIncrementOnSmartCast.kt create mode 100644 compiler/testData/codegen/box/increment/prefixNotnullClassIncrement.kt create mode 100644 compiler/testData/codegen/box/increment/prefixNullableClassIncrement.kt create mode 100644 compiler/testData/codegen/box/increment/prefixNullableIncrement.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index de832feb6be..f7cad9a7b76 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -3239,7 +3239,9 @@ public class ExpressionCodegen extends JetVisitor implem final boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { JetExpression operand = expression.getBaseExpression(); - if (operand instanceof JetReferenceExpression && asmResultType == Type.INT_TYPE) { + // Optimization for j = i++, when j and i are Int without any smart cast: we just work with primitive int + if (operand instanceof JetReferenceExpression && asmResultType == Type.INT_TYPE && + bindingContext.get(BindingContext.SMARTCAST, operand) == null) { int index = indexOfLocal((JetReferenceExpression) operand); if (index >= 0) { return StackValue.postIncrement(index, increment); @@ -3247,7 +3249,7 @@ public class ExpressionCodegen extends JetVisitor implem } } - return StackValue.operation(asmResultType, new Function1() { + return StackValue.operation(asmBaseType, new Function1() { @Override public Unit invoke(InstructionAdapter v) { StackValue value = gen(expression.getBaseExpression()); diff --git a/compiler/testData/codegen/box/increment/assignPlusOnSmartCast.kt b/compiler/testData/codegen/box/increment/assignPlusOnSmartCast.kt new file mode 100644 index 00000000000..f3b84e034bd --- /dev/null +++ b/compiler/testData/codegen/box/increment/assignPlusOnSmartCast.kt @@ -0,0 +1,8 @@ +public fun box() : String { + var i : Int? + i = 10 + // assignPlus on a smart cast should work + i += 1 + + return if (11 == i) "OK" else "fail i = $i" +} diff --git a/compiler/testData/codegen/box/increment/postfixIncrementDoubleSmartCast.kt b/compiler/testData/codegen/box/increment/postfixIncrementDoubleSmartCast.kt new file mode 100644 index 00000000000..738a31c9697 --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixIncrementDoubleSmartCast.kt @@ -0,0 +1,10 @@ +public fun box() : String { + var i : Int? + i = 10 + // We have "double" smart cast here: + // first on i and second on i++ + // Back-end should NOT think that both i and j are Int + val j: Int = i++ + + return if (j == 10 && 11 == i) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/postfixIncrementOnClass.kt b/compiler/testData/codegen/box/increment/postfixIncrementOnClass.kt new file mode 100644 index 00000000000..08cb9da0b6e --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixIncrementOnClass.kt @@ -0,0 +1,12 @@ +trait Base +class Derived: Base +class Another: Base +fun Base.inc(): Derived { return Derived() } + +public fun box() : String { + var i : Base + i = Another() + val j = i++ + + return if (j is Another && i is Derived) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/postfixIncrementOnClassSmartCast.kt b/compiler/testData/codegen/box/increment/postfixIncrementOnClassSmartCast.kt new file mode 100644 index 00000000000..cb0a9dff50a --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixIncrementOnClassSmartCast.kt @@ -0,0 +1,11 @@ +open class Base +class Derived: Base() +fun Derived.inc(): Derived { return Derived() } + +public fun box() : String { + var i : Base + i = Derived() + val j = i++ + + return if (j is Derived && i is Derived) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/postfixIncrementOnShortSmartCast.kt b/compiler/testData/codegen/box/increment/postfixIncrementOnShortSmartCast.kt new file mode 100644 index 00000000000..0dec61d0503 --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixIncrementOnShortSmartCast.kt @@ -0,0 +1,8 @@ +public fun box() : String { + var i : Short? + i = 10 + // Postfix increment on a smart casted short should work + val j = i++ + + return if (j!!.toInt() == 10 && i!!.toInt() == 11) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/postfixIncrementOnSmartCast.kt b/compiler/testData/codegen/box/increment/postfixIncrementOnSmartCast.kt new file mode 100644 index 00000000000..3da28a2d6e6 --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixIncrementOnSmartCast.kt @@ -0,0 +1,9 @@ +public fun box() : String { + var i : Int? + i = 10 + // Postfix increment on a smart cast should work + // Specific: i.inc() type is Int but i and j types are both Int? + val j = i++ + + return if (j == 10 && 11 == i) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/postfixNotnullClassIncrement.kt b/compiler/testData/codegen/box/increment/postfixNotnullClassIncrement.kt new file mode 100644 index 00000000000..29be526adf1 --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixNotnullClassIncrement.kt @@ -0,0 +1,12 @@ +class MyClass + +// In principle it is not correct, MyClass? is not a subtype of MyClass +fun MyClass.inc(): MyClass? = null + +public fun box() : String { + var i : MyClass? + i = MyClass() + val j = i++ + + return if (j is MyClass && null == i) "OK" else "fail i = $i j = $j" +} diff --git a/compiler/testData/codegen/box/increment/postfixNullableClassIncrement.kt b/compiler/testData/codegen/box/increment/postfixNullableClassIncrement.kt new file mode 100644 index 00000000000..56fc4da33e1 --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixNullableClassIncrement.kt @@ -0,0 +1,11 @@ +class MyClass + +fun MyClass?.inc(): MyClass? = null + +public fun box() : String { + var i : MyClass? + i = MyClass() + val j = i++ + + return if (j is MyClass && null == i) "OK" else "fail i = $i j = $j" +} diff --git a/compiler/testData/codegen/box/increment/postfixNullableIncrement.kt b/compiler/testData/codegen/box/increment/postfixNullableIncrement.kt new file mode 100644 index 00000000000..9e5783719d2 --- /dev/null +++ b/compiler/testData/codegen/box/increment/postfixNullableIncrement.kt @@ -0,0 +1,10 @@ +fun Int?.inc(): Int? = this + +fun init(): Int? { return 10 } + +public fun box() : String { + var i : Int? = init() + val j = i++ + + return if (j == 10 && 10 == i) "OK" else "fail i = $i j = $j" +} diff --git a/compiler/testData/codegen/box/increment/prefixIncrementOnClass.kt b/compiler/testData/codegen/box/increment/prefixIncrementOnClass.kt new file mode 100644 index 00000000000..72fd9154dbb --- /dev/null +++ b/compiler/testData/codegen/box/increment/prefixIncrementOnClass.kt @@ -0,0 +1,12 @@ +trait Base +class Derived: Base +class Another: Base +fun Base.inc(): Derived { return Derived() } + +public fun box() : String { + var i : Base + i = Another() + val j = ++i + + return if (j is Derived && i is Derived) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/prefixIncrementOnClassSmartCast.kt b/compiler/testData/codegen/box/increment/prefixIncrementOnClassSmartCast.kt new file mode 100644 index 00000000000..624155ce7af --- /dev/null +++ b/compiler/testData/codegen/box/increment/prefixIncrementOnClassSmartCast.kt @@ -0,0 +1,11 @@ +open class Base +class Derived: Base() +fun Derived.inc(): Derived { return Derived() } + +public fun box() : String { + var i : Base + i = Derived() + val j = ++i + + return if (j is Derived && i is Derived) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/prefixIncrementOnSmartCast.kt b/compiler/testData/codegen/box/increment/prefixIncrementOnSmartCast.kt new file mode 100644 index 00000000000..80e48f4f78b --- /dev/null +++ b/compiler/testData/codegen/box/increment/prefixIncrementOnSmartCast.kt @@ -0,0 +1,8 @@ +public fun box() : String { + var i : Int? + i = 10 + // Prefix increment on a smart cast should work + val j = ++i + + return if (j == 11 && 11 == i) "OK" else "fail j = $j i = $i" +} diff --git a/compiler/testData/codegen/box/increment/prefixNotnullClassIncrement.kt b/compiler/testData/codegen/box/increment/prefixNotnullClassIncrement.kt new file mode 100644 index 00000000000..0f71c9d6177 --- /dev/null +++ b/compiler/testData/codegen/box/increment/prefixNotnullClassIncrement.kt @@ -0,0 +1,12 @@ +class MyClass + +// In principle it is not correct, MyClass? is not a subtype of MyClass +fun MyClass.inc(): MyClass? = null + +public fun box() : String { + var i : MyClass? + i = MyClass() + val j = ++i + + return if (j == null && null == i) "OK" else "fail i = $i j = $j" +} diff --git a/compiler/testData/codegen/box/increment/prefixNullableClassIncrement.kt b/compiler/testData/codegen/box/increment/prefixNullableClassIncrement.kt new file mode 100644 index 00000000000..d51bd20a364 --- /dev/null +++ b/compiler/testData/codegen/box/increment/prefixNullableClassIncrement.kt @@ -0,0 +1,11 @@ +class MyClass + +fun MyClass?.inc(): MyClass? = null + +public fun box() : String { + var i : MyClass? + i = MyClass() + val j = ++i + + return if (j == null && null == i) "OK" else "fail i = $i j = $j" +} diff --git a/compiler/testData/codegen/box/increment/prefixNullableIncrement.kt b/compiler/testData/codegen/box/increment/prefixNullableIncrement.kt new file mode 100644 index 00000000000..49034d27036 --- /dev/null +++ b/compiler/testData/codegen/box/increment/prefixNullableIncrement.kt @@ -0,0 +1,10 @@ +fun Int?.inc(): Int? = this + +fun init(): Int? { return 10 } + +public fun box() : String { + var i : Int? = init() + val j = ++i + + return if (j == 10 && 10 == i) "OK" else "fail i = $i j = $j" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index b4510fcfec8..57092536b34 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -4049,6 +4049,105 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/increment") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Increment extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInIncrement() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/increment"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("assignPlusOnSmartCast.kt") + public void testAssignPlusOnSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/assignPlusOnSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("postfixIncrementDoubleSmartCast.kt") + public void testPostfixIncrementDoubleSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixIncrementDoubleSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("postfixIncrementOnClass.kt") + public void testPostfixIncrementOnClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixIncrementOnClass.kt"); + doTest(fileName); + } + + @TestMetadata("postfixIncrementOnClassSmartCast.kt") + public void testPostfixIncrementOnClassSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixIncrementOnClassSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("postfixIncrementOnShortSmartCast.kt") + public void testPostfixIncrementOnShortSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixIncrementOnShortSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("postfixIncrementOnSmartCast.kt") + public void testPostfixIncrementOnSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixIncrementOnSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("postfixNotnullClassIncrement.kt") + public void testPostfixNotnullClassIncrement() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixNotnullClassIncrement.kt"); + doTest(fileName); + } + + @TestMetadata("postfixNullableClassIncrement.kt") + public void testPostfixNullableClassIncrement() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixNullableClassIncrement.kt"); + doTest(fileName); + } + + @TestMetadata("postfixNullableIncrement.kt") + public void testPostfixNullableIncrement() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/postfixNullableIncrement.kt"); + doTest(fileName); + } + + @TestMetadata("prefixIncrementOnClass.kt") + public void testPrefixIncrementOnClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/prefixIncrementOnClass.kt"); + doTest(fileName); + } + + @TestMetadata("prefixIncrementOnClassSmartCast.kt") + public void testPrefixIncrementOnClassSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/prefixIncrementOnClassSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("prefixIncrementOnSmartCast.kt") + public void testPrefixIncrementOnSmartCast() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/prefixIncrementOnSmartCast.kt"); + doTest(fileName); + } + + @TestMetadata("prefixNotnullClassIncrement.kt") + public void testPrefixNotnullClassIncrement() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/prefixNotnullClassIncrement.kt"); + doTest(fileName); + } + + @TestMetadata("prefixNullableClassIncrement.kt") + public void testPrefixNullableClassIncrement() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/prefixNullableClassIncrement.kt"); + doTest(fileName); + } + + @TestMetadata("prefixNullableIncrement.kt") + public void testPrefixNullableIncrement() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/prefixNullableIncrement.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/innerNested") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)