Skip to content

Commit 85f9e2e

Browse files
committed
Fix CCE in generated code that happens when comparing boxed chars
The problem was that when obtaining char from the wrapper, codegen used int as expected type that led to a ClassCastException: java.lang.Character cannot be cast to java.lang.Number The solution is using coercion to chars, it's still correct, because of implicit widening coercion in JVM from C to I #KT-15105 Fixed
1 parent 378acbf commit 85f9e2e

File tree

7 files changed

+41
-1
lines changed

7 files changed

+41
-1
lines changed

compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,7 @@ public static Type comparisonOperandType(Type left, Type right) {
770770
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
771771
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
772772
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
773+
if (left == Type.CHAR_TYPE || right == Type.CHAR_TYPE) return Type.CHAR_TYPE;
773774
return Type.INT_TYPE;
774775
}
775776

compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/CompareTo.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
2525
class CompareTo : IntrinsicMethod() {
2626
private fun genInvoke(type: Type?, v: InstructionAdapter) {
2727
when (type) {
28-
Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
28+
Type.INT_TYPE, Type.CHAR_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
2929
Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
3030
Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
3131
Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
fun <T> id(x: T) = x
2+
3+
fun box(): String {
4+
if (id('a') > id('b')) return "fail 1"
5+
if (id('a') >= id('b')) return "fail 2"
6+
if (id('b') < id('a')) return "fail 3"
7+
if (id('b') <= id('a')) return "fail 4"
8+
9+
val x = id('a').compareTo('b')
10+
if (x != -1) return "fail 5"
11+
12+
val y = id('b').compareTo('a')
13+
if (y != 1) return "fail 6"
14+
15+
return "OK"
16+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@kotlin.Metadata
2+
public final class CompareBoxedCharsKt {
3+
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
4+
public final static method id(p0: java.lang.Object): java.lang.Object
5+
}

compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,12 @@ public void testCallNullable() throws Exception {
785785
doTest(fileName);
786786
}
787787

788+
@TestMetadata("compareBoxedChars.kt")
789+
public void testCompareBoxedChars() throws Exception {
790+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareBoxedChars.kt");
791+
doTest(fileName);
792+
}
793+
788794
@TestMetadata("compareWithBoxedDouble.kt")
789795
public void testCompareWithBoxedDouble() throws Exception {
790796
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");

compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,12 @@ public void testCallNullable() throws Exception {
785785
doTest(fileName);
786786
}
787787

788+
@TestMetadata("compareBoxedChars.kt")
789+
public void testCompareBoxedChars() throws Exception {
790+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareBoxedChars.kt");
791+
doTest(fileName);
792+
}
793+
788794
@TestMetadata("compareWithBoxedDouble.kt")
789795
public void testCompareWithBoxedDouble() throws Exception {
790796
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");

js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,12 @@ public void testCallNullable() throws Exception {
977977
doTest(fileName);
978978
}
979979

980+
@TestMetadata("compareBoxedChars.kt")
981+
public void testCompareBoxedChars() throws Exception {
982+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareBoxedChars.kt");
983+
doTest(fileName);
984+
}
985+
980986
@TestMetadata("compareWithBoxedDouble.kt")
981987
public void testCompareWithBoxedDouble() throws Exception {
982988
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");

0 commit comments

Comments
 (0)