Skip to content

Commit 910ae43

Browse files
authored
Merge pull request #8830 from slavapestov/irgen-clang-type-subclass-existentials
IRGen Clang type lowering for subclass existentials
2 parents 6a94bdc + 7e0e5f1 commit 910ae43

File tree

2 files changed

+54
-37
lines changed

2 files changed

+54
-37
lines changed

lib/IRGen/GenClangType.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -599,27 +599,39 @@ clang::CanQualType GenClangType::visitSILBlockStorageType(CanSILBlockStorageType
599599

600600
clang::CanQualType GenClangType::visitProtocolCompositionType(
601601
CanProtocolCompositionType type) {
602+
auto &clangCtx = getClangASTContext();
603+
602604
// FIXME. Eventually, this will have its own helper routine.
603605
SmallVector<const clang::ObjCProtocolDecl *, 4> Protocols;
604606
auto layout = type.getExistentialLayout();
605-
assert(layout.requiresClass && "Cannot represent opaque existential in Clang");
606-
assert(!layout.superclass && "Subclass existentials not supported here yet");
607+
assert(layout.isObjC() && "Cannot represent opaque existential in Clang");
608+
609+
auto superclassTy = clangCtx.ObjCBuiltinIdTy;
610+
if (layout.superclass) {
611+
superclassTy = clangCtx.getCanonicalType(
612+
cast<clang::ObjCObjectPointerType>(
613+
Converter.convert(IGM, CanType(layout.superclass)))
614+
->getPointeeType());
615+
}
616+
607617
for (Type t : layout.getProtocols()) {
608618
auto opt = cast<clang::ObjCObjectPointerType>(
609619
Converter.convert(IGM, CanType(t)));
610620
for (auto p : opt->quals())
611621
Protocols.push_back(p);
612622
}
613623

614-
auto &clangCtx = getClangASTContext();
615624
if (Protocols.empty())
616-
return getClangIdType(clangCtx);
625+
return superclassTy;
626+
617627
// id<protocol-list>
618-
clang::ObjCProtocolDecl **ProtoQuals = new(clangCtx) clang::ObjCProtocolDecl*[Protocols.size()];
619-
memcpy(ProtoQuals, Protocols.data(), sizeof(clang::ObjCProtocolDecl*)*Protocols.size());
620-
auto clangType = clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy,
621-
ProtoQuals,
622-
Protocols.size());
628+
clang::ObjCProtocolDecl **ProtoQuals =
629+
new(clangCtx) clang::ObjCProtocolDecl*[Protocols.size()];
630+
memcpy(ProtoQuals, Protocols.data(),
631+
sizeof(clang::ObjCProtocolDecl*)*Protocols.size());
632+
auto clangType = clangCtx.getObjCObjectType(superclassTy,
633+
ProtoQuals,
634+
Protocols.size());
623635
auto ptrTy = clangCtx.getObjCObjectPointerType(clangType);
624636
return clangCtx.getCanonicalType(ptrTy);
625637
}

test/IRGen/objc_type_encoding.swift

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: %build-irgen-test-overlays
3-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) %s -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s -check-prefix=CHECK-%target-os
3+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) %s -emit-ir -disable-objc-attr-requires-foundation-module -enable-experimental-subclass-existentials | %FileCheck %s -check-prefix=CHECK-%target-os
44

55
// REQUIRES: CPU=x86_64
66
// REQUIRES: objc_interop
@@ -41,9 +41,9 @@ import gizmo
4141

4242
@objc func testOptionalPrimitives()
4343
-> OpaquePointer? { return nil }
44-
// CHECK-macosx: private unnamed_addr constant [9 x i8] c"^v16@0:8\00"
45-
// CHECK-ios: private unnamed_addr constant [9 x i8] c"^v16@0:8\00"
46-
// CHECK-tvos: private unnamed_addr constant [9 x i8] c"^v16@0:8\00"
44+
// CHECK-macosx: private unnamed_addr constant [9 x i8] c"^v16@0:8\00"
45+
// CHECK-ios: private unnamed_addr constant [9 x i8] c"^v16@0:8\00"
46+
// CHECK-tvos: private unnamed_addr constant [9 x i8] c"^v16@0:8\00"
4747

4848
@objc func testCSignedTypes(_ a: CSignedChar, b: CShort, c: CInt, d: CLong, e: CLongLong) {}
4949
// CHECK-macosx: private unnamed_addr constant [23 x i8] c"v44@0:8c16s20i24q28q36\00"
@@ -71,68 +71,69 @@ import gizmo
7171
// CHECK-tvos: private unnamed_addr constant [20 x i8] c"v36@0:8c16s20i24q28\00"
7272

7373
@objc class func getSelf() -> Methods.Type { return self }
74-
// These strings are required for another purpose and so are tested above.
74+
// These strings are required for another purpose and so are tested above.
7575

