1#include "Test.h" 2#include <stdlib.h> 3#include <stdio.h> 4#include <string.h> 5#include <assert.h> 6#include <stdatomic.h> 7 8#pragma GCC diagnostic ignored "-Wobjc-property-no-attribute" 9 10// Clang < 3 doesn't exist usefully, so we can skip tests for it. Clang 3.5 11// adds proper metadata for weak properties, earlier ones don't, so don't fail 12// the tests because of known compiler bugs. 13#ifndef __clang_minor__ 14#define WEAK_ATTR ATTR("W", ""), 15#define WEAK_STR "W," 16#elif (__clang_major__ < 4) && (__clang_minor__ < 5) 17#define WEAK_ATTR 18#define WEAK_STR 19#else 20#define WEAK_ATTR ATTR("W", ""), 21#define WEAK_STR "W," 22#endif 23 24enum FooManChu { FOO, MAN, CHU }; 25struct YorkshireTeaStruct { int pot; signed char lady; }; 26typedef struct YorkshireTeaStruct YorkshireTeaStructType; 27union MoneyUnion { float alone; double down; }; 28 29#ifndef __has_attribute 30#define __has_attribute(x) 0 31#endif 32 33#if __has_attribute(objc_root_class) 34__attribute__((objc_root_class)) 35#endif 36@interface PropertyTest 37{ 38@public 39 Class isa; 40 atomic_bool atomicBoolDefault; 41 signed char charDefault; 42 double doubleDefault; 43 enum FooManChu enumDefault; 44 float floatDefault; 45 int intDefault; 46 long longDefault; 47 short shortDefault; 48 signed signedDefault; 49 struct YorkshireTeaStruct structDefault; 50 YorkshireTeaStructType typedefDefault; 51 union MoneyUnion unionDefault; 52 unsigned unsignedDefault; 53 int (*functionPointerDefault)(char *); 54 int *intPointer; 55 void *voidPointerDefault; 56 int intSynthEquals; 57 int intSetterGetter; 58 int intReadonly; 59 int intReadonlyGetter; 60 int intReadwrite; 61 int intAssign; 62 __unsafe_unretained id idDefault; 63 id idRetain; 64 id idCopy; 65 __weak id idWeak; 66 id idStrong; 67 int intNonatomic; 68 id idReadonlyCopyNonatomic; 69 id idReadonlyRetainNonatomic; 70 __weak id idReadonlyWeakNonatomic; 71 id _idOther; 72} 73@property atomic_bool atomicBoolDefault; 74@property signed char charDefault; 75@property double doubleDefault; 76@property enum FooManChu enumDefault; 77@property float floatDefault; 78@property int intDefault; 79@property long longDefault; 80@property short shortDefault; 81@property signed signedDefault; 82@property struct YorkshireTeaStruct structDefault; 83@property YorkshireTeaStructType typedefDefault; 84@property union MoneyUnion unionDefault; 85@property unsigned unsignedDefault; 86@property int (*functionPointerDefault)(char *); 87@property int *intPointer; 88@property void *voidPointerDefault; 89@property(getter=intGetFoo, setter=intSetFoo:) int intSetterGetter; 90@property(readonly) int intReadonly; 91@property(getter=isIntReadOnlyGetter, readonly) int intReadonlyGetter; 92@property(readwrite) int intReadwrite; 93@property(assign) int intAssign; 94@property(unsafe_unretained) id idDefault; 95@property(retain) id idRetain; 96@property(copy) id idCopy; 97@property(weak) id idWeak; 98@property(strong) id idStrong; 99@property(nonatomic) int intNonatomic; 100@property(nonatomic, readonly, copy) id idReadonlyCopyNonatomic; 101@property(nonatomic, readonly, retain) id idReadonlyRetainNonatomic; 102@property(nonatomic, readonly, weak) id idReadonlyWeakNonatomic; 103@property(retain) id idOther; 104@property(retain) id idDynamic; 105@property(retain, nonatomic, getter=dynamicGetterSetter, setter=setDynamicGetterSetter:) id idDynamicGetterSetter; 106@end 107 108@interface PropertyTest (Informal) 109- (void)setStructDefault2: (struct YorkshireTeaStruct)tp; 110- (void)setIntDefault2: (int)i; 111- (struct YorkshireTeaStruct)structDefault2; 112- (int)intDefault2; 113@end 114 115 116@implementation PropertyTest 117@synthesize atomicBoolDefault; 118@synthesize charDefault; 119@synthesize doubleDefault; 120@synthesize enumDefault; 121@synthesize floatDefault; 122@synthesize intDefault; 123@synthesize longDefault; 124@synthesize shortDefault; 125@synthesize signedDefault; 126@synthesize structDefault; 127@synthesize typedefDefault; 128@synthesize unionDefault; 129@synthesize unsignedDefault; 130@synthesize functionPointerDefault; 131@synthesize intPointer; 132@synthesize voidPointerDefault; 133@synthesize intSetterGetter; 134@synthesize intReadonly; 135@synthesize intReadonlyGetter; 136@synthesize intReadwrite; 137@synthesize intAssign; 138@synthesize idDefault; 139@synthesize idRetain; 140@synthesize idCopy; 141@synthesize idWeak; 142@synthesize idStrong; 143@synthesize intNonatomic; 144@synthesize idReadonlyCopyNonatomic; 145@synthesize idReadonlyRetainNonatomic; 146@synthesize idReadonlyWeakNonatomic; 147@synthesize idOther = _idOther; 148@dynamic idDynamic; 149@dynamic idDynamicGetterSetter; 150- (void)_ARCCompliantRetainRelease {} 151@end 152 153@protocol ProtocolTest 154@property atomic_bool atomicBoolDefault; 155@property signed char charDefault; 156@property double doubleDefault; 157@property enum FooManChu enumDefault; 158@property float floatDefault; 159@property int intDefault; 160@property long longDefault; 161@property short shortDefault; 162@property signed signedDefault; 163@property struct YorkshireTeaStruct structDefault; 164@property YorkshireTeaStructType typedefDefault; 165@property union MoneyUnion unionDefault; 166@property unsigned unsignedDefault; 167@property int (*functionPointerDefault)(char *); 168@property int *intPointer; 169@property void *voidPointerDefault; 170@property(getter=intGetFoo, setter=intSetFoo:) int intSetterGetter; 171@property(readonly) int intReadonly; 172@property(getter=isIntReadOnlyGetter, readonly) int intReadonlyGetter; 173@property(readwrite) int intReadwrite; 174@property(assign) int intAssign; 175@property(unsafe_unretained) id idDefault; 176@property(retain) id idRetain; 177@property(copy) id idCopy; 178@property(weak) id idWeak; 179@property(strong) id idStrong; 180@property(nonatomic) int intNonatomic; 181@property(nonatomic, readonly, copy) id idReadonlyCopyNonatomic; 182@property(nonatomic, readonly, retain) id idReadonlyRetainNonatomic; 183@property(nonatomic, readonly, weak) id idReadonlyWeakNonatomic; 184@property(retain) id idOther; 185@property(retain) id idDynamic; 186@property(retain, nonatomic, getter=dynamicGetterSetter, setter=setDynamicGetterSetter:) id idDynamicGetterSetter; 187@end 188 189#if __has_attribute(objc_root_class) 190__attribute__((objc_root_class)) 191#endif 192@interface PropertyProtocolTest <ProtocolTest> 193{ 194 Class isa; 195 atomic_bool atomicBoolDefault; 196 signed char charDefault; 197 double doubleDefault; 198 enum FooManChu enumDefault; 199 float floatDefault; 200 int intDefault; 201 long longDefault; 202 short shortDefault; 203 signed signedDefault; 204 struct YorkshireTeaStruct structDefault; 205 YorkshireTeaStructType typedefDefault; 206 union MoneyUnion unionDefault; 207 unsigned unsignedDefault; 208 int (*functionPointerDefault)(char *); 209 int *intPointer; 210 void *voidPointerDefault; 211 int intSynthEquals; 212 int intSetterGetter; 213 int intReadonly; 214 int intReadonlyGetter; 215 int intReadwrite; 216 int intAssign; 217 __unsafe_unretained id idDefault; 218 id idRetain; 219 id idCopy; 220 __weak id idWeak; 221 id idStrong; 222 int intNonatomic; 223 id idReadonlyCopyNonatomic; 224 id idReadonlyRetainNonatomic; 225 __weak id idReadonlyWeakNonatomic; 226 id _idOther; 227} 228@end 229 230@implementation PropertyProtocolTest 231@synthesize atomicBoolDefault; 232@synthesize charDefault; 233@synthesize doubleDefault; 234@synthesize enumDefault; 235@synthesize floatDefault; 236@synthesize intDefault; 237@synthesize longDefault; 238@synthesize shortDefault; 239@synthesize signedDefault; 240@synthesize structDefault; 241@synthesize typedefDefault; 242@synthesize unionDefault; 243@synthesize unsignedDefault; 244@synthesize functionPointerDefault; 245@synthesize intPointer; 246@synthesize voidPointerDefault; 247@synthesize intSetterGetter; 248@synthesize intReadonly; 249@synthesize intReadonlyGetter; 250@synthesize intReadwrite; 251@synthesize intAssign; 252@synthesize idDefault; 253@synthesize idRetain; 254@synthesize idCopy; 255@synthesize idWeak; 256@synthesize idStrong; 257@synthesize intNonatomic; 258@synthesize idReadonlyCopyNonatomic; 259@synthesize idReadonlyRetainNonatomic; 260@synthesize idReadonlyWeakNonatomic; 261@synthesize idOther = _idOther; 262@dynamic idDynamic; 263@dynamic idDynamicGetterSetter; 264- (void)_ARCCompliantRetainRelease {} 265@end 266 267#define ATTR(n, v) (objc_property_attribute_t){(n), (v)} 268#define ATTRS(...) (objc_property_attribute_t[]){ __VA_ARGS__ }, \ 269 sizeof((objc_property_attribute_t[]){ __VA_ARGS__ }) / sizeof(objc_property_attribute_t) 270#define OPT_ASSERT(stmt) if (abort) { \ 271 assert(stmt);\ 272} else { \ 273 if (!(stmt)) { return NO; } \ 274} 275 276static BOOL testPropertyForProperty_alt(objc_property_t p, 277 const char *name, 278 const char *types, 279 objc_property_attribute_t* list, 280 unsigned int size, BOOL abort) 281{ 282 OPT_ASSERT(0 != p); 283 OPT_ASSERT(strcmp(name, property_getName(p)) == 0); 284 const char *attrs = property_getAttributes(p); 285 OPT_ASSERT(0 != attrs); 286 OPT_ASSERT(strcmp(types, attrs) == 0); 287 unsigned int attrsCount = 0; 288 objc_property_attribute_t *attrsList = property_copyAttributeList(p, &attrsCount); 289 OPT_ASSERT(0 != attrsList); 290 OPT_ASSERT(attrsCount == size); 291 for (unsigned int index=0; index<size; index++) { 292 int found = 0; 293 for (unsigned int attrsIndex=0; attrsIndex<attrsCount; attrsIndex++) { 294 if (strcmp(attrsList[attrsIndex].name, list[index].name) == 0) { 295 OPT_ASSERT(strcmp(attrsList[attrsIndex].value, list[index].value) == 0); 296 found = 1; 297 } 298 } 299 OPT_ASSERT(found); 300 } 301 free(attrsList); 302 attrsList = property_copyAttributeList(p, NULL); 303 OPT_ASSERT(0 != attrsList); 304 objc_property_attribute_t *ra; 305 for (attrsCount = 0, ra = attrsList; (ra->name != NULL) && (attrsCount < size); attrsCount++, ra++) {} 306 OPT_ASSERT(attrsCount == size); 307 free(attrsList); 308 for (unsigned int index=0; index<size; index++) { 309 const char* value = property_copyAttributeValue(p, list[index].name); 310 OPT_ASSERT(0 != value); 311 OPT_ASSERT(strcmp(value, list[index].value) == 0); 312 } 313 return YES; 314} 315 316 317static void testPropertyForProperty(objc_property_t p, 318 const char *name, 319 const char *types, 320 objc_property_attribute_t* list, 321 unsigned int size) 322{ 323 testPropertyForProperty_alt(p, name, types, list, size, YES); 324} 325 326static void testPropertyForClass(Class testClass, 327 const char *name, 328 const char *types, 329 objc_property_attribute_t* list, 330 unsigned int size) 331{ 332 testPropertyForProperty(class_getProperty(testClass, name), name, types, list, size); 333 334 static int addPropertyForClassIndex = 0; 335 char addPropertyName[32]; 336 sprintf(addPropertyName, "addPropertyForClass%d", ++addPropertyForClassIndex); 337 assert(class_addProperty(testClass, addPropertyName, list, size)); 338 testPropertyForProperty(class_getProperty(testClass, addPropertyName), addPropertyName, types, list, size); 339} 340 341static BOOL testPropertyForProtocol_alt(Protocol *testProto, 342 const char *name, 343 const char *types, 344 objc_property_attribute_t* list, 345 unsigned int size, BOOL abort) 346{ 347 if (!testPropertyForProperty_alt(protocol_getProperty(testProto, name, YES, YES), name, types, list, size, abort)) 348 { 349 return NO; 350 } 351 352 static int addPropertyForProtocolIndex = 0; 353 char addPropertyName[32]; 354 sprintf(addPropertyName, "addPropertyForProtocol%d", ++addPropertyForProtocolIndex); 355 protocol_addProperty(testProto, addPropertyName, list, size, YES, YES); 356 OPT_ASSERT(0 == protocol_getProperty(testProto, addPropertyName, YES, YES)); 357 return YES; 358} 359 360static void testPropertyForProtocol(Protocol *testProto, 361 const char *name, 362 const char *types, 363 objc_property_attribute_t* list, 364 unsigned int size) 365{ 366 testPropertyForProtocol_alt(testProto, name, types, list, size, YES); 367} 368 369static BOOL testProperty_alt(const char *name, const char *types, objc_property_attribute_t* list, unsigned int size, BOOL abort) 370{ 371 return testPropertyForProperty_alt(class_getProperty(objc_getClass("PropertyTest"), name), name, types, list, size, abort) 372 && testPropertyForProperty_alt(class_getProperty(objc_getClass("PropertyProtocolTest"), name), name, types, list, size, abort); 373} 374 375static void testProperty(const char *name, const char *types, objc_property_attribute_t* list, unsigned int size) 376{ 377 testProperty_alt(name, types, list, size, YES); 378} 379 380static void testAddPropertyForClass(Class testClass) 381{ 382 objc_property_attribute_t emptyType = { "T", "i" }; 383 assert(!class_addProperty(testClass, NULL, &emptyType, 1)); 384 class_replaceProperty(testClass, NULL, &emptyType, 1); 385 386 assert(class_addProperty(testClass, "addProperty1", ATTRS(ATTR("T", "@")))); 387 testPropertyForProperty(class_getProperty(testClass, "addProperty1"), 388 "addProperty1", "T@", ATTRS(ATTR("T", "@"))); 389 390 assert(class_addProperty(testClass, "addProperty2", ATTRS(ATTR("T", "@"), 391 ATTR("D", "")))); 392 testPropertyForProperty(class_getProperty(testClass, "addProperty2"), 393 "addProperty2", "T@,D", ATTRS(ATTR("T", "@"), 394 ATTR("D", ""))); 395 396 assert(class_addProperty(testClass, "addProperty3", ATTRS(ATTR("T", "@"), 397 ATTR("D", ""), 398 ATTR("V", "backingIvar")))); 399 testPropertyForProperty(class_getProperty(testClass, "addProperty3"), 400 "addProperty3", "T@,D,VbackingIvar", ATTRS(ATTR("T", "@"), 401 ATTR("D", ""), 402 ATTR("V", "backingIvar"))); 403 404 assert(class_addProperty(testClass, "addProperty4", ATTRS(ATTR("T", "@"), 405 ATTR("R", ""), 406 ATTR("&", ""), 407 ATTR("C", ""), 408 WEAK_ATTR 409 ATTR("D", ""), 410 ATTR("V", "backingIvar")))); 411 testPropertyForProperty(class_getProperty(testClass, "addProperty4"), 412 "addProperty4", "T@,R,&,C," WEAK_STR "D,VbackingIvar", ATTRS(ATTR("T", "@"), 413 ATTR("R", ""), 414 ATTR("&", ""), 415 ATTR("C", ""), 416 WEAK_ATTR 417 ATTR("D", ""), 418 ATTR("V", "backingIvar"))); 419 420 assert(class_addProperty(testClass, "addProperty5", ATTRS(ATTR("T", "@"), 421 ATTR("D", ""), 422 WEAK_ATTR 423 ATTR("C", ""), 424 ATTR("&", ""), 425 ATTR("R", ""), 426 ATTR("V", "backingIvar")))); 427 // The only concession to MacOS X is that we reorder the attributes string 428 if (!testPropertyForProperty_alt(class_getProperty(testClass, "addProperty5"), 429 "addProperty5", "T@,D," WEAK_STR "C,&,R,VbackingIvar", ATTRS(ATTR("T", "@"), 430 ATTR("D", ""), 431 WEAK_ATTR 432 ATTR("C", ""), 433 ATTR("&", ""), 434 ATTR("R", ""), 435 ATTR("V", "backingIvar")), NO)) 436 { 437 testPropertyForProperty(class_getProperty(testClass, "addProperty5"), 438 "addProperty5", "T@,R,&,C," WEAK_STR "D,VbackingIvar", ATTRS(ATTR("T", "@"), 439 ATTR("R", ""), 440 ATTR("&", ""), 441 ATTR("C", ""), 442 WEAK_ATTR 443 ATTR("D", ""), 444 ATTR("V", "backingIvar"))); 445 } 446 447 assert(class_addProperty(testClass, "replaceProperty", ATTRS(ATTR("T", "@")))); 448 testPropertyForProperty(class_getProperty(testClass, "replaceProperty"), 449 "replaceProperty", "T@", ATTRS(ATTR("T", "@"))); 450 451 assert(!class_addProperty(testClass, "replaceProperty", ATTRS(ATTR("T", "i")))); 452 testPropertyForProperty(class_getProperty(testClass, "replaceProperty"), 453 "replaceProperty", "T@", ATTRS(ATTR("T", "@"))); 454 455 class_replaceProperty(testClass, "replaceProperty", ATTRS(ATTR("T", "i"))); 456 testPropertyForProperty(class_getProperty(testClass, "replaceProperty"), 457 "replaceProperty", "Ti", ATTRS(ATTR("T", "i"))); 458} 459 460static void testAddProperty() 461{ 462 testAddPropertyForClass(objc_getClass("PropertyTest")); 463 testAddPropertyForClass(objc_getClass("PropertyProtocolTest")); 464} 465 466static void testAddPropertyForProtocol(Protocol *testProto) 467{ 468 objc_property_attribute_t emptyType = { "T", "i" }; 469 protocol_addProperty(testProto, NULL, &emptyType, 1, YES, YES); 470 471 protocol_addProperty(testProto, "addProperty1", ATTRS(ATTR("T", "@")), YES, YES); 472 protocol_addProperty(testProto, "addProperty2", ATTRS(ATTR("T", "@"), 473 ATTR("D", "")), YES, YES); 474 protocol_addProperty(testProto, "addProperty3", ATTRS(ATTR("T", "@"), 475 ATTR("D", ""), 476 ATTR("V", "backingIvar")), YES, YES); 477 478 objc_registerProtocol(testProto); 479 480 testPropertyForProperty(protocol_getProperty(testProto, "addProperty1", YES, YES), 481 "addProperty1", "T@", ATTRS(ATTR("T", "@"))); 482 testPropertyForProperty(protocol_getProperty(testProto, "addProperty2", YES, YES), 483 "addProperty2", "T@,D", ATTRS(ATTR("T", "@"), 484 ATTR("D", ""))); 485 testPropertyForProperty(protocol_getProperty(testProto, "addProperty3", YES, YES), 486 "addProperty3", "T@,D,VbackingIvar", ATTRS(ATTR("T", "@"), 487 ATTR("D", ""), 488 ATTR("V", "backingIvar"))); 489} 490 491static int intDefault2Getter(id self, SEL _cmd) { 492 Ivar ivar = class_getInstanceVariable(objc_getClass("PropertyTest"), "intDefault"); 493 return (int)object_getIvar(self, ivar); 494} 495 496static void intDefault2Setter(id self, SEL _cmd, int value) { 497 Ivar ivar = class_getInstanceVariable(objc_getClass("PropertyTest"), "intDefault"); 498 object_setIvar(self, ivar, (__bridge id)(void*)(intptr_t)value); 499} 500 501static struct YorkshireTeaStruct structDefault2Getter(id self, SEL _cmd) { 502 struct YorkshireTeaStruct *s; 503 object_getInstanceVariable(self, "structDefault", (void**)&s); 504 return *s; 505} 506 507void structDefault2Setter(id self, SEL _cmd, struct YorkshireTeaStruct value) { 508 object_setInstanceVariable(self, "structDefault", &value); 509} 510 511int main(void) 512{ 513 testProperty("atomicBoolDefault", "TAB,VatomicBoolDefault", ATTRS(ATTR("T", "AB"), ATTR("V", "atomicBoolDefault"))); 514 testProperty("charDefault", "Tc,VcharDefault", ATTRS(ATTR("T", "c"), ATTR("V", "charDefault"))); 515 testProperty("doubleDefault", "Td,VdoubleDefault", ATTRS(ATTR("T", "d"), ATTR("V", "doubleDefault"))); 516 testProperty("enumDefault", "Ti,VenumDefault", ATTRS(ATTR("T", "i"), ATTR("V", "enumDefault"))); 517 testProperty("floatDefault", "Tf,VfloatDefault", ATTRS(ATTR("T", "f"), ATTR("V", "floatDefault"))); 518 testProperty("intDefault", "Ti,VintDefault", ATTRS(ATTR("T", "i"), ATTR("V", "intDefault"))); 519 if (sizeof(long) == 4) 520 { 521 testProperty("longDefault", "Tl,VlongDefault", ATTRS(ATTR("T", "l"), ATTR("V", "longDefault"))); 522 } 523 else 524 { 525 testProperty("longDefault", "Tq,VlongDefault", ATTRS(ATTR("T", "q"), ATTR("V", "longDefault"))); 526 } 527 testProperty("shortDefault", "Ts,VshortDefault", ATTRS(ATTR("T", "s"), ATTR("V", "shortDefault"))); 528 testProperty("signedDefault", "Ti,VsignedDefault", ATTRS(ATTR("T", "i"), ATTR("V", "signedDefault"))); 529 testProperty("structDefault", "T{YorkshireTeaStruct=ic},VstructDefault", ATTRS(ATTR("T", "{YorkshireTeaStruct=ic}"), 530 ATTR("V", "structDefault"))); 531 testProperty("typedefDefault", "T{YorkshireTeaStruct=ic},VtypedefDefault", ATTRS(ATTR("T", "{YorkshireTeaStruct=ic}"), 532 ATTR("V", "typedefDefault"))); 533 testProperty("unionDefault", "T(MoneyUnion=fd),VunionDefault", ATTRS(ATTR("T", "(MoneyUnion=fd)"), 534 ATTR("V", "unionDefault"))); 535 testProperty("unsignedDefault", "TI,VunsignedDefault", ATTRS(ATTR("T", "I"), ATTR("V", "unsignedDefault"))); 536 testProperty("functionPointerDefault", "T^?,VfunctionPointerDefault", ATTRS(ATTR("T", "^?"), ATTR("V", "functionPointerDefault"))); 537 testProperty("intPointer", "T^i,VintPointer", ATTRS(ATTR("T", "^i"), ATTR("V", "intPointer"))); 538 testProperty("voidPointerDefault", "T^v,VvoidPointerDefault", ATTRS(ATTR("T", "^v"), ATTR("V", "voidPointerDefault"))); 539 testProperty("intSetterGetter", "Ti,GintGetFoo,SintSetFoo:,VintSetterGetter", ATTRS(ATTR("T", "i"), 540 ATTR("G", "intGetFoo"), 541 ATTR("S", "intSetFoo:"), 542 ATTR("V", "intSetterGetter"))); 543 testProperty("intReadonly", "Ti,R,VintReadonly", ATTRS(ATTR("T", "i"), 544 ATTR("R", ""), 545 ATTR("V", "intReadonly"))); 546 testProperty("intReadonlyGetter", "Ti,R,GisIntReadOnlyGetter,VintReadonlyGetter", ATTRS(ATTR("T", "i"), 547 ATTR("R", ""), 548 ATTR("G", "isIntReadOnlyGetter"), 549 ATTR("V", "intReadonlyGetter"))); 550 testProperty("intReadwrite", "Ti,VintReadwrite", ATTRS(ATTR("T", "i"), ATTR("V", "intReadwrite"))); 551 testProperty("intAssign", "Ti,VintAssign", ATTRS(ATTR("T", "i"), ATTR("V", "intAssign"))); 552 testProperty("idDefault", "T@,VidDefault", ATTRS(ATTR("T", "@"), 553 ATTR("V", "idDefault"))); 554 testProperty("idRetain", "T@,&,VidRetain", ATTRS(ATTR("T", "@"), 555 ATTR("&", ""), 556 ATTR("V", "idRetain"))); 557 testProperty("idCopy", "T@,C,VidCopy", ATTRS(ATTR("T", "@"), 558 ATTR("C", ""), 559 ATTR("V", "idCopy"))); 560 testProperty("idWeak", "T@,W,VidWeak", ATTRS(ATTR("T", "@"), 561 ATTR("W", ""), 562 ATTR("V", "idWeak"))); 563 testProperty("idStrong", "T@,&,VidStrong", ATTRS(ATTR("T", "@"), 564 ATTR("&", ""), 565 ATTR("V", "idStrong"))); 566 testProperty("intNonatomic", "Ti,N,VintNonatomic", ATTRS(ATTR("T", "i"), 567 ATTR("N", ""), 568 ATTR("V", "intNonatomic"))); 569 testProperty("idReadonlyCopyNonatomic", "T@,R,C,N,VidReadonlyCopyNonatomic", ATTRS(ATTR("T", "@"), 570 ATTR("C", ""), 571 ATTR("R", ""), 572 ATTR("N", ""), 573 ATTR("V", "idReadonlyCopyNonatomic"))); 574 testProperty("idReadonlyRetainNonatomic", "T@,R,&,N,VidReadonlyRetainNonatomic", ATTRS(ATTR("T", "@"), 575 ATTR("R", ""), 576 ATTR("&", ""), 577 ATTR("N", ""), 578 ATTR("V", "idReadonlyRetainNonatomic"))); 579 /** 580 * The weak attribute was not present for earlier versions of clang, so we test 581 * for all variants that the compiler may produce. 582 */ 583 if (!testProperty_alt("idReadonlyWeakNonatomic", "T@,R," WEAK_STR "N,VidReadonlyWeakNonatomic", ATTRS(ATTR("T", "@"), 584 ATTR("R", ""), 585 ATTR("N", ""), 586 ATTR("V", "idReadonlyWeakNonatomic")), NO)) 587 { 588 testProperty("idReadonlyWeakNonatomic", "T@,R," WEAK_STR "N,VidReadonlyWeakNonatomic", ATTRS(ATTR("T", "@"), 589 ATTR("R", ""), 590 WEAK_ATTR 591 ATTR("N", ""), 592 ATTR("V", "idReadonlyWeakNonatomic"))); 593 } 594 testProperty("idOther", "T@,&,V_idOther", ATTRS(ATTR("T", "@"), ATTR("&", ""), ATTR("V", "_idOther"))); 595 testProperty("idDynamic", "T@,&,D", ATTRS(ATTR("T", "@"), ATTR("&", ""), ATTR("D", ""))); 596 testProperty("idDynamicGetterSetter", "T@,&,D,N,GdynamicGetterSetter,SsetDynamicGetterSetter:", ATTRS(ATTR("T", "@"), 597 ATTR("&", ""), 598 ATTR("D", ""), 599 ATTR("N", ""), 600 ATTR("G", "dynamicGetterSetter"), 601 ATTR("S", "setDynamicGetterSetter:"))); 602 603 Protocol *testProto = objc_getProtocol("ProtocolTest"); 604 testPropertyForProtocol(testProto, "atomicBoolDefault", "TAB", ATTRS(ATTR("T", "AB"))); 605 testPropertyForProtocol(testProto, "charDefault", "Tc", ATTRS(ATTR("T", "c"))); 606 testPropertyForProtocol(testProto, "doubleDefault", "Td", ATTRS(ATTR("T", "d"))); 607 testPropertyForProtocol(testProto, "enumDefault", "Ti", ATTRS(ATTR("T", "i"))); 608 testPropertyForProtocol(testProto, "floatDefault", "Tf", ATTRS(ATTR("T", "f"))); 609 testPropertyForProtocol(testProto, "intDefault", "Ti", ATTRS(ATTR("T", "i"))); 610 if (sizeof(long) == 4) 611 { 612 testPropertyForProtocol(testProto, "longDefault", "Tl", ATTRS(ATTR("T", "l"))); 613 } 614 else 615 { 616 testPropertyForProtocol(testProto, "longDefault", "Tq", ATTRS(ATTR("T", "q"))); 617 } 618 testPropertyForProtocol(testProto, "shortDefault", "Ts", ATTRS(ATTR("T", "s"))); 619 testPropertyForProtocol(testProto, "signedDefault", "Ti", ATTRS(ATTR("T", "i"))); 620 testPropertyForProtocol(testProto, "structDefault", "T{YorkshireTeaStruct=ic}", ATTRS(ATTR("T", "{YorkshireTeaStruct=ic}"))); 621 testPropertyForProtocol(testProto, "typedefDefault", "T{YorkshireTeaStruct=ic}", ATTRS(ATTR("T", "{YorkshireTeaStruct=ic}"))); 622 testPropertyForProtocol(testProto, "unionDefault", "T(MoneyUnion=fd)", ATTRS(ATTR("T", "(MoneyUnion=fd)"))); 623 testPropertyForProtocol(testProto, "unsignedDefault", "TI", ATTRS(ATTR("T", "I"))); 624 testPropertyForProtocol(testProto, "functionPointerDefault", "T^?", ATTRS(ATTR("T", "^?"))); 625 testPropertyForProtocol(testProto, "intPointer", "T^i", ATTRS(ATTR("T", "^i"))); 626 testPropertyForProtocol(testProto, "voidPointerDefault", "T^v", ATTRS(ATTR("T", "^v"))); 627 testPropertyForProtocol(testProto, "intSetterGetter", "Ti,GintGetFoo,SintSetFoo:", ATTRS(ATTR("T", "i"), 628 ATTR("G", "intGetFoo"), 629 ATTR("S", "intSetFoo:"))); 630 testPropertyForProtocol(testProto, "intReadonly", "Ti,R", ATTRS(ATTR("T", "i"), 631 ATTR("R", ""))); 632 testPropertyForProtocol(testProto, "intReadonlyGetter", "Ti,R,GisIntReadOnlyGetter", ATTRS(ATTR("T", "i"), 633 ATTR("R", ""), 634 ATTR("G", "isIntReadOnlyGetter"))); 635 testPropertyForProtocol(testProto, "intReadwrite", "Ti", ATTRS(ATTR("T", "i"))); 636 testPropertyForProtocol(testProto, "intAssign", "Ti", ATTRS(ATTR("T", "i"))); 637 testPropertyForProtocol(testProto, "idDefault", "T@", ATTRS(ATTR("T", "@"))); 638 testPropertyForProtocol(testProto, "idRetain", "T@,&", ATTRS(ATTR("T", "@"), 639 ATTR("&", ""))); 640 testPropertyForProtocol(testProto, "idCopy", "T@,C", ATTRS(ATTR("T", "@"), 641 ATTR("C", ""))); 642 testPropertyForProtocol(testProto, "idWeak", "T@,W", ATTRS(ATTR("T", "@"), 643 ATTR("W", ""))); 644 testPropertyForProtocol(testProto, "idStrong", "T@,&", ATTRS(ATTR("T", "@"), 645 ATTR("&", ""))); 646 testPropertyForProtocol(testProto, "intNonatomic", "Ti,N", ATTRS(ATTR("T", "i"), 647 ATTR("N", ""))); 648 testPropertyForProtocol(testProto, "idReadonlyCopyNonatomic", "T@,R,C,N", ATTRS(ATTR("T", "@"), 649 ATTR("R", ""), 650 ATTR("C", ""), 651 ATTR("N", ""))); 652 testPropertyForProtocol(testProto, "idReadonlyRetainNonatomic", "T@,R,&,N", ATTRS(ATTR("T", "@"), 653 ATTR("R", ""), 654 ATTR("&", ""), 655 ATTR("N", ""))); 656 /* 657 * Again, different clang versions emit slightly different property declarations. 658 */ 659 if (!testPropertyForProtocol_alt(testProto, "idReadonlyWeakNonatomic", "T@,R," WEAK_STR "N", ATTRS(ATTR("T", "@"), 660 ATTR("R", ""), 661 WEAK_ATTR 662 ATTR("N", "")), NO)) 663 { 664 665 testPropertyForProtocol(testProto, "idReadonlyWeakNonatomic", "T@,R,N", ATTRS(ATTR("T", "@"), 666 ATTR("R", ""), 667 ATTR("N", ""))); 668 } 669 testPropertyForProtocol(testProto, "idOther", "T@,&", ATTRS(ATTR("T", "@"), ATTR("&", ""))); 670 testPropertyForProtocol(testProto, "idDynamic", "T@,&", ATTRS(ATTR("T", "@"), ATTR("&", ""))); 671 testPropertyForProtocol(testProto, "idDynamicGetterSetter", "T@,&,N,GdynamicGetterSetter,SsetDynamicGetterSetter:", ATTRS(ATTR("T", "@"), 672 ATTR("&", ""), 673 ATTR("N", ""), 674 ATTR("G", "dynamicGetterSetter"), 675 ATTR("S", "setDynamicGetterSetter:"))); 676 677 testAddProperty(); 678 679 Protocol *testAddProtocol = objc_allocateProtocol("TestAddProtocol"); 680 assert(0 != testAddProtocol); 681 testAddPropertyForProtocol(testAddProtocol); 682 683 Class testClass = objc_getClass("PropertyTest"); 684 objc_property_attribute_t intDefault2Attrs[] = { ATTR("T", "i"), ATTR("V", "intDefault") }; 685 assert(class_addProperty(testClass, "intDefault2", intDefault2Attrs, 2)); 686 assert(class_addMethod(testClass, @selector(intDefault2), (IMP)intDefault2Getter, "i@:")); 687 assert(class_addMethod(testClass, @selector(setIntDefault2:), (IMP)intDefault2Setter, "v@:i")); 688 testPropertyForClass(testClass, "intDefault2", "Ti,VintDefault", ATTRS(ATTR("T", "i"), ATTR("V", "intDefault"))); 689 690 objc_property_attribute_t structDefault2Attrs[] = { ATTR("T", "{YorkshireTeaStruct=ic}"), 691 ATTR("V", "structDefault") }; 692 assert(class_addProperty(testClass, "structDefault2", structDefault2Attrs, 2)); 693 assert(class_addMethod(testClass, @selector(structDefault2), (IMP)structDefault2Getter, "{YorkshireTeaStruct=ic}@:")); 694 assert(class_addMethod(testClass, @selector(setStructDefault2:), (IMP)structDefault2Setter, "v@:{YorkshireTeaStruct=ic}")); 695 testPropertyForClass(testClass, "structDefault2", "T{YorkshireTeaStruct=ic},VstructDefault", ATTRS(ATTR("T", "{YorkshireTeaStruct=ic}"), 696 ATTR("V", "structDefault"))); 697 698 PropertyTest* t = class_createInstance(testClass, 0); 699 assert(t != nil); 700 object_setClass(t, testClass); 701 t.intDefault = 2; 702 assert(t.intDefault == 2); 703 [t setIntDefault2:3]; 704 assert((int)[t intDefault2] == 3); 705 assert(t.intDefault == 3); 706 707 struct YorkshireTeaStruct struct1 = { 2, 'A' }; 708 t.structDefault = struct1; 709 struct YorkshireTeaStruct readStruct = t.structDefault; 710 assert(memcmp(&struct1, &readStruct, sizeof(struct1)) == 0); 711 struct YorkshireTeaStruct struct2 = { 3, 'B' }; 712 [t setStructDefault2:struct2]; 713 struct YorkshireTeaStruct readStruct2 = [t structDefault2]; 714 assert(memcmp(&struct2, &readStruct2, sizeof(struct2)) == 0); 715 readStruct = t.structDefault; 716 assert(memcmp(&struct2, &readStruct, sizeof(struct2)) == 0); 717 718 objc_property_attribute_t idRetainAttrs[] = { ATTR("T", "@"), 719 ATTR("&", ""), 720 ATTR("V", "_idOther") }; 721 class_replaceProperty(testClass, "idRetain", idRetainAttrs, 3); 722 testPropertyForClass(testClass, "idRetain", "T@,&,V_idOther", ATTRS(ATTR("T", "@"), 723 ATTR("&", ""), 724 ATTR("V", "_idOther"))); 725 id testValue = [Test new]; 726 t.idRetain = testValue; 727 assert(t->idRetain == testValue); 728 assert(t->_idOther == nil); 729 730 Method idRetainSetter = class_getInstanceMethod(testClass, @selector(setIdRetain:)); 731 Method idOtherSetter = class_getInstanceMethod(testClass, @selector(setIdOther:)); 732 method_setImplementation(idRetainSetter, method_getImplementation(idOtherSetter)); 733 idRetainSetter = class_getInstanceMethod(testClass, @selector(setIdRetain:)); 734 735 id testValue2 = [Test new]; 736 t.idRetain = testValue2; 737 assert(t->idRetain == testValue); 738 assert(t->_idOther == testValue2); 739 return 0; 740} 741