protocol.m 12 KB

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