]>
Commit | Line | Data |
---|---|---|
13ba007e A |
1 | // TEST_CFLAGS -framework Foundation -Wno-deprecated-declarations |
2 | // need Foundation to get NSObject compatibility additions for class Protocol | |
3 | // because ARC calls [protocol retain] | |
4 | /* | |
5 | TEST_BUILD_OUTPUT | |
6 | .*protocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')? | |
7 | END | |
8 | */ | |
9 | ||
10 | #include "test.h" | |
11 | #include "testroot.i" | |
12 | #include <string.h> | |
13 | #include <objc/runtime.h> | |
14 | #include <objc/objc-internal.h> | |
15 | ||
16 | @protocol Proto1 | |
17 | +(id)proto1ClassMethod; | |
18 | -(id)proto1InstanceMethod; | |
19 | @end | |
20 | ||
21 | @protocol Proto2 | |
22 | +(id)proto2ClassMethod; | |
23 | -(id)proto2InstanceMethod; | |
24 | @end | |
25 | ||
26 | @protocol Proto3 <Proto2> | |
27 | +(id)proto3ClassMethod; | |
28 | -(id)proto3InstanceMethod; | |
29 | @end | |
30 | ||
31 | @protocol Proto4 | |
32 | @property int i; | |
33 | @end | |
34 | ||
35 | // Force some of Proto5's selectors out of address order rdar://10582325 | |
36 | SEL fn(int x) { if (x) return @selector(m12:); else return @selector(m22:); } | |
37 | ||
38 | // This declaration order deliberately looks weird because it determines the | |
39 | // selector address order on some architectures rdar://10582325 | |
40 | @protocol Proto5 | |
41 | -(id)m11:(id<Proto1>)a; | |
42 | -(void)m12:(id<Proto1>)a; | |
43 | -(int)m13:(id<Proto1>)a; | |
44 | +(void)m22:(TestRoot<Proto1>*)a; | |
45 | +(int)m23:(TestRoot<Proto1>*)a; | |
46 | +(TestRoot*)m21:(TestRoot<Proto1>*)a; | |
47 | @optional | |
48 | -(id(^)(id))m31:(id<Proto1>(^)(id<Proto1>))a; | |
49 | -(void)m32:(id<Proto1>(^)(id<Proto1>))a; | |
50 | -(int)m33:(id<Proto1>(^)(id<Proto1>))a; | |
51 | +(void)m42:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a; | |
52 | +(int)m43:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a; | |
53 | +(TestRoot*(^)(TestRoot*))m41:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a; | |
54 | @end | |
55 | ||
56 | @protocol Proto6 <Proto5> | |
57 | @optional | |
58 | +(TestRoot*(^)(TestRoot*))n41:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a; | |
59 | @end | |
60 | ||
61 | @protocol ProtoEmpty | |
62 | @end | |
63 | ||
64 | #define SwiftV1MangledName "_TtP6Module15SwiftV1Protocol_" | |
65 | ||
66 | __attribute__((objc_runtime_name(SwiftV1MangledName))) | |
67 | @protocol SwiftV1Protocol | |
68 | @end | |
69 | ||
70 | @interface Super : TestRoot <Proto1> @end | |
71 | @implementation Super | |
72 | +(id)proto1ClassMethod { return self; } | |
73 | -(id)proto1InstanceMethod { return self; } | |
74 | @end | |
75 | ||
76 | @interface SubNoProtocols : Super @end | |
77 | @implementation SubNoProtocols @end | |
78 | ||
79 | @interface SuperNoProtocols : TestRoot @end | |
80 | @implementation SuperNoProtocols | |
81 | @end | |
82 | ||
83 | @interface SubProp : Super <Proto4> { int i; } @end | |
84 | @implementation SubProp | |
85 | @synthesize i; | |
86 | @end | |
87 | ||
88 | ||
89 | int main() | |
90 | { | |
91 | Class cls; | |
92 | Protocol * __unsafe_unretained *list; | |
93 | Protocol *protocol, *empty; | |
94 | struct objc_method_description desc2; | |
95 | objc_property_t *proplist; | |
96 | unsigned int count; | |
97 | ||
98 | protocol = @protocol(Proto3); | |
99 | empty = @protocol(ProtoEmpty); | |
100 | testassert(protocol); | |
101 | testassert(empty); | |
102 | ||
103 | testassert(0 == strcmp(protocol_getName(protocol), "Proto3")); | |
104 | testassert(0 == strcmp(protocol_getName(empty), "ProtoEmpty")); | |
105 | ||
106 | testassert(class_conformsToProtocol([Super class], @protocol(Proto1))); | |
107 | testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto1))); | |
108 | testassert(class_conformsToProtocol([SubProp class], @protocol(Proto4))); | |
109 | testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto3))); | |
110 | testassert(!class_conformsToProtocol([Super class], @protocol(Proto3))); | |
111 | ||
112 | testassert(!protocol_conformsToProtocol(@protocol(Proto1), @protocol(Proto2))); | |
113 | testassert(protocol_conformsToProtocol(@protocol(Proto3), @protocol(Proto2))); | |
114 | testassert(!protocol_conformsToProtocol(@protocol(Proto2), @protocol(Proto3))); | |
115 | ||
116 | testassert(protocol_isEqual(@protocol(Proto1), @protocol(Proto1))); | |
117 | testassert(! protocol_isEqual(@protocol(Proto1), @protocol(Proto2))); | |
118 | ||
119 | desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, YES); | |
120 | testassert(desc2.name && desc2.types); | |
121 | testassert(desc2.name == @selector(proto3InstanceMethod)); | |
122 | desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, NO); | |
123 | testassert(desc2.name && desc2.types); | |
124 | testassert(desc2.name == @selector(proto3ClassMethod)); | |
125 | desc2 = protocol_getMethodDescription(protocol, @selector(proto2ClassMethod), YES, NO); | |
126 | testassert(desc2.name && desc2.types); | |
127 | testassert(desc2.name == @selector(proto2ClassMethod)); | |
128 | ||
129 | desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, YES); | |
130 | testassert(!desc2.name && !desc2.types); | |
131 | desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, NO); | |
132 | testassert(!desc2.name && !desc2.types); | |
133 | desc2 = protocol_getMethodDescription(empty, @selector(proto3ClassMethod), YES, YES); | |
134 | testassert(!desc2.name && !desc2.types); | |
135 | desc2 = protocol_getMethodDescription(empty, @selector(proto3InstanceMethod), YES, NO); | |
136 | testassert(!desc2.name && !desc2.types); | |
137 | ||
138 | count = 100; | |
139 | list = protocol_copyProtocolList(@protocol(Proto2), &count); | |
140 | testassert(!list); | |
141 | testassert(count == 0); | |
142 | count = 100; | |
143 | list = protocol_copyProtocolList(@protocol(Proto3), &count); | |
144 | testassert(list); | |
145 | testassert(count == 1); | |
146 | testassert(protocol_isEqual(list[0], @protocol(Proto2))); | |
147 | testassert(!list[1]); | |
148 | free(list); | |
149 | ||
150 | count = 100; | |
151 | cls = objc_getClass("Super"); | |
152 | testassert(cls); | |
153 | list = class_copyProtocolList(cls, &count); | |
154 | testassert(list); | |
155 | testassert(list[count] == NULL); | |
156 | testassert(count == 1); | |
157 | testassert(0 == strcmp(protocol_getName(list[0]), "Proto1")); | |
158 | free(list); | |
159 | ||
160 | count = 100; | |
161 | cls = objc_getClass("SuperNoProtocols"); | |
162 | testassert(cls); | |
163 | list = class_copyProtocolList(cls, &count); | |
164 | testassert(!list); | |
165 | testassert(count == 0); | |
166 | ||
167 | count = 100; | |
168 | cls = objc_getClass("SubNoProtocols"); | |
169 | testassert(cls); | |
170 | list = class_copyProtocolList(cls, &count); | |
171 | testassert(!list); | |
172 | testassert(count == 0); | |
173 | ||
174 | ||
175 | cls = objc_getClass("SuperNoProtocols"); | |
176 | testassert(cls); | |
177 | list = class_copyProtocolList(cls, NULL); | |
178 | testassert(!list); | |
179 | ||
180 | cls = objc_getClass("Super"); | |
181 | testassert(cls); | |
182 | list = class_copyProtocolList(cls, NULL); | |
183 | testassert(list); | |
184 | free(list); | |
185 | ||
186 | count = 100; | |
187 | list = class_copyProtocolList(NULL, &count); | |
188 | testassert(!list); | |
189 | testassert(count == 0); | |
190 | ||
191 | ||
192 | // Check property added by protocol | |
193 | cls = objc_getClass("SubProp"); | |
194 | testassert(cls); | |
195 | ||
196 | count = 100; | |
197 | list = class_copyProtocolList(cls, &count); | |
198 | testassert(list); | |
199 | testassert(count == 1); | |
200 | testassert(0 == strcmp(protocol_getName(list[0]), "Proto4")); | |
201 | testassert(list[1] == NULL); | |
202 | free(list); | |
203 | ||
204 | count = 100; | |
205 | proplist = class_copyPropertyList(cls, &count); | |
206 | testassert(proplist); | |
207 | testassert(count == 1); | |
208 | testassert(0 == strcmp(property_getName(proplist[0]), "i")); | |
209 | testassert(proplist[1] == NULL); | |
210 | free(proplist); | |
211 | ||
212 | // Check extended type encodings | |
213 | testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(DoesNotExist), true, true) == NULL); | |
214 | testassert(_protocol_getMethodTypeEncoding(NULL, @selector(m11), true, true) == NULL); | |
215 | testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), true, false) == NULL); | |
216 | testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, false) == NULL); | |
217 | testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, true) == NULL); | |
218 | testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21), true, true) == NULL); | |
219 | #if __LP64__ | |
220 | const char *types11 = "@24@0:8@\"<Proto1>\"16"; | |
221 | const char *types12 = "v24@0:8@\"<Proto1>\"16"; | |
222 | const char *types13 = "i24@0:8@\"<Proto1>\"16"; | |
223 | const char *types21 = "@\"TestRoot\"24@0:8@\"TestRoot<Proto1>\"16"; | |
224 | const char *types22 = "v24@0:8@\"TestRoot<Proto1>\"16"; | |
225 | const char *types23 = "i24@0:8@\"TestRoot<Proto1>\"16"; | |
226 | const char *types31 = "@?<@@?@>24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16"; | |
227 | const char *types32 = "v24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16"; | |
228 | const char *types33 = "i24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16"; | |
229 | const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16"; | |
230 | const char *types42 = "v24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16"; | |
231 | const char *types43 = "i24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16"; | |
232 | #else | |
233 | const char *types11 = "@12@0:4@\"<Proto1>\"8"; | |
234 | const char *types12 = "v12@0:4@\"<Proto1>\"8"; | |
235 | const char *types13 = "i12@0:4@\"<Proto1>\"8"; | |
236 | const char *types21 = "@\"TestRoot\"12@0:4@\"TestRoot<Proto1>\"8"; | |
237 | const char *types22 = "v12@0:4@\"TestRoot<Proto1>\"8"; | |
238 | const char *types23 = "i12@0:4@\"TestRoot<Proto1>\"8"; | |
239 | const char *types31 = "@?<@@?@>12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8"; | |
240 | const char *types32 = "v12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8"; | |
241 | const char *types33 = "i12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8"; | |
242 | const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8"; | |
243 | const char *types42 = "v12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8"; | |
244 | const char *types43 = "i12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8"; | |
245 | #endif | |
246 | ||
247 | // Make sure some of Proto5's selectors are out of order rdar://10582325 | |
248 | // These comparisons deliberately look weird because they determine the | |
249 | // selector order on some architectures. | |
250 | testassert(sel_registerName("m11:") > sel_registerName("m12:") || | |
251 | sel_registerName("m21:") > sel_registerName("m22:") || | |
252 | sel_registerName("m32:") < sel_registerName("m31:") || | |
253 | sel_registerName("m42:") < sel_registerName("m41:") ); | |
254 | ||
255 | if (!_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true)) { | |
256 | fail("rdar://10492418 extended type encodings not present (is compiler old?)"); | |
257 | } else { | |
258 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true), types11)); | |
259 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m12:), true, true), types12)); | |
260 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m13:), true, true), types13)); | |
261 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21:), true, false), types21)); | |
262 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m22:), true, false), types22)); | |
263 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m23:), true, false), types23)); | |
264 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m31:), false, true), types31)); | |
265 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m32:), false, true), types32)); | |
266 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m33:), false, true), types33)); | |
267 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m41:), false, false), types41)); | |
268 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m42:), false, false), types42)); | |
269 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m43:), false, false), types43)); | |
270 | ||
271 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(n41:), false, false), types41)); | |
272 | testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(m41:), false, false), types41)); | |
273 | } | |
274 | ||
275 | testassert(@protocol(SwiftV1Protocol) == objc_getProtocol("Module.SwiftV1Protocol")); | |
276 | testassert(@protocol(SwiftV1Protocol) == objc_getProtocol(SwiftV1MangledName)); | |
277 | testassert(0 == strcmp(protocol_getName(@protocol(SwiftV1Protocol)), "Module.SwiftV1Protocol")); | |
278 | testassert(!objc_getProtocol("SwiftV1Protocol")); | |
279 | ||
280 | succeed(__FILE__); | |
281 | } |