Skip to content

Commit 3301541

Browse files
committed
[IRGen] Fix crash in CVW generation for ObjC references
rdar://139664644 The code that differentiates between regular ObjC and native Swift ObjC references could crash when generics were involved. Instead of through the TypeInfo, we are going directly throught the SILType to the type decl, which avoids the crash caused by casting the TypeInfo.
1 parent 1bdffc3 commit 3301541

File tree

2 files changed

+107
-7
lines changed

2 files changed

+107
-7
lines changed

lib/IRGen/TypeLayout.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,14 +1295,14 @@ bool ScalarTypeLayoutEntry::refCountString(IRGenModule &IGM,
12951295
B.addRefCount(LayoutStringBuilder::RefCountingKind::Block, size);
12961296
break;
12971297
case ScalarKind::ObjCReference: {
1298-
auto *classTI = dyn_cast<ClassTypeInfo>(&typeInfo);
1299-
assert(classTI);
1300-
if (!classTI->getClass()->hasClangNode()) {
1301-
B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeSwiftObjC,
1302-
size);
1303-
} else {
1304-
B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size);
1298+
if (auto *classDecl = representative.getClassOrBoundGenericClass()) {
1299+
if (!classDecl->hasClangNode()) {
1300+
B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeSwiftObjC,
1301+
size);
1302+
break;
1303+
}
13051304
}
1305+
B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size);
13061306
break;
13071307
}
13081308
case ScalarKind::ThickFunc:

test/Interpreter/layout_string_witnesses_objc.swift

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,103 @@ func testMultiPayloadBlock() {
190190
}
191191

192192
testMultiPayloadBlock()
193+
194+
class GenericOuterClassNSObject<T: NSObject> {
195+
enum InnerEnum {
196+
case x(T.Type)
197+
case y(T)
198+
}
199+
}
200+
201+
func testNestedGenericEnumNSObject() {
202+
let ptr = UnsafeMutablePointer<GenericOuterClassNSObject<ObjCPrintOnDealloc>.InnerEnum>.allocate(capacity: 1)
203+
204+
// initWithCopy
205+
do {
206+
let x = GenericOuterClassNSObject<ObjCPrintOnDealloc>.InnerEnum.y(ObjCPrintOnDealloc())
207+
testInit(ptr, to: x)
208+
}
209+
210+
// assignWithTake
211+
do {
212+
let y = GenericOuterClassNSObject<ObjCPrintOnDealloc>.InnerEnum.y(ObjCPrintOnDealloc())
213+
214+
// CHECK-NEXT: Before deinit
215+
print("Before deinit")
216+
217+
// CHECK-NEXT: ObjCPrintOnDealloc deinitialized!
218+
testAssign(ptr, from: y)
219+
}
220+
221+
// assignWithCopy
222+
do {
223+
var z = GenericOuterClassNSObject<ObjCPrintOnDealloc>.InnerEnum.y(ObjCPrintOnDealloc())
224+
225+
// CHECK-NEXT: Before deinit
226+
print("Before deinit")
227+
228+
// CHECK-NEXT: ObjCPrintOnDealloc deinitialized!
229+
testAssignCopy(ptr, from: &z)
230+
}
231+
232+
// CHECK-NEXT: Before deinit
233+
print("Before deinit")
234+
235+
// destroy
236+
// CHECK-NEXT: ObjCPrintOnDealloc deinitialized!
237+
testDestroy(ptr)
238+
239+
ptr.deallocate()
240+
}
241+
242+
testNestedGenericEnumNSObject()
243+
244+
class GenericOuterClassSwiftObjC<T: SwiftObjC> {
245+
enum InnerEnum {
246+
case x(T.Type)
247+
case y(T)
248+
}
249+
}
250+
251+
func testNestedGenericEnumSwiftObjC() {
252+
let ptr = UnsafeMutablePointer<GenericOuterClassSwiftObjC<SwiftObjC>.InnerEnum>.allocate(capacity: 1)
253+
254+
// initWithCopy
255+
do {
256+
let x = GenericOuterClassSwiftObjC<SwiftObjC>.InnerEnum.y(SwiftObjC())
257+
testInit(ptr, to: x)
258+
}
259+
260+
// assignWithTake
261+
do {
262+
let y = GenericOuterClassSwiftObjC<SwiftObjC>.InnerEnum.y(SwiftObjC())
263+
264+
// CHECK-NEXT: Before deinit
265+
print("Before deinit")
266+
267+
// CHECK-NEXT: SwiftObjC deinitialized!
268+
testAssign(ptr, from: y)
269+
}
270+
271+
// assignWithCopy
272+
do {
273+
var z = GenericOuterClassSwiftObjC<SwiftObjC>.InnerEnum.y(SwiftObjC())
274+
275+
// CHECK-NEXT: Before deinit
276+
print("Before deinit")
277+
278+
// CHECK-NEXT: SwiftObjC deinitialized!
279+
testAssignCopy(ptr, from: &z)
280+
}
281+
282+
// CHECK-NEXT: Before deinit
283+
print("Before deinit")
284+
285+
// destroy
286+
// CHECK-NEXT: SwiftObjC deinitialized!
287+
testDestroy(ptr)
288+
289+
ptr.deallocate()
290+
}
291+
292+
testNestedGenericEnumSwiftObjC()

0 commit comments

Comments
 (0)