mirror of
https://github.com/apple/swift.git
synced 2026-10-22 19:15:50 +02:00
ClangImporter imports C 'Class' as AnyClass, but declaring a C-interop function that takes/returns it via @c or @_extern(c) was rejected. Support it across three layers: Sema: make AnyClass (an ExistentialMetatypeType of AnyObject) representable in ForeignLanguage::C, gated on ObjC interop since 'Class' is an ObjC runtime type. Reuse getObjCObjectRepresentable so C and ObjC agree on the kind. SILGen: a @c/@_extern(c) function is emitted directly as its C entry point (no separate native thunk), so bridge the metatype at that boundary in place: objc_to_thick_metatype on a 'Class' parameter in the prolog, and thick_to_objc_metatype on an AnyClass result in the epilog. Both are no-ops unless the native and foreign SIL types differ. PrintAsClang: keep the @c declaration in the plain-C section and emit '#include <objc/objc.h>' there when a @c decl uses 'Class', so the generated header stays usable from plain C.
53 lines
2.6 KiB
Swift
53 lines
2.6 KiB
Swift
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s
|
|
|
|
// REQUIRES: objc_interop
|
|
|
|
import Foundation
|
|
|
|
@objc
|
|
class ObjCClass: NSObject { }
|
|
|
|
@c(objcClassReturn) func objcClassReturn() -> ObjCClass { fatalError() }
|
|
// expected-error @-1 {{global function cannot be marked '@c' because its result type cannot be represented in C}}
|
|
// expected-note @-2 {{classes cannot be represented in C}}
|
|
|
|
@c(objcClassParams) func objcClassParams(a: ObjCClass, b: ObjCClass) { }
|
|
// expected-error @-1 {{global function cannot be marked '@c' because the type of the parameter 1 cannot be represented in C}}
|
|
// expected-error @-2 {{global function cannot be marked '@c' because the type of the parameter 2 cannot be represented in C}}
|
|
// expected-note @-3 2 {{classes cannot be represented in C}}
|
|
|
|
@objc
|
|
protocol ObjCProtocol {}
|
|
|
|
@c(objcProtocol) func objcProtocol(a: ObjCProtocol) { }
|
|
// expected-error @-1 {{global function cannot be marked '@c' because the type of the parameter cannot be represented in C}}
|
|
// expected-note @-2 {{protocols cannot be represented in C}}
|
|
|
|
@objc
|
|
enum ObjCEnum: Int { case A, B }
|
|
@c(objcEnumUseInCDecl) func objcEnumUseInCDecl(a: ObjCEnum) { }
|
|
// expected-error @-1 {{global function cannot be marked '@c' because the type of the parameter cannot be represented in C}}
|
|
// expected-note @-2 {{Swift enums not marked '@c' cannot be represented in C}}
|
|
|
|
/// Objective-C accepts @c enums.
|
|
@c(CEnum)
|
|
enum CEnum: Int { case A, B }
|
|
@_cdecl("cdeclEnumUseInObjc") func cdeclEnumUseInObjc(a: CEnum) { }
|
|
|
|
enum SwiftEnum { case A, B }
|
|
@_cdecl("swiftEnumUseInObjc") func swiftEnumUseInObjc(a: SwiftEnum) { }
|
|
// expected-error @-1 {{global function cannot be marked '@_cdecl' because the type of the parameter cannot be represented in Objective-C}}
|
|
// expected-note @-2 {{Swift enums not marked '@c' or '@objc' cannot be represented in Objective-C}}
|
|
|
|
/// AnyClass maps to the C runtime type Class.
|
|
@c(anyClassParam) func anyClassParam(a: AnyClass) { }
|
|
@c(anyClassReturn) func anyClassReturn() -> AnyClass { fatalError() }
|
|
|
|
/// The object form (AnyObject) and protocol-qualified class metatypes (P.Type,
|
|
/// i.e. C's Class<P>) are still rejected: only bare AnyClass is representable.
|
|
@c(anyObjectParam) func anyObjectParam(a: AnyObject) { }
|
|
// expected-error @-1 {{global function cannot be marked '@c' because the type of the parameter cannot be represented in C}}
|
|
// expected-note @-2 {{protocols cannot be represented in C}}
|
|
@c(objcProtoMetatype) func objcProtoMetatype(a: ObjCProtocol.Type) { }
|
|
// expected-error @-1 {{global function cannot be marked '@c' because the type of the parameter cannot be represented in C}}
|