Skip to content

Commit ffc26fb

Browse files
committed
SILGen: Allocating entry points for @objc dynamic inits should use alloc_ref_dynamic
If the initializer witnesses a protocol requirement, the protocol witness thunk references the allocating entry point directly, since it has no vtable entry. For this reason we must use alloc_ref_dynamic and not alloc_ref to ensure the right type of instance is allocated. Fixes <rdar://problem/49560721>, <https://bugs.swift.org/browse/SR-10285>.
1 parent fb8bd3a commit ffc26fb

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

lib/SILGen/SILGenConstructor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,9 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
530530
// Allocate the 'self' value.
531531
bool useObjCAllocation = usesObjCAllocator(selfClassDecl);
532532

533-
if (ctor->hasClangNode() || ctor->isConvenienceInit()) {
533+
if (ctor->hasClangNode() ||
534+
ctor->isObjCDynamic() ||
535+
ctor->isConvenienceInit()) {
534536
assert(ctor->hasClangNode() || ctor->isObjC());
535537
// For an allocator thunk synthesized for an @objc convenience initializer
536538
// or imported Objective-C init method, allocate using the metatype.

test/Interpreter/objc_metatypes.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
// REQUIRES: objc_interop
4+
5+
import StdlibUnittest
6+
import Foundation
7+
8+
protocol Horse {
9+
init()
10+
}
11+
12+
class Pony : NSObject, Horse {
13+
override required init() {}
14+
}
15+
16+
class ChincoteaguePony : Pony {}
17+
18+
var ObjCMetatypesTest = TestSuite("ObjCMetatypes")
19+
20+
ObjCMetatypesTest.test("ClassInit") {
21+
let metatype: Pony.Type = ChincoteaguePony.self
22+
let instance = metatype.init()
23+
expectEqual(type(of: instance), ChincoteaguePony.self)
24+
}
25+
26+
ObjCMetatypesTest.test("ProtocolInit") {
27+
let metatype: Horse.Type = ChincoteaguePony.self
28+
let instance = metatype.init()
29+
expectEqual(type(of: instance), ChincoteaguePony.self)
30+
}
31+
32+
runAllTests()

test/SILGen/objc_dynamic_init.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ class Gadget: NSObject, Hoozit {
1717
}
1818
}
1919

20+
// CHECK-LABEL: sil hidden [ossa] @$s17objc_dynamic_init6GadgetCACycfC : $@convention(method) (@thick Gadget.Type) -> @owned Gadget
21+
// CHECK: [[OBJC_METATYPE:%.*]] = thick_to_objc_metatype %0 : $@thick Gadget.Type to $@objc_metatype Gadget.Type
22+
// CHECK: [[SELF:%.*]] = alloc_ref_dynamic [objc] %1 : $@objc_metatype Gadget.Type, $Gadget
23+
// CHECK: [[INIT:%.*]] = function_ref @$s17objc_dynamic_init6GadgetCACycfcTD : $@convention(method) (@owned Gadget) -> @owned Gadget
24+
// CHECK: [[NEW_SELF:%.*]] = apply [[INIT]]([[SELF]]) : $@convention(method) (@owned Gadget) -> @owned Gadget
25+
// CHECK: return [[NEW_SELF]]
26+
27+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17objc_dynamic_init6GadgetCAA6HoozitA2aDPxycfCTW : $@convention(witness_method: Hoozit) (@thick Gadget.Type) -> @out Gadget {
28+
// CHECK: function_ref @$s17objc_dynamic_init6GadgetCACycfC
29+
2030
class Gizmo: Gadget, Wotsit {
2131
required init() {
2232
super.init()
@@ -35,8 +45,7 @@ final class Bobamathing: Thingamabob {
3545
}
3646
}
3747

38-
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s{{.*}}GadgetC{{.*}}CTW
39-
// CHECK: function_ref @{{.*}}Gadget{{.*}}fC :
48+
4049

4150
// CHECK-LABEL: sil_vtable Gadget {
4251
// CHECK-NOT: #Gadget.init!allocator.1

0 commit comments

Comments
 (0)