ARCLayouts.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Note that test ARCLayoutsWithoutWeak uses the same files
  2. // with different build options.
  3. /*
  4. TEST_CONFIG MEM=arc
  5. TEST_BUILD
  6. mkdir -p $T{OBJDIR}
  7. $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRCBase.m -o $T{OBJDIR}/MRCBase.o
  8. $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRCARC.m -o $T{OBJDIR}/MRCARC.o
  9. $C{COMPILE_NOLINK} -c $DIR/ARCBase.m -o $T{OBJDIR}/ARCBase.o
  10. $C{COMPILE_NOLINK} -c $DIR/ARCMRC.m -o $T{OBJDIR}/ARCMRC.o
  11. $C{COMPILE} '-DNAME=\"ARCLayouts.m\"' -fobjc-arc $DIR/ARCLayouts.m -x none $T{OBJDIR}/MRCBase.o $T{OBJDIR}/MRCARC.o $T{OBJDIR}/ARCBase.o $T{OBJDIR}/ARCMRC.o -framework Foundation -o ARCLayouts.exe
  12. END
  13. */
  14. #include "test.h"
  15. #import <stdio.h>
  16. #import <Foundation/Foundation.h>
  17. #import <objc/runtime.h>
  18. #import "ARCMRC.h"
  19. #import "MRCARC.h"
  20. @interface NSObject (Layouts)
  21. + (const char *)strongLayout;
  22. + (const char *)weakLayout;
  23. @end
  24. void printlayout(const char *name, const uint8_t *layout)
  25. {
  26. if (!testverbose()) return;
  27. testprintf("%s: ", name);
  28. // these use fprintf() to avoid repeated VERBOSE: in the middle of the line
  29. if (!layout) {
  30. fprintf(stderr, "NULL\n");
  31. return;
  32. }
  33. const uint8_t *c;
  34. for (c = layout; *c; c++) {
  35. fprintf(stderr, "%02x ", *c);
  36. }
  37. fprintf(stderr, "00\n");
  38. }
  39. @implementation NSObject (Layouts)
  40. + (const char *)strongLayout {
  41. const uint8_t *layout = class_getIvarLayout(self);
  42. printlayout("strong", layout);
  43. return (const char *)layout;
  44. }
  45. + (const char *)weakLayout {
  46. const uint8_t *weakLayout = class_getWeakIvarLayout(self);
  47. printlayout("weak", weakLayout);
  48. return (const char *)weakLayout;
  49. }
  50. + (Ivar)instanceVariable:(const char *)name {
  51. return class_getInstanceVariable(self, name);
  52. }
  53. @end
  54. void checkMM(Class cls, const char *ivarName,
  55. objc_ivar_memory_management_t mmExpected)
  56. {
  57. Ivar ivar = [cls instanceVariable:ivarName];
  58. objc_ivar_memory_management_t mm = _class_getIvarMemoryManagement(cls,ivar);
  59. testprintf("%s->%s want %d, got %d\n",
  60. class_getName(cls), ivarName, mmExpected, mm);
  61. testassert(mmExpected == mm);
  62. }
  63. int main (int argc __unused, const char * argv[] __unused) {
  64. testprintf("ARCMRC\n");
  65. testassert(strcmp([ARCMRC strongLayout], "\x01") == 0);
  66. testassert([ARCMRC weakLayout] == NULL);
  67. // Verify that ARCBase->misalign and MRCBase->alignment did their thing.
  68. testassert(ivar_getOffset(class_getInstanceVariable([ARCBase class], "misalign2")) & 1);
  69. testassert(ivar_getOffset(class_getInstanceVariable([MRCBase class], "alignment")) > (ptrdiff_t)sizeof(void*));
  70. testprintf("ARCMisalign\n");
  71. testassert([ARCMisalign strongLayout] == NULL);
  72. testassert([ARCMisalign weakLayout] == NULL);
  73. testprintf("ARCBase\n");
  74. if (strcmp([ARCBase strongLayout], "\x11\x30") == 0) {
  75. testwarn("1130 layout is a compiler flaw but doesn't fail");
  76. } else {
  77. testassert(strcmp([ARCBase strongLayout], "\x11") == 0);
  78. }
  79. testassert(strcmp([ARCBase weakLayout], "\x31") == 0);
  80. testprintf("MRCARC\n");
  81. testassert([MRCARC strongLayout] == NULL);
  82. testassert([MRCARC weakLayout] == NULL);
  83. testprintf("MRCBase\n");
  84. // MRC marks __weak only.
  85. testassert([MRCBase strongLayout] == NULL);
  86. if (supportsMRCWeak) {
  87. testassert(strcmp([MRCBase weakLayout], "\x71") == 0);
  88. } else {
  89. testassert([MRCBase weakLayout] == nil);
  90. }
  91. // now check consistency between dynamic accessors and KVC, etc.
  92. ARCMRC *am = [ARCMRC new];
  93. MRCARC *ma = [MRCARC new];
  94. NSString *amValue = [[NSString alloc] initWithFormat:@"%s %p", "ARCMRC", am];
  95. NSString *amValue2 = [[NSString alloc] initWithFormat:@"%s %p", "ARCMRC", am];
  96. NSString *maValue = [[NSString alloc] initWithFormat:@"%s %p", "MRCARC", ma];
  97. NSString *maValue2 = [[NSString alloc] initWithFormat:@"%s %p", "MRCARC", ma];
  98. am.number = M_PI;
  99. object_setIvar(am, [ARCMRC instanceVariable:"object"], amValue);
  100. testassert(CFGetRetainCount((__bridge CFTypeRef)amValue) == 1);
  101. testassert(am.object == amValue);
  102. object_setIvarWithStrongDefault(am, [ARCMRC instanceVariable:"object"], amValue2);
  103. testassert(CFGetRetainCount((__bridge CFTypeRef)amValue2) == 2);
  104. testassert(am.object == amValue2);
  105. am.pointer = @selector(ARCMRC);
  106. object_setIvar(am, [ARCMRC instanceVariable:"delegate"], ma);
  107. testassert(CFGetRetainCount((__bridge CFTypeRef)ma) == 1);
  108. testassert(am.delegate == ma);
  109. object_setIvarWithStrongDefault(am, [ARCMRC instanceVariable:"delegate"], ma);
  110. testassert(CFGetRetainCount((__bridge CFTypeRef)ma) == 1);
  111. testassert(am.delegate == ma);
  112. ma.number = M_E;
  113. object_setIvar(ma, [MRCARC instanceVariable:"object"], maValue);
  114. testassert(CFGetRetainCount((__bridge CFTypeRef)maValue) == 2);
  115. @autoreleasepool {
  116. testassert(ma.object == maValue);
  117. }
  118. object_setIvarWithStrongDefault(ma, [MRCARC instanceVariable:"object"], maValue2);
  119. testassert(CFGetRetainCount((__bridge CFTypeRef)maValue2) == 2);
  120. @autoreleasepool {
  121. testassert(ma.object == maValue2);
  122. }
  123. ma.pointer = @selector(MRCARC);
  124. ma.delegate = am;
  125. object_setIvar(ma, [MRCARC instanceVariable:"delegate"], am);
  126. testassert(CFGetRetainCount((__bridge CFTypeRef)am) == 1);
  127. @autoreleasepool {
  128. testassert(ma.delegate == am);
  129. }
  130. object_setIvarWithStrongDefault(ma, [MRCARC instanceVariable:"delegate"], am);
  131. testassert(CFGetRetainCount((__bridge CFTypeRef)am) == 1);
  132. @autoreleasepool {
  133. testassert(ma.delegate == am);
  134. }
  135. // Verify that object_copy() handles ARC variables correctly.
  136. MRCARC *ma2 = docopy(ma);
  137. testassert(ma2);
  138. testassert(ma2 != ma);
  139. testassert(CFGetRetainCount((__bridge CFTypeRef)maValue2) == 3);
  140. testassert(CFGetRetainCount((__bridge CFTypeRef)am) == 1);
  141. testassert(ma2.number == ma.number);
  142. testassert(ma2.object == ma.object);
  143. @autoreleasepool {
  144. testassert(ma2.delegate == ma.delegate);
  145. }
  146. testassert(ma2.pointer == ma.pointer);
  147. // Test _class_getIvarMemoryManagement() SPI
  148. objc_ivar_memory_management_t memoryMRCWeak =
  149. supportsMRCWeak ? objc_ivar_memoryWeak : objc_ivar_memoryUnknown;
  150. checkMM([ARCMRC class], "number", objc_ivar_memoryUnknown);
  151. checkMM([ARCMRC class], "object", objc_ivar_memoryUnknown);
  152. checkMM([ARCMRC class], "pointer", objc_ivar_memoryUnknown);
  153. checkMM([ARCMRC class], "delegate", memoryMRCWeak);
  154. checkMM([ARCMRC class], "dataSource", objc_ivar_memoryStrong);
  155. checkMM([MRCARC class], "number", objc_ivar_memoryUnretained);
  156. checkMM([MRCARC class], "object", objc_ivar_memoryStrong);
  157. checkMM([MRCARC class], "pointer", objc_ivar_memoryUnretained);
  158. checkMM([MRCARC class], "delegate", objc_ivar_memoryWeak);
  159. checkMM([MRCARC class], "dataSource", objc_ivar_memoryUnknown);
  160. checkMM([ARCBase class], "number", objc_ivar_memoryUnretained);
  161. checkMM([ARCBase class], "object", objc_ivar_memoryStrong);
  162. checkMM([ARCBase class], "pointer", objc_ivar_memoryUnretained);
  163. checkMM([ARCBase class], "delegate", objc_ivar_memoryWeak);
  164. checkMM([MRCBase class], "number", objc_ivar_memoryUnknown);
  165. checkMM([MRCBase class], "object", objc_ivar_memoryUnknown);
  166. checkMM([MRCBase class], "pointer", objc_ivar_memoryUnknown);
  167. checkMM([MRCBase class], "delegate", memoryMRCWeak);
  168. succeed(NAME);
  169. return 0;
  170. }