mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Clang emits ObjC strings into special sections
d5e7c27d53/clang/lib/CodeGen/CGObjCMac.cpp (L4056-L4072)
As far as I can tell from `CGObjCMac.cpp`:
* types go into `__objc_methtype`
* class, category, and protocol names go into `__objc_classname`
* method names, property names, and property types go into
`__objc_methname`
See also https://github.com/swiftlang/swift/pull/84236.
262 lines
9.1 KiB
Swift
262 lines
9.1 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %build-irgen-test-overlays
|
|
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -disable-objc-attr-requires-foundation-module -emit-module %S/Inputs/objc_extension_base.swift -o %t
|
|
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir -g | %FileCheck %s
|
|
|
|
// REQUIRES: CPU=x86_64 || CPU=arm64
|
|
// REQUIRES: objc_interop
|
|
|
|
import Foundation
|
|
import gizmo
|
|
import objc_extension_base
|
|
|
|
// Check that metadata for nested enums added in extensions to imported classes
|
|
// gets emitted concretely.
|
|
|
|
// CHECK: [[CATEGORY_NAME:@.*]] = private unnamed_addr constant [16 x i8] c"objc_extensions\00"
|
|
// CHECK: [[METHOD_TYPE:@.*]] = private unnamed_addr constant [8 x i8] c"v16@0:8\00"
|
|
|
|
// CHECK-LABEL: @"_CATEGORY_PROTOCOLS_Gizmo_$_objc_extensions" = internal constant
|
|
// CHECK-SAME: i64 1,
|
|
// CHECK-SAME: @_PROTOCOL__TtP15objc_extensions11NewProtocol_
|
|
|
|
// CHECK-LABEL: @"_CATEGORY_Gizmo_$_objc_extensions" = internal constant
|
|
// CHECK-SAME: ptr [[CATEGORY_NAME]],
|
|
// CHECK-SAME: ptr @"OBJC_CLASS_$_Gizmo",
|
|
// CHECK-SAME: @"_CATEGORY_INSTANCE_METHODS_Gizmo_$_objc_extensions",
|
|
// CHECK-SAME: @"_CATEGORY_CLASS_METHODS_Gizmo_$_objc_extensions",
|
|
// CHECK-SAME: @"_CATEGORY_PROTOCOLS_Gizmo_$_objc_extensions",
|
|
// CHECK-SAME: ptr null
|
|
// CHECK-SAME: }, section "__DATA, {{.*}}", align 8
|
|
|
|
@objc protocol NewProtocol {
|
|
func brandNewInstanceMethod()
|
|
}
|
|
|
|
extension NSObject {
|
|
@objc func someMethod() -> String { return "Hello" }
|
|
}
|
|
|
|
extension Gizmo: NewProtocol {
|
|
@objc func brandNewInstanceMethod() {
|
|
}
|
|
|
|
@objc class func brandNewClassMethod() {
|
|
}
|
|
|
|
// Overrides an instance method of NSObject
|
|
override func someMethod() -> String {
|
|
return super.someMethod()
|
|
}
|
|
|
|
// Overrides a class method of NSObject
|
|
@objc override class func hasOverride() {}
|
|
}
|
|
|
|
/*
|
|
* Make sure that two extensions of the same ObjC class in the same module can
|
|
* coexist by having different category names.
|
|
*/
|
|
|
|
// CHECK: [[CATEGORY_NAME_1:@.*]] = private unnamed_addr constant [17 x i8] c"objc_extensions1\00"
|
|
|
|
// CHECK: @"_CATEGORY_Gizmo_$_objc_extensions1" = internal constant
|
|
// CHECK: ptr [[CATEGORY_NAME_1]],
|
|
// CHECK: ptr @"OBJC_CLASS_$_Gizmo",
|
|
// CHECK: {{.*}} @"_CATEGORY_INSTANCE_METHODS_Gizmo_$_objc_extensions1",
|
|
// CHECK: {{.*}} @"_CATEGORY_CLASS_METHODS_Gizmo_$_objc_extensions1",
|
|
// CHECK: ptr null,
|
|
// CHECK: ptr null
|
|
// CHECK: }, section "__DATA, {{.*}}", align 8
|
|
|
|
extension Gizmo {
|
|
@objc func brandSpankingNewInstanceMethod() {
|
|
}
|
|
|
|
@objc class func brandSpankingNewClassMethod() {
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Make sure that extensions of an ObjC class with `@objc(CustomName)` get the
|
|
* indicated category name.
|
|
*/
|
|
// CHECK: @"_CATEGORY_Gizmo_$_WidgetMaker" = internal constant
|
|
// CHECK: ptr @.str.11.WidgetMaker,
|
|
// CHECK: ptr @"OBJC_CLASS_$_Gizmo",
|
|
// CHECK: {{.*}} @"_CATEGORY_INSTANCE_METHODS_Gizmo_$_WidgetMaker",
|
|
// CHECK: {{.*}} ptr null,
|
|
// CHECK: ptr null,
|
|
// CHECK: ptr null
|
|
// CHECK: }, section "__DATA, {{.*}}", align 8
|
|
|
|
@objc(WidgetMaker) extension Gizmo {
|
|
func makeWidget() {
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check that extensions of Swift subclasses of ObjC objects get categories.
|
|
*/
|
|
|
|
class Hoozit : NSObject {
|
|
}
|
|
|
|
// CHECK-LABEL: @"_CATEGORY_INSTANCE_METHODS__TtC15objc_extensions6Hoozit_$_objc_extensions" = internal constant
|
|
// CHECK: i32 24,
|
|
// CHECK: i32 1,
|
|
// CHECK: [1 x { ptr, ptr, ptr }] [{ ptr, ptr, ptr } {
|
|
// CHECK: ptr @"\01L_selector_data(blibble)",
|
|
// CHECK: ptr [[STR:@[^,]*]],
|
|
// CHECK: ptr @"$s15objc_extensions6HoozitC7blibbleyyFTo"
|
|
// CHECK: }]
|
|
// CHECK: }, section "__DATA, {{.*}}", align 8
|
|
|
|
// CHECK-LABEL: @"_CATEGORY_CLASS_METHODS__TtC15objc_extensions6Hoozit_$_objc_extensions" = internal constant
|
|
// CHECK: i32 24,
|
|
// CHECK: i32 1,
|
|
// CHECK: [1 x { ptr, ptr, ptr }] [{ ptr, ptr, ptr } {
|
|
// CHECK: ptr @"\01L_selector_data(blobble)",
|
|
// CHECK: ptr [[STR]],
|
|
// CHECK: ptr @"$s15objc_extensions6HoozitC7blobbleyyFZTo"
|
|
// CHECK: }]
|
|
// CHECK: }, section "__DATA, {{.*}}", align 8
|
|
|
|
// CHECK-LABEL: @"_CATEGORY__TtC15objc_extensions6Hoozit_$_objc_extensions" = internal constant
|
|
// CHECK: ptr [[CATEGORY_NAME]],
|
|
// CHECK: ptr {{.*}} @"$s15objc_extensions6HoozitCMf",
|
|
// CHECK: {{.*}} @"_CATEGORY_INSTANCE_METHODS__TtC15objc_extensions6Hoozit_$_objc_extensions",
|
|
// CHECK: {{.*}} @"_CATEGORY_CLASS_METHODS__TtC15objc_extensions6Hoozit_$_objc_extensions",
|
|
// CHECK: ptr null,
|
|
// CHECK: ptr null
|
|
// CHECK: }, section "__DATA, {{.*}}", align 8
|
|
|
|
extension Hoozit {
|
|
@objc func blibble() { }
|
|
@objc class func blobble() { }
|
|
}
|
|
|
|
class SwiftOnly { }
|
|
|
|
// CHECK-LABEL: @"_CATEGORY_INSTANCE_METHODS__TtC15objc_extensions9SwiftOnly_$_objc_extensions" = internal constant
|
|
// CHECK: i32 24,
|
|
// CHECK: i32 1,
|
|
// CHECK: [1 x { ptr, ptr, ptr }] [{ ptr, ptr, ptr } {
|
|
// CHECK: ptr @"\01L_selector_data(wibble)",
|
|
// CHECK: ptr [[STR]],
|
|
// CHECK: ptr @"$s15objc_extensions9SwiftOnlyC6wibbleyyFTo"
|
|
// CHECK: }] }, section "__DATA, {{.*}}", align 8
|
|
extension SwiftOnly {
|
|
@objc func wibble() { }
|
|
}
|
|
|
|
class Wotsit: Hoozit {}
|
|
|
|
extension Hoozit {
|
|
@objc func overriddenByExtensionInSubclass() {}
|
|
}
|
|
|
|
extension Wotsit {
|
|
@objc override func overriddenByExtensionInSubclass() {}
|
|
}
|
|
|
|
extension NSObject {
|
|
private enum SomeEnum { case X }
|
|
|
|
@objc public func needMetadataOfSomeEnum() {
|
|
print(NSObject.SomeEnum.X)
|
|
}
|
|
|
|
@objc class func hasOverride() {}
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @"_CATEGORY__TtCC15objc_extensions5Outer5Inner_$_objc_extensions" = internal constant
|
|
// CHECK-SAME: ptr [[CATEGORY_NAME]],
|
|
// CHECK-SAME: @"_CATEGORY_INSTANCE_METHODS__TtCC15objc_extensions5Outer5Inner_$_objc_extensions",
|
|
// CHECK-SAME: ptr null
|
|
// CHECK-SAME: }, section "__DATA, {{.*}}", align 8
|
|
|
|
class Outer : NSObject {
|
|
class Inner : NSObject {}
|
|
}
|
|
|
|
extension Outer.Inner {
|
|
@objc func innerExtensionMethod() {}
|
|
}
|
|
|
|
|
|
/*
|
|
* Make sure that @NSManaged causes a category to be generated.
|
|
*/
|
|
class NSDogcow : NSObject {}
|
|
|
|
// CHECK: [[NAME:@.*]] = private unnamed_addr constant [5 x i8] c"woof\00"
|
|
// CHECK: [[ATTR:@.*]] = private unnamed_addr constant [7 x i8] c"Tq,N,D\00"
|
|
// CHECK: @"_CATEGORY_PROPERTIES__TtC15objc_extensions8NSDogcow_$_objc_extensions" = internal constant {{.*}} [[NAME]], {{.*}} [[ATTR]] {{.*}}, section "__DATA, {{.*}}", align 8
|
|
extension NSDogcow {
|
|
@NSManaged var woof: Int
|
|
}
|
|
|
|
// CHECK: @"$sSo8NSObjectC15objc_extensionsE8SomeEnum33_1F05E59585E0BB585FCA206FBFF1A92DLLOSQACMc" =
|
|
|
|
class SwiftSubGizmo : SwiftBaseGizmo {
|
|
|
|
// Don't crash on this call. Emit an objC method call to super.
|
|
//
|
|
// CHECK-LABEL: define {{.*}} @"$s15objc_extensions13SwiftSubGizmoC4frobyyF"
|
|
// CHECK: $s15objc_extensions13SwiftSubGizmoCMa
|
|
// CHECK: objc_msgSendSuper2
|
|
// CHECK: ret
|
|
public override func frob() {
|
|
super.frob()
|
|
}
|
|
}
|
|
|
|
@inline(never) func opaquePrint(_ value: Any) { print(value) }
|
|
|
|
/*
|
|
* Check that we can extend ObjC generics and use both the type and metatype of
|
|
* the generic parameter. Specifically, we're checking that we emit debug info
|
|
* if we look up the existential bound, and that we derive the argument to
|
|
* `opaquePrint(_:)` from the actual parameter, not just the fixed metadata.
|
|
*/
|
|
extension FungingArray {
|
|
// CHECK-LABEL: define {{.*}} @"$sSo12FungingArrayC15objc_extensionsEyAByxGxcfC"
|
|
// CHECK-SAME: (ptr %0, ptr swiftself %1)
|
|
// CHECK: @__swift_instantiateConcreteTypeFromMangledName{{.*}}@"$sSo9NSFunging_pMD"{{.*}}!dbg
|
|
|
|
// CHECK-LABEL: define {{.*}} @"$sSo12FungingArrayC15objc_extensionsEyAByxGxcfc"
|
|
// CHECK-SAME: (ptr %0, ptr swiftself %1)
|
|
// CHECK: [[ALLOCA:%[^, =]+]] = alloca %Any, align 8
|
|
// CHECK: @__swift_instantiateConcreteTypeFromMangledName{{.*}}@"$sSo9NSFunging_pMD"{{.*}}!dbg
|
|
// CHECK: {{%[^, =]+}} = getelementptr inbounds{{.*}} %Any, ptr [[ALLOCA]], i32 0, i32 0
|
|
// CHECK: [[ANYBUF:%[^, =]+]] = getelementptr inbounds{{.*}} %Any, ptr [[ALLOCA]], i32 0, i32 0
|
|
// CHECK: [[BUFPTR:%[^, =]+]] = {{.*}} [[ANYBUF]]
|
|
// CHECK: store {{.*}} %0, {{.*}} [[BUFPTR]]
|
|
// CHECK: call swiftcc void @"$s15objc_extensions11opaquePrintyyypF"(ptr {{.*}} [[ALLOCA]])
|
|
@objc public convenience init(_ elem: Element) {
|
|
opaquePrint(elem)
|
|
self.init()
|
|
}
|
|
|
|
// CHECK-LABEL: define {{.*}} @"$sSo12FungingArrayC15objc_extensionsE7pinningAByxGxm_tcfC"
|
|
// CHECK-SAME: (ptr %0, ptr swiftself %1)
|
|
// CHECK: @__swift_instantiateConcreteTypeFromMangledName{{.*}}@"$sSo9NSFunging_pMD"{{.*}}!dbg
|
|
|
|
// CHECK-LABEL: define {{.*}} @"$sSo12FungingArrayC15objc_extensionsE7pinningAByxGxm_tcfc"
|
|
// CHECK-SAME: (ptr %0, ptr swiftself %1)
|
|
// CHECK: [[ALLOCA:%[^, =]+]] = alloca %Any, align 8
|
|
// CHECK: @__swift_instantiateConcreteTypeFromMangledName{{.*}}@"$sSo9NSFunging_pMD"{{.*}}!dbg
|
|
// CHECK: [[OBJC_CLASS:%[^, =]+]] = call ptr @swift_getObjCClassFromMetadata(ptr %0)
|
|
// CHECK: {{%[^, =]+}} = getelementptr inbounds{{.*}} %Any, ptr [[ALLOCA]], i32 0, i32 0
|
|
// CHECK: [[ANYBUF:%[^, =]+]] = getelementptr inbounds{{.*}} %Any, ptr [[ALLOCA]], i32 0, i32 0
|
|
// CHECK: [[BUFPTR:%[^, =]+]] = {{.*}} [[ANYBUF]]
|
|
// CHECK: store {{.*}} [[OBJC_CLASS]], {{.*}} [[BUFPTR]]
|
|
// CHECK: call swiftcc void @"$s15objc_extensions11opaquePrintyyypF"(ptr {{.*}} [[ALLOCA]])
|
|
@objc public convenience init(pinning: Element.Type) {
|
|
opaquePrint(pinning as AnyObject)
|
|
self.init()
|
|
}
|
|
}
|