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#include "test.h" 6#include "testroot.i" 7#include <string.h> 8#include <objc/runtime.h> 9#include <objc/objc-internal.h> 10 11#if !__OBJC2__ 12#include <objc/Protocol.h> 13#endif 14 15@protocol Proto1 16+(id)proto1ClassMethod; 17-(id)proto1InstanceMethod; 18@end 19 20@protocol Proto2 21+(id)proto2ClassMethod; 22-(id)proto2InstanceMethod; 23@end 24 25@protocol Proto3 <Proto2> 26+(id)proto3ClassMethod; 27-(id)proto3InstanceMethod; 28@end 29 30@protocol Proto4 31@property int i; 32@end 33 34 35// Force some of Proto5's selectors out of address order rdar://10582325 36SEL 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@interface Super : TestRoot <Proto1> @end 65@implementation Super 66+(id)proto1ClassMethod { return self; } 67-(id)proto1InstanceMethod { return self; } 68@end 69 70@interface SubNoProtocols : Super @end 71@implementation SubNoProtocols @end 72 73@interface SuperNoProtocols : TestRoot @end 74@implementation SuperNoProtocols 75@end 76 77@interface SubProp : Super <Proto4> { int i; } @end 78@implementation SubProp 79@synthesize i; 80@end 81 82 83int main() 84{ 85 Class cls; 86 Protocol * __unsafe_unretained *list; 87 Protocol *protocol, *empty; 88#if !__OBJC2__ 89 struct objc_method_description *desc; 90#endif 91 struct objc_method_description desc2; 92 objc_property_t *proplist; 93 unsigned int count; 94 95 protocol = @protocol(Proto3); 96 empty = @protocol(ProtoEmpty); 97 testassert(protocol); 98 testassert(empty); 99 100#if !__OBJC2__ 101 testassert([protocol isKindOf:[Protocol class]]); 102 testassert([empty isKindOf:[Protocol class]]); 103 testassert(0 == strcmp([protocol name], "Proto3")); 104 testassert(0 == strcmp([empty name], "ProtoEmpty")); 105#endif 106 testassert(0 == strcmp(protocol_getName(protocol), "Proto3")); 107 testassert(0 == strcmp(protocol_getName(empty), "ProtoEmpty")); 108 109 testassert(class_conformsToProtocol([Super class], @protocol(Proto1))); 110 testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto1))); 111 testassert(class_conformsToProtocol([SubProp class], @protocol(Proto4))); 112 testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto3))); 113 testassert(!class_conformsToProtocol([Super class], @protocol(Proto3))); 114 115 testassert(!protocol_conformsToProtocol(@protocol(Proto1), @protocol(Proto2))); 116 testassert(protocol_conformsToProtocol(@protocol(Proto3), @protocol(Proto2))); 117 testassert(!protocol_conformsToProtocol(@protocol(Proto2), @protocol(Proto3))); 118 119#if !__OBJC2__ 120 testassert([@protocol(Proto1) isEqual:@protocol(Proto1)]); 121 testassert(! [@protocol(Proto1) isEqual:@protocol(Proto2)]); 122#endif 123 testassert(protocol_isEqual(@protocol(Proto1), @protocol(Proto1))); 124 testassert(! protocol_isEqual(@protocol(Proto1), @protocol(Proto2))); 125 126#if !__OBJC2__ 127 desc = [protocol descriptionForInstanceMethod:@selector(proto3InstanceMethod)]; 128 testassert(desc); 129 testassert(desc->name == @selector(proto3InstanceMethod)); 130 desc = [protocol descriptionForClassMethod:@selector(proto3ClassMethod)]; 131 testassert(desc); 132 testassert(desc->name == @selector(proto3ClassMethod)); 133 desc = [protocol descriptionForClassMethod:@selector(proto2ClassMethod)]; 134 testassert(desc); 135 testassert(desc->name == @selector(proto2ClassMethod)); 136 137 desc = [protocol descriptionForInstanceMethod:@selector(proto3ClassMethod)]; 138 testassert(!desc); 139 desc = [protocol descriptionForClassMethod:@selector(proto3InstanceMethod)]; 140 testassert(!desc); 141 desc = [empty descriptionForInstanceMethod:@selector(proto3ClassMethod)]; 142 testassert(!desc); 143 desc = [empty descriptionForClassMethod:@selector(proto3InstanceMethod)]; 144 testassert(!desc); 145#endif 146 desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, YES); 147 testassert(desc2.name && desc2.types); 148 testassert(desc2.name == @selector(proto3InstanceMethod)); 149 desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, NO); 150 testassert(desc2.name && desc2.types); 151 testassert(desc2.name == @selector(proto3ClassMethod)); 152 desc2 = protocol_getMethodDescription(protocol, @selector(proto2ClassMethod), YES, NO); 153 testassert(desc2.name && desc2.types); 154 testassert(desc2.name == @selector(proto2ClassMethod)); 155 156 desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, YES); 157 testassert(!desc2.name && !desc2.types); 158 desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, NO); 159 testassert(!desc2.name && !desc2.types); 160 desc2 = protocol_getMethodDescription(empty, @selector(proto3ClassMethod), YES, YES); 161 testassert(!desc2.name && !desc2.types); 162 desc2 = protocol_getMethodDescription(empty, @selector(proto3InstanceMethod), YES, NO); 163 testassert(!desc2.name && !desc2.types); 164 165 count = 100; 166 list = protocol_copyProtocolList(@protocol(Proto2), &count); 167 testassert(!list); 168 testassert(count == 0); 169 count = 100; 170 list = protocol_copyProtocolList(@protocol(Proto3), &count); 171 testassert(list); 172 testassert(count == 1); 173 testassert(protocol_isEqual(list[0], @protocol(Proto2))); 174 testassert(!list[1]); 175 free(list); 176 177 count = 100; 178 cls = objc_getClass("Super"); 179 testassert(cls); 180 list = class_copyProtocolList(cls, &count); 181 testassert(list); 182 testassert(list[count] == NULL); 183 testassert(count == 1); 184 testassert(0 == strcmp(protocol_getName(list[0]), "Proto1")); 185 free(list); 186 187 count = 100; 188 cls = objc_getClass("SuperNoProtocols"); 189 testassert(cls); 190 list = class_copyProtocolList(cls, &count); 191 testassert(!list); 192 testassert(count == 0); 193 194 count = 100; 195 cls = objc_getClass("SubNoProtocols"); 196 testassert(cls); 197 list = class_copyProtocolList(cls, &count); 198 testassert(!list); 199 testassert(count == 0); 200 201 202 cls = objc_getClass("SuperNoProtocols"); 203 testassert(cls); 204 list = class_copyProtocolList(cls, NULL); 205 testassert(!list); 206 207 cls = objc_getClass("Super"); 208 testassert(cls); 209 list = class_copyProtocolList(cls, NULL); 210 testassert(list); 211 free(list); 212 213 count = 100; 214 list = class_copyProtocolList(NULL, &count); 215 testassert(!list); 216 testassert(count == 0); 217 218 219 // Check property added by protocol 220 cls = objc_getClass("SubProp"); 221 testassert(cls); 222 223 count = 100; 224 list = class_copyProtocolList(cls, &count); 225 testassert(list); 226 testassert(count == 1); 227 testassert(0 == strcmp(protocol_getName(list[0]), "Proto4")); 228 testassert(list[1] == NULL); 229 free(list); 230 231 count = 100; 232 proplist = class_copyPropertyList(cls, &count); 233 testassert(proplist); 234 testassert(count == 1); 235 testassert(0 == strcmp(property_getName(proplist[0]), "i")); 236 testassert(proplist[1] == NULL); 237 free(proplist); 238 239 // Check extended type encodings 240 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(DoesNotExist), true, true) == NULL); 241 testassert(_protocol_getMethodTypeEncoding(NULL, @selector(m11), true, true) == NULL); 242 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), true, false) == NULL); 243 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, false) == NULL); 244 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, true) == NULL); 245 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21), true, true) == NULL); 246#if __LP64__ 247 const char *types11 = "@24@0:8@\"<Proto1>\"16"; 248 const char *types12 = "v24@0:8@\"<Proto1>\"16"; 249 const char *types13 = "i24@0:8@\"<Proto1>\"16"; 250 const char *types21 = "@\"TestRoot\"24@0:8@\"TestRoot<Proto1>\"16"; 251 const char *types22 = "v24@0:8@\"TestRoot<Proto1>\"16"; 252 const char *types23 = "i24@0:8@\"TestRoot<Proto1>\"16"; 253 const char *types31 = "@?<@@?@>24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16"; 254 const char *types32 = "v24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16"; 255 const char *types33 = "i24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16"; 256 const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16"; 257 const char *types42 = "v24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16"; 258 const char *types43 = "i24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16"; 259#else 260 const char *types11 = "@12@0:4@\"<Proto1>\"8"; 261 const char *types12 = "v12@0:4@\"<Proto1>\"8"; 262 const char *types13 = "i12@0:4@\"<Proto1>\"8"; 263 const char *types21 = "@\"TestRoot\"12@0:4@\"TestRoot<Proto1>\"8"; 264 const char *types22 = "v12@0:4@\"TestRoot<Proto1>\"8"; 265 const char *types23 = "i12@0:4@\"TestRoot<Proto1>\"8"; 266 const char *types31 = "@?<@@?@>12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8"; 267 const char *types32 = "v12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8"; 268 const char *types33 = "i12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8"; 269 const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8"; 270 const char *types42 = "v12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8"; 271 const char *types43 = "i12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8"; 272#endif 273 274 // Make sure some of Proto5's selectors are out of order rdar://10582325 275 // These comparisons deliberately look weird because they determine the 276 // selector order on some architectures. 277 testassert(sel_registerName("m11:") > sel_registerName("m12:") || 278 sel_registerName("m21:") > sel_registerName("m22:") || 279 sel_registerName("m32:") < sel_registerName("m31:") || 280 sel_registerName("m42:") < sel_registerName("m41:") ); 281 282 if (!_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true)) { 283#if __clang__ 284 testwarn("rdar://10492418 extended type encodings not present (is compiler old?)"); 285#else 286 // extended type encodings quietly not supported 287 testwarn("rdar://10492418 extended type encodings not present (compiler is not clang?)"); 288#endif 289 } else { 290 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true), types11)); 291 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m12:), true, true), types12)); 292 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m13:), true, true), types13)); 293 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21:), true, false), types21)); 294 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m22:), true, false), types22)); 295 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m23:), true, false), types23)); 296 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m31:), false, true), types31)); 297 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m32:), false, true), types32)); 298 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m33:), false, true), types33)); 299 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m41:), false, false), types41)); 300 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m42:), false, false), types42)); 301 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m43:), false, false), types43)); 302 303 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(n41:), false, false), types41)); 304 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(m41:), false, false), types41)); 305 } 306 307 succeed(__FILE__); 308} 309