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
This commit is contained in:
@@ -770,6 +770,7 @@ public class AsmUtil {
|
|||||||
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
|
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
|
||||||
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
|
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
|
||||||
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
|
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
|
||||||
|
if (left == Type.CHAR_TYPE || right == Type.CHAR_TYPE) return Type.CHAR_TYPE;
|
||||||
return Type.INT_TYPE;
|
return Type.INT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|||||||
class CompareTo : IntrinsicMethod() {
|
class CompareTo : IntrinsicMethod() {
|
||||||
private fun genInvoke(type: Type?, v: InstructionAdapter) {
|
private fun genInvoke(type: Type?, v: InstructionAdapter) {
|
||||||
when (type) {
|
when (type) {
|
||||||
Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
|
Type.INT_TYPE, Type.CHAR_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
|
||||||
Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
|
Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
|
||||||
Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
|
Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
|
||||||
Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false)
|
Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
fun <T> id(x: T) = x
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (id('a') > id('b')) return "fail 1"
|
||||||
|
if (id('a') >= id('b')) return "fail 2"
|
||||||
|
if (id('b') < id('a')) return "fail 3"
|
||||||
|
if (id('b') <= id('a')) return "fail 4"
|
||||||
|
|
||||||
|
val x = id('a').compareTo('b')
|
||||||
|
if (x != -1) return "fail 5"
|
||||||
|
|
||||||
|
val y = id('b').compareTo('a')
|
||||||
|
if (y != 1) return "fail 6"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class CompareBoxedCharsKt {
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
public final static method id(p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
+6
@@ -785,6 +785,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compareBoxedChars.kt")
|
||||||
|
public void testCompareBoxedChars() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareBoxedChars.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compareWithBoxedDouble.kt")
|
@TestMetadata("compareWithBoxedDouble.kt")
|
||||||
public void testCompareWithBoxedDouble() throws Exception {
|
public void testCompareWithBoxedDouble() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");
|
||||||
|
|||||||
@@ -785,6 +785,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compareBoxedChars.kt")
|
||||||
|
public void testCompareBoxedChars() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareBoxedChars.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compareWithBoxedDouble.kt")
|
@TestMetadata("compareWithBoxedDouble.kt")
|
||||||
public void testCompareWithBoxedDouble() throws Exception {
|
public void testCompareWithBoxedDouble() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");
|
||||||
|
|||||||
@@ -977,6 +977,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compareBoxedChars.kt")
|
||||||
|
public void testCompareBoxedChars() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareBoxedChars.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compareWithBoxedDouble.kt")
|
@TestMetadata("compareWithBoxedDouble.kt")
|
||||||
public void testCompareWithBoxedDouble() throws Exception {
|
public void testCompareWithBoxedDouble() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user