]> git.saurik.com Git - apple/objc4.git/blame - test/category.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / category.m
CommitLineData
13ba007e
A
1// TEST_CFLAGS -Wl,-no_objc_category_merging
2
3#include "test.h"
4#include "testroot.i"
5#include <string.h>
6#include <objc/runtime.h>
7
1807f628
A
8#if __LP64__
9# define PTR " .quad "
10#else
11# define PTR " .long "
12#endif
13
13ba007e
A
14static int state = 0;
15
16@interface Super : TestRoot @end
17@implementation Super
18-(void)instancemethod { fail("-instancemethod not overridden by category"); }
19+(void)method { fail("+method not overridden by category"); }
20@end
21
22@interface Super (Category) @end
23@implementation Super (Category)
24+(void)method {
25 testprintf("in [Super(Category) method]\n");
26 testassert(self == [Super class]);
27 testassert(state == 0);
28 state = 1;
29}
30-(void)instancemethod {
31 testprintf("in [Super(Category) instancemethod]\n");
32 testassert(object_getClass(self) == [Super class]);
33 testassert(state == 1);
34 state = 2;
35}
36@end
37
38@interface Super (PropertyCategory)
39@property int i;
40@property(class) int i;
41@end
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; }
47@end
48
49// rdar://5086110 memory smasher in category with class method and property
50@interface Super (r5086110)
51@property int property5086110;
52@end
53@implementation Super (r5086110)
54+(void)method5086110 {
55 fail("method method5086110 called!");
56}
57- (int)property5086110 { fail("property5086110 called!"); return 0; }
58- (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
59@end
60
61// rdar://25605427 incorrect handling of class properties in 10.11 and earlier
62@interface Super25605427 : TestRoot
63@property(class, readonly) int i;
64@end
65@implementation Super25605427
66+(int)i { return 0; }
67@end
68
69@interface Super25605427 (r25605427a)
70@property(readonly) int r25605427a1;
71@end
72@implementation Super25605427 (r25605427a)
73-(int)r25605427a1 { return 0; }
74+(int)r25605427a2 { return 0; }
75@end
76
77@interface Super25605427 (r25605427b)
78@property(readonly) int r25605427b1;
79@end
80@implementation Super25605427 (r25605427b)
81-(int)r25605427b1 { return 0; }
82+(int)r25605427b2 { return 0; }
83@end
84
85@interface Super25605427 (r25605427c)
86@property(readonly) int r25605427c1;
87@end
88@implementation Super25605427 (r25605427c)
89-(int)r25605427c1 { return 0; }
90+(int)r25605427c2 { return 0; }
91@end
92
93@interface Super25605427 (r25605427d)
94@property(readonly) int r25605427d1;
95@end
96@implementation Super25605427 (r25605427d)
97-(int)r25605427d1 { return 0; }
98+(int)r25605427d2 { return 0; }
99@end
100
101
102@interface PropertyClass : Super {
103 int q;
104}
105@property(readonly) int q;
106@end
107@implementation PropertyClass
108@synthesize q;
109@end
110
111@interface PropertyClass (PropertyCategory)
112@property int q;
113@end
114@implementation PropertyClass (PropertyCategory)
115@dynamic q;
116@end
117
118
1807f628
A
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)"
122#else
123#define SIGNED_CATEGORY_IMP
124#endif
125asm(
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"
133
134" .p2align 3 \n"
135"l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2: \n"
136" .long 24 \n"
137" .long 1 \n"
34d5b5e8
A
138" " PTR " L_catlist2MethodString \n"
139" " PTR " L_catlist2MethodTypes \n"
140" " PTR " _catlist2MethodImplementation" SIGNED_CATEGORY_IMP" \n"
1807f628
A
141
142" .p2align 3 \n"
143"l_OBJC_$_CATEGORY_Super_$_Category_catlist2: \n"
34d5b5e8
A
144" " PTR " L_catlist2CategoryName \n"
145" " PTR " _OBJC_CLASS_$_Super \n"
146" " PTR " l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2 \n"
147" " PTR " 0 \n"
148" " PTR " 0 \n"
149" " PTR " 0 \n"
150" " PTR " 0 \n"
1807f628
A
151" .long 64 \n"
152" .space 4 \n"
153
154" .section __DATA,__objc_catlist2 \n"
155" .p2align 3 \n"
34d5b5e8 156" " PTR " l_OBJC_$_CATEGORY_Super_$_Category_catlist2 \n"
1807f628
A
157
158" .text \n"
159);
160
161@interface Super (Category_catlist2)
162- (int)catlist2Method;
163@end
164
165EXTERN_C int catlist2MethodImplementation(id self __unused, SEL _cmd __unused) {
166 return 0;
167}
168
169
13ba007e
A
170int main()
171{
172 {
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"));
180 }
181
182 // methods introduced by category
183 state = 0;
184 [Super method];
185 [[Super new] instancemethod];
186 testassert(state == 2);
187
188 // property introduced by category
189 objc_property_t p = class_getProperty([Super class], "i");
190 testassert(p);
191 testassert(0 == strcmp(property_getName(p), "i"));
192 testassert(property_getAttributes(p));
193
194 objc_property_t p2 = class_getProperty(object_getClass([Super class]), "i");
195 testassert(p2);
196 testassert(p != p2);
197 testassert(0 == strcmp(property_getName(p2), "i"));
198 testassert(property_getAttributes(p2));
199
200 // methods introduced by category's property
201 Method m;
202 m = class_getInstanceMethod([Super class], @selector(i));
203 testassert(m);
204 m = class_getInstanceMethod([Super class], @selector(setI:));
205 testassert(m);
206
207 m = class_getClassMethod([Super class], @selector(i));
208 testassert(m);
209 m = class_getClassMethod([Super class], @selector(setI:));
210 testassert(m);
211
212 // class's property shadowed by category's property
213 objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
214 testassert(plist);
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]);
222 free(plist);
223
1807f628
A
224 // method introduced by category in catlist2
225 testassert([[Super new] catlist2Method] == 0);
226
13ba007e
A
227 succeed(__FILE__);
228}
229