Skip to content

Commit

Permalink
[K/N][Tests] Fix crashes when casting to an Obj-C class companion
Browse files Browse the repository at this point in the history
  • Loading branch information
edisongz committed Mar 29, 2024
1 parent 757812a commit a110cd6
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ internal abstract class FunctionGenerationContext(
generationState.dependenciesTracker.add(irClass)
if (irClass.isObjCMetaClass()) {
val name = irClass.getExternalObjCMetaClassBinaryName()
val objCClass = getObjCClass(name, isMetaclass = true)
val objCClass = getObjCClass(name)

val getClass = llvm.externalNativeRuntimeFunction(
"object_getClass",
Expand Down Expand Up @@ -1364,8 +1364,7 @@ internal abstract class FunctionGenerationContext(
}
}

private fun getObjCClass(binaryName: String, isMetaclass: Boolean = false) =
load(llvm.int8PtrType, codegen.objCDataGenerator!!.genClassRef(binaryName, isMetaclass).llvm)
private fun getObjCClass(binaryName: String) = load(llvm.int8PtrType, codegen.objCDataGenerator!!.genClassRef(binaryName).llvm)

fun getObjCClassFromNativeRuntime(binaryName: String): LLVMValueRef {
generationState.dependenciesTracker.addNativeRuntime()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
global.pointer
}

fun genClassRef(name: String, isMetaclass: Boolean = false): ConstPointer = classRefs.getOrPut(name) {
// Need to distinguish between _OBJC_CLASS_$_ and _OBJC_METACLASS_$_
val classGlobal = getClassGlobal(name, isMetaclass)
fun genClassRef(name: String): ConstPointer = classRefs.getOrPut(name) {
val classGlobal = getClassGlobal(name, isMetaclass = false)
val global = codegen.staticData.placeGlobal("OBJC_CLASSLIST_REFERENCES_\$_", classGlobal).also {
it.setLinkage(LLVMLinkage.LLVMPrivateLinkage)
it.setSection("__DATA,__objc_classrefs,regular,no_dead_strip")
Expand Down
31 changes: 25 additions & 6 deletions native/native.tests/testData/codegen/cinterop/objc/kt65260.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,37 @@
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import platform.Foundation.*
import platform.darwin.*
import kotlinx.cinterop.internal.*
import kotlin.test.*

fun box(): String {
fun test1() {
try {
// Test: cast to NSObject Metaclass
Any() as NSObject.Companion
// Test: cast to subclass of NSObject Metaclass
Any() as NSString.Companion
Any() as NSArray.Companion
} catch (e: Exception) {
// Cannot access 'TypeCastException': it is internal in Kotlin/Native.
assertTrue(e is ClassCastException)
}
}

fun test2() {
try {
Any() as NSNumber.Companion
} catch (e: Exception) {
assertTrue(e is ClassCastException)
}
}

fun test3() {
assertFalse(Any() is NSObject.Companion)
assertFalse(Any() is NSNumber.Companion)

val nsObjectClass: Any = NSObject
assertFalse(nsObjectClass is NSNumberMeta)
}

fun box(): String {
test1()
test2()
test3()

return "OK"
}

0 comments on commit a110cd6

Please sign in to comment.