1 // TEST_CFLAGS -Wl,-no_objc_category_merging
6 #include <objc/runtime.h>
11 # define PTR " .long "
16 @interface Super : TestRoot @end
18 -(void)instancemethod { fail("-instancemethod not overridden by category"); }
19 +(void)method { fail("+method not overridden by category"); }
22 @interface Super (Category) @end
23 @implementation Super (Category)
25 testprintf("in [Super(Category) method]\n");
26 testassert(self == [Super class]);
27 testassert(state == 0);
30 -(void)instancemethod {
31 testprintf("in [Super(Category) instancemethod]\n");
32 testassert(object_getClass(self) == [Super class]);
33 testassert(state == 1);
38 @interface Super (PropertyCategory)
40 @property(class) int i;
42 @implementation Super (PropertyCategory)
43 - (int)i { return 0; }
44 - (void)setI:(int)value { (void)value; }
45 + (int)i { return 0; }
46 + (void)setI:(int)value { (void)value; }
49 // rdar://5086110 memory smasher in category with class method and property
50 @interface Super (r5086110)
51 @property int property5086110;
53 @implementation Super (r5086110)
54 +(void)method5086110 {
55 fail("method method5086110 called!");
57 - (int)property5086110 { fail("property5086110 called!"); return 0; }
58 - (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
61 // rdar://25605427 incorrect handling of class properties in 10.11 and earlier
62 @interface Super25605427 : TestRoot
63 @property(class, readonly) int i;
65 @implementation Super25605427
69 @interface Super25605427 (r25605427a)
70 @property(readonly) int r25605427a1;
72 @implementation Super25605427 (r25605427a)
73 -(int)r25605427a1 { return 0; }
74 +(int)r25605427a2 { return 0; }
77 @interface Super25605427 (r25605427b)
78 @property(readonly) int r25605427b1;
80 @implementation Super25605427 (r25605427b)
81 -(int)r25605427b1 { return 0; }
82 +(int)r25605427b2 { return 0; }
85 @interface Super25605427 (r25605427c)
86 @property(readonly) int r25605427c1;
88 @implementation Super25605427 (r25605427c)
89 -(int)r25605427c1 { return 0; }
90 +(int)r25605427c2 { return 0; }
93 @interface Super25605427 (r25605427d)
94 @property(readonly) int r25605427d1;
96 @implementation Super25605427 (r25605427d)
97 -(int)r25605427d1 { return 0; }
98 +(int)r25605427d2 { return 0; }
102 @interface PropertyClass : Super {
105 @property(readonly) int q;
107 @implementation PropertyClass
111 @interface PropertyClass (PropertyCategory)
114 @implementation PropertyClass (PropertyCategory)
119 // Manually build a category that goes in __objc_catlist2.
120 #if __has_feature(ptrauth_calls)
121 #define SIGNED_CATEGORY_IMP "@AUTH(ia,0,addr)"
123 #define SIGNED_CATEGORY_IMP
126 " .section __DATA,__objc_const \n"
127 "L_catlist2CategoryName: \n"
128 " .asciz \"Category_catlist2\" \n"
129 "L_catlist2MethodString: \n"
130 " .asciz \"catlist2Method\" \n"
131 "L_catlist2MethodTypes: \n"
132 " .asciz \"i16@0:8\" \n"
135 "l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2: \n"
138 " "PTR" L_catlist2MethodString \n"
139 " "PTR" L_catlist2MethodTypes \n"
140 " "PTR" _catlist2MethodImplementation"SIGNED_CATEGORY_IMP" \n"
143 "l_OBJC_$_CATEGORY_Super_$_Category_catlist2: \n"
144 " "PTR" L_catlist2CategoryName \n"
145 " "PTR" _OBJC_CLASS_$_Super \n"
146 " "PTR" l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2 \n"
154 " .section __DATA,__objc_catlist2 \n"
156 " "PTR" l_OBJC_$_CATEGORY_Super_$_Category_catlist2 \n"
161 @interface Super (Category_catlist2)
162 - (int)catlist2Method;
165 EXTERN_C int catlist2MethodImplementation(id self __unused, SEL _cmd __unused) {
173 // rdar://25605427 bugs in 10.11 and earlier when metaclass
174 // has a property and category has metaclass additions.
175 // Memory smasher in buildPropertyList (caught by guard malloc)
176 Class cls = [Super25605427 class];
177 // Incorrect attachment of instance properties from category to metacls
178 testassert(class_getProperty(cls, "r25605427d1"));
179 testassert(! class_getProperty(object_getClass(cls), "r25605427d1"));
182 // methods introduced by category
185 [[Super new] instancemethod];
186 testassert(state == 2);
188 // property introduced by category
189 objc_property_t p = class_getProperty([Super class], "i");
191 testassert(0 == strcmp(property_getName(p), "i"));
192 testassert(property_getAttributes(p));
194 objc_property_t p2 = class_getProperty(object_getClass([Super class]), "i");
197 testassert(0 == strcmp(property_getName(p2), "i"));
198 testassert(property_getAttributes(p2));
200 // methods introduced by category's property
202 m = class_getInstanceMethod([Super class], @selector(i));
204 m = class_getInstanceMethod([Super class], @selector(setI:));
207 m = class_getClassMethod([Super class], @selector(i));
209 m = class_getClassMethod([Super class], @selector(setI:));
212 // class's property shadowed by category's property
213 objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
215 testassert(plist[0]);
216 testassert(0 == strcmp(property_getName(plist[0]), "q"));
217 testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D"));
218 testassert(plist[1]);
219 testassert(0 == strcmp(property_getName(plist[1]), "q"));
220 testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq"));
221 testassert(!plist[2]);
224 // method introduced by category in catlist2
225 testassert([[Super new] catlist2Method] == 0);