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