From b0edec8449cc568d5520dd21f113b80c0ce204a0 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 7 Jul 2016 16:23:42 +0300 Subject: [PATCH] KT-13023 Char operations throw ClassCastException for boxed Chars Char is not a Number, so we can't use the same coercion strategy for Char members, since it doesn't work for boxed Chars. --- .../kotlin/codegen/intrinsics/BinaryOp.kt | 25 +++++++++++++------ .../codegen/box/primitiveTypes/kt13023.kt | 20 +++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/codegen/box/primitiveTypes/kt13023.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/BinaryOp.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/BinaryOp.kt index d3bf2457ea7..bdc985ea3c1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/BinaryOp.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/BinaryOp.kt @@ -32,14 +32,25 @@ class BinaryOp(private val opcode: Int) : IntrinsicMethod() { override fun toCallable(method: CallableMethod): Callable { val returnType = method.returnType assert(method.getValueParameters().size == 1) - val operandType = numberFunctionOperandType(returnType) - val paramType = if (shift()) Type.INT_TYPE else operandType - return createBinaryIntrinsicCallable(returnType, paramType, operandType) { - v -> - v.visitInsn(returnType.getOpcode(opcode)) - if (operandType != returnType) - StackValue.coerce(operandType, returnType, v) + val arg0Type: Type + val arg1Type: Type + val intermediateResultType: Type + + if (method.owner != Type.CHAR_TYPE) { + intermediateResultType = numberFunctionOperandType(returnType) + arg0Type = intermediateResultType + arg1Type = if (shift()) Type.INT_TYPE else arg0Type + } + else { + arg0Type = Type.CHAR_TYPE + arg1Type = method.getValueParameters()[0].asmType + intermediateResultType = numberFunctionOperandType(returnType) + } + + return createBinaryIntrinsicCallable(returnType, arg1Type, arg0Type) { v -> + v.visitInsn(returnType.getOpcode(opcode)) + StackValue.coerce(intermediateResultType, returnType, v) } } } diff --git a/compiler/testData/codegen/box/primitiveTypes/kt13023.kt b/compiler/testData/codegen/box/primitiveTypes/kt13023.kt new file mode 100644 index 00000000000..602654d9563 --- /dev/null +++ b/compiler/testData/codegen/box/primitiveTypes/kt13023.kt @@ -0,0 +1,20 @@ +// WITH_RUNTIME + +import kotlin.test.assertEquals + +fun box(): String { + val b = 'b' + val c = 'c' + assertEquals('c', b + 1) + assertEquals('a', b - 1) + assertEquals(1, c - b) + + val list = listOf('b', 'a') + assertEquals('c', list[0] + 1) + assertEquals('a', list[0] - 1) + assertEquals(1, list[0] - list[1]) + assertEquals(1, list[0] - 'a') + assertEquals(1, 'b' - list[1]) + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b9aba8e7d8c..c842ac1134e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -9766,6 +9766,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kt13023.kt") + public void testKt13023() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/primitiveTypes/kt13023.kt"); + doTest(fileName); + } + @TestMetadata("kt1508.kt") public void testKt1508() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/primitiveTypes/kt1508.kt");