7676
@objc func getDynamicSelf() -> Self { return self }
77-
// CHECK-macosx: private unnamed_addr constant [8 x i8] c"@16@0:8\00"
78-
// CHECK-ios: private unnamed_addr constant [8 x i8] c"@16@0:8\00"
79-
// CHECK-tvos: private unnamed_addr constant [8 x i8] c"@16@0:8\00"
77+
// CHECK-macosx: private unnamed_addr constant [8 x i8] c"@16@0:8\00"
78+
// CHECK-ios: private unnamed_addr constant [8 x i8] c"@16@0:8\00"
79+
// CHECK-tvos: private unnamed_addr constant [8 x i8] c"@16@0:8\00"
8080

81-
func testId(_ s: AnyObject) -> AnyObject { return self }
81+
@objc func testId(_ s: AnyObject) -> AnyObject { return self }
8282
// CHECK-macosx: private unnamed_addr constant [11 x i8] c"@24@0:8@16\00"
8383
// CHECK-ios: private unnamed_addr constant [11 x i8] c"@24@0:8@16\00"
8484
// CHECK-tvos: private unnamed_addr constant [11 x i8] c"@24@0:8@16\00"
8585

86-
@objc func comp1(_ a: P1 & P2, b: P1 & P2 & P3) -> P1 & P2 { return a }
86+
@objc func comp1(_ a: P1 & P2, b: P1 & P2 & P3) -> P1 & P2 { return a }
8787
// CHECK-macosx: private unnamed_addr constant [14 x i8] c"@32@0:8@16@24\00"
8888
// CHECK-ios: private unnamed_addr constant [14 x i8] c"@32@0:8@16@24\00"
8989
// CHECK-tvos: private unnamed_addr constant [14 x i8] c"@32@0:8@16@24\00"
9090

91-
@objc func returnsBool(_ b : Bool) -> Bool { return b }
91+
@objc func returnsBool(_ b : Bool) -> Bool { return b }
9292
// CHECK-macosx: private unnamed_addr constant [11 x i8] c"c20@0:8c16\00"
9393
// CHECK-ios: private unnamed_addr constant [11 x i8] c"B20@0:8B16\00"
9494
// CHECK-tvos: private unnamed_addr constant [11 x i8] c"B20@0:8B16\00"
9595

96-
@objc func comp1(_ a: Methods, b: Methods, c: Methods) -> Methods { return a }
96+
@objc func comp1(_ a: Methods, b: Methods, c: Methods) -> Methods { return a }
9797
// CHECK-macosx: private unnamed_addr constant [17 x i8] c"@40@0:8@16@24@32\00"
9898
// CHECK-ios: private unnamed_addr constant [17 x i8] c"@40@0:8@16@24@32\00"
9999
// CHECK-tvos: private unnamed_addr constant [17 x i8] c"@40@0:8@16@24@32\00"
100100

101-
@objc func passSelector(_ aSelector : Selector) {}
101+
@objc func passSelector(_ aSelector : Selector) {}
102102
// CHECK-macosx: private unnamed_addr constant [11 x i8] c"v24@0:8:16\00"
103103
// CHECK-ios: private unnamed_addr constant [11 x i8] c"v24@0:8:16\00"
104104
// CHECK-tvos: private unnamed_addr constant [11 x i8] c"v24@0:8:16\00"
105105

106-
@objc func copyUnsafeMutablePointer(_ p: UnsafeMutablePointer<Int32>) -> UnsafeMutablePointer<Int32> { return p }
106+
@objc func copyUnsafeMutablePointer(_ p: UnsafeMutablePointer<Int32>) -> UnsafeMutablePointer<Int32> { return p }
107107
// CHECK-macosx: private unnamed_addr constant [13 x i8] c"^i24@0:8^i16\00"
108108
// CHECK-ios: private unnamed_addr constant [13 x i8] c"^i24@0:8^i16\00"
109109
// CHECK-tvos: private unnamed_addr constant [13 x i8] c"^i24@0:8^i16\00"
110110

111-
@objc func copyUnsafeMutablePointerInt(_ p: UnsafeMutablePointer<Int>) -> UnsafeMutablePointer<Int> { return p }
111+
@objc func copyUnsafeMutablePointerInt(_ p: UnsafeMutablePointer<Int>) -> UnsafeMutablePointer<Int> { return p }
112112
// CHECK-macosx: private unnamed_addr constant [13 x i8] c"^q24@0:8^q16\00"
113113
// CHECK-ios: private unnamed_addr constant [13 x i8] c"^q24@0:8^q16\00"
114114
// CHECK-tvos: private unnamed_addr constant [13 x i8] c"^q24@0:8^q16\00"
115115

116-
func testArchetype(_ work: P3) {
117-
}
116+
@objc func testArchetype(_ work: P3) {
117+
}
118118
// CHECK-macosx: private unnamed_addr constant [11 x i8] c"v24@0:8@16\00"
119119
// CHECK-ios: private unnamed_addr constant [11 x i8] c"v24@0:8@16\00"
120120
// CHECK-tvos: private unnamed_addr constant [11 x i8] c"v24@0:8@16\00"
121121

