category.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // TEST_CFLAGS -Wl,-no_objc_category_merging
  2. #include "test.h"
  3. #include "testroot.i"
  4. #include <string.h>
  5. #include <objc/runtime.h>
  6. #if __LP64__
  7. # define PTR " .quad "
  8. #else
  9. # define PTR " .long "
  10. #endif
  11. static int state = 0;
  12. @interface Super : TestRoot @end
  13. @implementation Super
  14. -(void)instancemethod { fail("-instancemethod not overridden by category"); }
  15. +(void)method { fail("+method not overridden by category"); }
  16. @end
  17. @interface Super (Category) @end
  18. @implementation Super (Category)
  19. +(void)method {
  20. testprintf("in [Super(Category) method]\n");
  21. testassert(self == [Super class]);
  22. testassert(state == 0);
  23. state = 1;
  24. }
  25. -(void)instancemethod {
  26. testprintf("in [Super(Category) instancemethod]\n");
  27. testassert(object_getClass(self) == [Super class]);
  28. testassert(state == 1);
  29. state = 2;
  30. }
  31. @end
  32. @interface Super (PropertyCategory)
  33. @property int i;
  34. @property(class) int i;
  35. @end
  36. @implementation Super (PropertyCategory)
  37. - (int)i { return 0; }
  38. - (void)setI:(int)value { (void)value; }
  39. + (int)i { return 0; }
  40. + (void)setI:(int)value { (void)value; }
  41. @end
  42. // rdar://5086110 memory smasher in category with class method and property
  43. @interface Super (r5086110)
  44. @property int property5086110;
  45. @end
  46. @implementation Super (r5086110)
  47. +(void)method5086110 {
  48. fail("method method5086110 called!");
  49. }
  50. - (int)property5086110 { fail("property5086110 called!"); return 0; }
  51. - (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
  52. @end
  53. // rdar://25605427 incorrect handling of class properties in 10.11 and earlier
  54. @interface Super25605427 : TestRoot
  55. @property(class, readonly) int i;
  56. @end
  57. @implementation Super25605427
  58. +(int)i { return 0; }
  59. @end
  60. @interface Super25605427 (r25605427a)
  61. @property(readonly) int r25605427a1;
  62. @end
  63. @implementation Super25605427 (r25605427a)
  64. -(int)r25605427a1 { return 0; }
  65. +(int)r25605427a2 { return 0; }
  66. @end
  67. @interface Super25605427 (r25605427b)
  68. @property(readonly) int r25605427b1;
  69. @end
  70. @implementation Super25605427 (r25605427b)
  71. -(int)r25605427b1 { return 0; }
  72. +(int)r25605427b2 { return 0; }
  73. @end
  74. @interface Super25605427 (r25605427c)
  75. @property(readonly) int r25605427c1;
  76. @end
  77. @implementation Super25605427 (r25605427c)
  78. -(int)r25605427c1 { return 0; }
  79. +(int)r25605427c2 { return 0; }
  80. @end
  81. @interface Super25605427 (r25605427d)
  82. @property(readonly) int r25605427d1;
  83. @end
  84. @implementation Super25605427 (r25605427d)
  85. -(int)r25605427d1 { return 0; }
  86. +(int)r25605427d2 { return 0; }
  87. @end
  88. @interface PropertyClass : Super {
  89. int q;
  90. }
  91. @property(readonly) int q;
  92. @end
  93. @implementation PropertyClass
  94. @synthesize q;
  95. @end
  96. @interface PropertyClass (PropertyCategory)
  97. @property int q;
  98. @end
  99. @implementation PropertyClass (PropertyCategory)
  100. @dynamic q;
  101. @end
  102. // Manually build a category that goes in __objc_catlist2.
  103. #if __has_feature(ptrauth_calls)
  104. #define SIGNED_CATEGORY_IMP "@AUTH(ia,0,addr)"
  105. #else
  106. #define SIGNED_CATEGORY_IMP
  107. #endif
  108. asm(
  109. " .section __DATA,__objc_const \n"
  110. "L_catlist2CategoryName: \n"
  111. " .asciz \"Category_catlist2\" \n"
  112. "L_catlist2MethodString: \n"
  113. " .asciz \"catlist2Method\" \n"
  114. "L_catlist2MethodTypes: \n"
  115. " .asciz \"i16@0:8\" \n"
  116. " .p2align 3 \n"
  117. "l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2: \n"
  118. " .long 24 \n"
  119. " .long 1 \n"
  120. " "PTR" L_catlist2MethodString \n"
  121. " "PTR" L_catlist2MethodTypes \n"
  122. " "PTR" _catlist2MethodImplementation"SIGNED_CATEGORY_IMP" \n"
  123. " .p2align 3 \n"
  124. "l_OBJC_$_CATEGORY_Super_$_Category_catlist2: \n"
  125. " "PTR" L_catlist2CategoryName \n"
  126. " "PTR" _OBJC_CLASS_$_Super \n"
  127. " "PTR" l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2 \n"
  128. " "PTR" 0 \n"
  129. " "PTR" 0 \n"
  130. " "PTR" 0 \n"
  131. " "PTR" 0 \n"
  132. " .long 64 \n"
  133. " .space 4 \n"
  134. " .section __DATA,__objc_catlist2 \n"
  135. " .p2align 3 \n"
  136. " "PTR" l_OBJC_$_CATEGORY_Super_$_Category_catlist2 \n"
  137. " .text \n"
  138. );
  139. @interface Super (Category_catlist2)
  140. - (int)catlist2Method;
  141. @end
  142. EXTERN_C int catlist2MethodImplementation(id self __unused, SEL _cmd __unused) {
  143. return 0;
  144. }
  145. int main()
  146. {
  147. {
  148. // rdar://25605427 bugs in 10.11 and earlier when metaclass
  149. // has a property and category has metaclass additions.
  150. // Memory smasher in buildPropertyList (caught by guard malloc)
  151. Class cls = [Super25605427 class];
  152. // Incorrect attachment of instance properties from category to metacls
  153. testassert(class_getProperty(cls, "r25605427d1"));
  154. testassert(! class_getProperty(object_getClass(cls), "r25605427d1"));
  155. }
  156. // methods introduced by category
  157. state = 0;
  158. [Super method];
  159. [[Super new] instancemethod];
  160. testassert(state == 2);
  161. // property introduced by category
  162. objc_property_t p = class_getProperty([Super class], "i");
  163. testassert(p);
  164. testassert(0 == strcmp(property_getName(p), "i"));
  165. testassert(property_getAttributes(p));
  166. objc_property_t p2 = class_getProperty(object_getClass([Super class]), "i");
  167. testassert(p2);
  168. testassert(p != p2);
  169. testassert(0 == strcmp(property_getName(p2), "i"));
  170. testassert(property_getAttributes(p2));
  171. // methods introduced by category's property
  172. Method m;
  173. m = class_getInstanceMethod([Super class], @selector(i));
  174. testassert(m);
  175. m = class_getInstanceMethod([Super class], @selector(setI:));
  176. testassert(m);
  177. m = class_getClassMethod([Super class], @selector(i));
  178. testassert(m);
  179. m = class_getClassMethod([Super class], @selector(setI:));
  180. testassert(m);
  181. // class's property shadowed by category's property
  182. objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
  183. testassert(plist);
  184. testassert(plist[0]);
  185. testassert(0 == strcmp(property_getName(plist[0]), "q"));
  186. testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D"));
  187. testassert(plist[1]);
  188. testassert(0 == strcmp(property_getName(plist[1]), "q"));
  189. testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq"));
  190. testassert(!plist[2]);
  191. free(plist);
  192. // method introduced by category in catlist2
  193. testassert([[Super new] catlist2Method] == 0);
  194. succeed(__FILE__);
  195. }