1 /* Test the Modern GNU Objective-C Runtime API.
3 This is test 'method', covering all functions starting with 'method'. */
6 /* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
7 /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
8 /* { dg-additional-options "-Wno-objc-root-class" } */
10 /* To get the modern GNU Objective-C Runtime API, you include
12 #include <objc/runtime.h>
17 @interface MyRootClass
24 @implementation MyRootClass
25 + alloc { return class_createInstance (self, 0); }
26 - init { return self; }
27 + initialize { return self; }
34 @protocol MySecondProtocol
35 - (id) setVariable: (id)value;
38 @interface MySubClass : MyRootClass <MyProtocol>
40 - (void) setVariable: (id)value;
45 @implementation MySubClass
46 - (void) setVariable: (id)value { variable_ivar = value; }
47 - (id) variable { return variable_ivar; }
48 - (id) constant { return nil; }
52 int main(int argc, void **args)
54 /* Functions are tested in alphabetical order. */
56 printf ("Testing method_copyArgumentType () ...\n");
58 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
59 @selector (setVariable:));
60 char *type = method_copyArgumentType (method, 2);
62 if (type == NULL || type[0] != '@')
66 printf ("Testing method_copyReturnType () ...\n");
68 Method method = class_getClassMethod (objc_getClass ("MyRootClass"),
70 char *type = method_copyReturnType (method);
72 /* Check that it returns an object. */
73 if (type == NULL || type[0] != '@')
77 printf ("Testing method_exchangeImplementations () ...\n");
79 Method method_a = class_getInstanceMethod (objc_getClass ("MySubClass"),
80 @selector (variable));
81 Method method_b = class_getInstanceMethod (objc_getClass ("MySubClass"),
82 @selector (constant));
83 MySubClass *object = [[MySubClass alloc] init];
85 /* Check that things work as expected before the swap. */
86 [object setVariable: object];
88 if ([object variable] != object || [object constant] != nil)
91 /* Swap the methods. */
92 method_exchangeImplementations (method_a, method_b);
94 /* Check that behavior has changed. */
95 if ([object variable] != nil || [object constant] != object)
98 /* Swap the methods again. */
99 method_exchangeImplementations (method_a, method_b);
101 /* Check that behavior is back to normal. */
102 if ([object variable] != object || [object constant] != nil)
106 printf ("Testing method_getArgumentType () ...\n");
108 Method method = class_getInstanceMethod (objc_getClass ("MyRootClass"),
112 method_getArgumentType (method, 1, type, 16);
114 /* Check the second argument (_cmd), which should be a SEL. */
119 printf ("Testing method_getDescription () ...\n");
121 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
122 @selector (variable));
123 struct objc_method_description *description = method_getDescription (method);
125 if (strcmp (sel_getName (description->name), "variable") != 0)
128 if (method_getDescription (NULL) != NULL)
132 printf ("Testing method_getImplementation () ...\n");
134 typedef void (*set_variable_function) (id receiver, SEL _cmd, id variable);
135 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
136 @selector (setVariable:));
137 set_variable_function imp;
138 MySubClass *object = [[MySubClass alloc] init];
140 imp = (set_variable_function)(method_getImplementation (method));
142 (*imp)(object, @selector (setVariable:), object);
144 if ([object variable] != object)
148 printf ("Testing method_getName () ...\n");
150 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
151 @selector (setVariable:));
152 if (strcmp (sel_getName (method_getName (method)), "setVariable:") != 0)
156 printf ("Testing method_getNumberOfArguments () ...\n");
158 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
159 @selector (setVariable:));
160 if (method_getNumberOfArguments (method) != 3)
163 method = class_getInstanceMethod (objc_getClass ("MySubClass"),
164 @selector (variable));
165 if (method_getNumberOfArguments (method) != 2)
169 printf ("Testing method_getTypeEncoding () ...\n");
171 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
172 @selector (setVariable:));
173 const char *types = method_getTypeEncoding (method);
175 /* Check that method type string starts with 'v' (void) */
176 if (types == NULL || types[0] != 'v')
180 printf ("Testing method_getReturnType () ...\n");
182 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
183 @selector (setVariable:));
186 method_getReturnType (method, type, 16);
191 method_getReturnType (NULL, type, 16);
197 printf ("Testing method_setImplementation () ...\n");
199 Method method_a = class_getInstanceMethod (objc_getClass ("MySubClass"),
200 @selector (variable));
201 Method method_b = class_getInstanceMethod (objc_getClass ("MySubClass"),
202 @selector (constant));
203 IMP original_imp_a = method_getImplementation (method_a);
204 IMP original_imp_b = method_getImplementation (method_b);
205 MySubClass *object = [[MySubClass alloc] init];
207 /* Check that things work as expected before the swap. */
208 [object setVariable: object];
210 if ([object variable] != object || [object constant] != nil)
213 /* Have 'variable' use the same implementation as 'constant'. */
214 if (method_setImplementation (method_a, original_imp_b) != original_imp_a)
217 /* Check that behavior has changed. */
218 if ([object variable] != nil || [object constant] != nil)
221 /* Put the original method back. */
222 if (method_setImplementation (method_a, original_imp_a) != original_imp_b)
225 /* Check that behavior is back to normal. */
226 if ([object variable] != object || [object constant] != nil)