122-
@objc func foo(_ x: (Int) -> Int) -> Int {
123-
return 1
124-
}
122+
@objc func foo(_ x: (Int) -> Int) -> Int {
123+
return 1
124+
}
125125
// CHECK-macosx: private unnamed_addr constant [12 x i8] c"q24@0:8@?16\00"
126126
// CHECK-ios: private unnamed_addr constant [12 x i8] c"q24@0:8@?16\00"
127127
// CHECK-tvos: private unnamed_addr constant [12 x i8] c"q24@0:8@?16\00"
128128

129-
@objc func returnNSRadixedOptions() -> NSRadixedOptions {
129+
@objc func returnNSRadixedOptions() -> NSRadixedOptions {
130130
return .octal
131131
}
132132
// CHECK-macosx: [[ENUMENCODING:@.*]] = private unnamed_addr constant [8 x i8] c"i16@0:8\00"
133133
// CHECK-ios: [[ENUMENCODING:@.*]] = private unnamed_addr constant [8 x i8] c"i16@0:8\00"
134134
// CHECK-tvos: [[ENUMENCODING:@.*]] = private unnamed_addr constant [8 x i8] c"i16@0:8\00"
135-
@objc func returnChoseNSRadixedOptions(_ choice: NSRadixedOptions) -> NSRadixedOptions {
135+
136+
@objc func returnChoseNSRadixedOptions(_ choice: NSRadixedOptions) -> NSRadixedOptions {
136137
switch choice {
137138
case .octal: return .hex
138139
case .hex: return .octal
@@ -142,7 +143,7 @@ func testArchetype(_ work: P3) {
142143
// CHECK-ios: private unnamed_addr constant [11 x i8] c"i20@0:8i16\00"
143144
// CHECK-tvos: private unnamed_addr constant [11 x i8] c"i20@0:8i16\00"
144145

145-
@objc func getRawEnumInGizmo() -> RawEnumInGizmo {
146+
@objc func getRawEnumInGizmo() -> RawEnumInGizmo {
146147
return InGizmoTwo
147148
}
148149
// CHECK-macosx: { i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"\01L_selector_data(getRawEnumInGizmo)", i64 0, i64 0),
@@ -160,19 +161,23 @@ func testArchetype(_ work: P3) {
160161

161162
@objc protocol MyProtocol {
162163
func myMethod2(_ arg : NSRuncing & NSFunging)
163-
func readWithAuthorization(_ authData : Gizmo, reply : (NSView, NSSpoon) -> Void)
164-
func doSomething(_ context: MyCustomObject)
164+
func readWithAuthorization(_ authData : Gizmo, reply : (NSView, NSSpoon) -> Void)
165+
func doSomething(_ context: MyCustomObject)
166+
func subclassComposition(_: MyCustomObject & NSRuncing & NSFunging)
165167
}
166168

167169
// CHECK-macosx: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
168170
// CHECK-macosx: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
169171
// CHECK-macosx: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
170-
// CHECK-macosx: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [3 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0)]
172+
// CHECK-macosx: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
173+
// CHECK-macosx: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [4 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* [[ENC4]], i64 0, i64 0)]
171174
// CHECK-ios: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
172175
// CHECK-ios: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
173176
// CHECK-ios: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
174-
// CHECK-ios: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [3 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0)]
177+
// CHECK-ios: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
178+
// CHECK-ios: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [4 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* [[ENC4]], i64 0, i64 0)]
175179
// CHECK-tvos: [[ENC1:@.*]] = private unnamed_addr constant [35 x i8] c"v24@0:8@\22<NSFunging><NSRuncing>\2216\00"
176180
// CHECK-tvos: [[ENC2:@.*]] = private unnamed_addr constant [46 x i8] c"v32@0:8@\22Gizmo\2216@?<v@?@\22NSView\22@\22NSSpoon\22>24\00"
177181
// CHECK-tvos: [[ENC3:@.*]] = private unnamed_addr constant [53 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject\2216\00"
178-
// CHECK-tvos: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [3 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0)]
182+
// CHECK-tvos: [[ENC4:@.*]] = private unnamed_addr constant [75 x i8] c"v24@0:8@\22_TtC18objc_type_encoding14MyCustomObject<NSFunging><NSRuncing>\2216\00"
183+
// CHECK-tvos: @_PROTOCOL_METHOD_TYPES__TtP18objc_type_encoding10MyProtocol_ = private constant [4 x i8*] [i8* getelementptr inbounds ([35 x i8], [35 x i8]* [[ENC1]], i64 0, i64 0), i8* getelementptr inbounds ([46 x i8], [46 x i8]* [[ENC2]], i64 0, i64 0), i8* getelementptr inbounds ([53 x i8], [53 x i8]* [[ENC3]], i64 0, i64 0), i8* getelementptr inbounds ([75 x i8], [75 x i8]* [[ENC4]], i64 0, i64 0)]

0 commit comments

Comments
 (0)