diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt index 1f4ea51a300..a75efbb0240 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.backend.konan +import org.jetbrains.kotlin.backend.konan.descriptors.findPackage import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull import org.jetbrains.kotlin.backend.konan.descriptors.getStringValue import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull @@ -34,6 +35,7 @@ internal val externalObjCClassFqName = interopPackageName.child(Name.identifier( private val objCMethodFqName = interopPackageName.child(Name.identifier("ObjCMethod")) private val objCConstructorFqName = FqName("kotlinx.cinterop.ObjCConstructor") private val objCFactoryFqName = interopPackageName.child(Name.identifier("ObjCFactory")) +private val objcnamesForwardDeclarationsPackageName = Name.identifier("objcnames") @Deprecated("Use IR version rather than descriptor version") fun ClassDescriptor.isObjCClass(): Boolean = @@ -61,6 +63,9 @@ fun IrClass.isExternalObjCClass(): Boolean = this.isObjCClass() && it.descriptor.annotations.hasAnnotation(externalObjCClassFqName) } +fun ClassDescriptor.isObjCForwardDeclaration(): Boolean = + this.findPackage().fqName.startsWith(objcnamesForwardDeclarationsPackageName) + fun ClassDescriptor.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().any { it.fqNameSafe == objCClassFqName } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index dfc374712ad..a27d725ca6c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -800,9 +800,9 @@ internal class ObjCExportTranslatorImpl( private tailrec fun mapObjCObjectReferenceTypeIgnoringNullability(descriptor: ClassDescriptor): ObjCNonNullReferenceType { // TODO: more precise types can be used. - if (descriptor.isObjCMetaClass()) return ObjCIdType + if (descriptor.isObjCMetaClass()) return ObjCMetaClassType - if (descriptor.isExternalObjCClass()) { + if (descriptor.isExternalObjCClass() || descriptor.isObjCForwardDeclaration()) { return if (descriptor.isInterface) { val name = descriptor.name.asString().removeSuffix("Protocol") generator?.referenceProtocol(name) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt index 5218a2e4d6f..57ea9ad5525 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt @@ -89,6 +89,10 @@ class ObjCBlockPointerType( }) } +object ObjCMetaClassType : ObjCNonNullReferenceType() { + override fun render(attrsAndName: String): String = "Class".withAttrsAndName(attrsAndName) +} + class ObjCPrimitiveType( val cName: String ) : ObjCType() { diff --git a/backend.native/tests/framework/values/expectedLazy.h b/backend.native/tests/framework/values/expectedLazy.h index 1e94cb20c0c..21615d539fc 100644 --- a/backend.native/tests/framework/values/expectedLazy.h +++ b/backend.native/tests/framework/values/expectedLazy.h @@ -600,6 +600,8 @@ __attribute__((swift_name("ValuesKt"))) + (void (^)(void))asNothingBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asNothingBlock(block:)"))); + (void (^ _Nullable)(void))getNullBlock __attribute__((swift_name("getNullBlock()"))); + (BOOL)isBlockNullBlock:(void (^ _Nullable)(void))block __attribute__((swift_name("isBlockNull(block:)"))); ++ (void)takeForwardDeclaredClassObj:(ForwardDeclaredClass *)obj __attribute__((swift_name("takeForwardDeclaredClass(obj:)"))); ++ (void)takeForwardDeclaredProtocolObj:(id)obj __attribute__((swift_name("takeForwardDeclaredProtocol(obj:)"))); @property (class, readonly) double dbl __attribute__((swift_name("dbl"))); @property (class, readonly) float flt __attribute__((swift_name("flt"))); @property (class, readonly) int32_t integer __attribute__((swift_name("integer"))); diff --git a/backend.native/tests/framework/values/values.kt b/backend.native/tests/framework/values/values.kt index 2c529046af9..99ae5bc146e 100644 --- a/backend.native/tests/framework/values/values.kt +++ b/backend.native/tests/framework/values/values.kt @@ -423,3 +423,6 @@ object UnitBlockCoercionImpl : UnitBlockCoercion<() -> Unit> { } abstract class MyAbstractList : List + +fun takeForwardDeclaredClass(obj: objcnames.classes.ForwardDeclaredClass) {} +fun takeForwardDeclaredProtocol(obj: objcnames.protocols.ForwardDeclaredProtocol) {}