File: objc_extensions.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (243 lines) | stat: -rw-r--r-- 8,760 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// 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 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() {
  }
}

/*
 * 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()
  }
}