Merge trunk version 201119 into gupc branch.
[official-gcc.git] / gcc / testsuite / objc.dg / gnu-api-2-objc.m
blobd65c120455e4aa9b43397743e9eb388f26d1d560
1 /* Test the Modern GNU Objective-C Runtime API.
3   This is test 'objc', covering all functions starting with 'objc'.  */
5 /* { dg-do run } */
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" } { "" } } */
9 /* To get the modern GNU Objective-C Runtime API, you include
10    objc/runtime.h.  */
11 #include <objc/runtime.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
16 @interface MyRootClass
17 { Class isa; }
18 + alloc;
19 - init;
20 + initialize;
21 @end
23 @implementation MyRootClass
24 + alloc { return class_createInstance (self, 0); }
25 - init  { return self; }
26 + initialize { return self; }
27 @end
29 @protocol MyProtocol
30 - (id) variable;
31 @end
33 @protocol MySecondProtocol
34 - (id) setVariable: (id)value;
35 @end
37 @interface MySubClass : MyRootClass <MyProtocol>
38 { id variable_ivar; }
39 - (void) setVariable: (id)value;
40 - (id) variable;
41 @end
43 @implementation MySubClass
44 - (void) setVariable: (id)value { variable_ivar = value; }
45 - (id) variable { return variable_ivar; }
46 @end
48 /* Hack to calculate the log2 of a byte alignment.  */
49 unsigned char
50 log_2_of (unsigned int x)
52   unsigned char result = 0;
54   /* We count how many times we need to divide by 2 before we reach 1.
55      This algorithm is good enough for the small numbers (such as 8,
56      16 or 64) that we have to deal with.  */
57   while (x > 1)
58     {
59       x = x / 2;
60       result++;
61     }
63   return result;
66 int main(int argc, void **args)
68   /* Functions are tested in alphabetical order.  */
70   printf ("Testing objc_allocateClassPair ()...\n");
71   {
72     Class new_root_class = objc_allocateClassPair (Nil, "MyNewRootClass", 0);
73     Class new_class = objc_allocateClassPair (objc_getClass ("MyRootClass"), "MyNewSubClass", 0);
75     /* A new root class would obviously need at least an 'isa'
76        instance variable.  */
77     class_addIvar (new_root_class, "isa", sizeof (Class), log_2_of (__alignof__ (Class)),
78                    @encode (Class));
80     objc_registerClassPair (new_root_class);
81     objc_registerClassPair (new_class);
83     if (strcmp (class_getName (new_class), "MyNewSubClass") != 0)
84       abort ();
86     if (class_getSuperclass (new_class) != objc_getClass ("MyRootClass"))
87       abort ();
89     if (strcmp (class_getName (new_root_class), "MyNewRootClass") != 0)
90       abort ();
92     if (class_getSuperclass (new_root_class) != Nil)
93       abort ();
95     {
96       MySubClass *o = [[(Class)objc_getClass ("MyNewSubClass") alloc] init];
97       
98       if (object_getClass (o) != objc_getClass ("MyNewSubClass"))
99         abort ();
100     }
101   }
103   printf ("Testing objc_copyProtocolList ()...\n");
104   {
105     /* Make sure both our two protocols are known to the runtime.  */
106     id my_protocol = @protocol (MyProtocol);
107     id my_second_protocol = @protocol (MySecondProtocol);
108     unsigned int count;
109     Protocol ** list = objc_copyProtocolList (&count);
111     if (count != 2)
112       abort ();
114     if (! ((strcmp (protocol_getName (list[0]), "MyProtocol") == 0
115             && strcmp (protocol_getName (list[1]), "MySecondProtocol") == 0)
116            || (strcmp (protocol_getName (list[0]), "MySecondProtocol") == 0
117                && strcmp (protocol_getName (list[1]), "MyProtocol") == 0)))
118       abort ();
119     
120     if (list[2] != NULL)
121       abort ();
122   }
124   printf ("Testing objc_disposeClassPair ()...\n");
125   {
126     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"), @selector (setVariable:));
127     Class new_class = objc_allocateClassPair (objc_getClass ("MyRootClass"), "MyNewSubClass2", 0);
129     if (new_class == Nil)
130       abort ();
132     /* Add a bit of everything to the class to exercise undoing all these changes.  */
134     /* Instance variable.  */
135     class_addIvar (new_class, "my_variable", sizeof (float), log_2_of (__alignof__ (float)), @encode (float));
137     /* Instance method.  */
138     class_addMethod (new_class, @selector (setVariable:), method_getImplementation (method),
139                      method_getTypeEncoding (method));
141     /* Class method.  */
142     class_addMethod (object_getClass (new_class), @selector (setVariable:), method_getImplementation (method),
143                      method_getTypeEncoding (method));
145     /* Protocol.  */
146     class_addProtocol (new_class, @protocol (MyProtocol));
148     objc_disposeClassPair (new_class);
149   }
151   /* This function currently does not exist with the GNU runtime.  */
152   /* printf ("Testing objc_duplicateClass ()...\n"); */
154   /* TODO - Test it when implemented in the GNU Runtime */
155   /*  printf ("Testing objc_getAssociatedObject ()...\n");  */
157   printf ("Testing objc_getClass ()...\n");
158   {
159     if (strcmp (class_getName (objc_getClass ("MySubClass")),
160                 "MySubClass") != 0)
161       abort ();
162   }
164   printf ("Testing objc_getClassList ()...\n");
165   {
166     Class *list;
167     int i, count, other_count;
168     count = objc_getClassList (NULL, 0);
170     /* count most likely will be 5, (MyRootClass, MySubClass,
171        Protocol, Object, NXConstantString).  */
172     if (count < 3)
173       abort ();
174     
175     list = malloc (sizeof (Class) * count);
176     other_count = objc_getClassList (list, count);
178     if (other_count != count)
179       abort ();
181     /* Spot-check: search for class 'MyRootClass' in the list.  */
182     for (i = 0; i < count; i++)
183       {
184         if (strcmp (class_getName (list[i]), "MyRootClass") == 0)
185           break;
186       }
187     if (i == count)
188       abort ();
190     /* Spot-check: search for class 'MySubClass' in the list.  */
191     for (i = 0; i < count; i++)
192       {
193         if (strcmp (class_getName (list[i]), "MySubClass") == 0)
194           break;
195       }
196     if (i == count)
197       abort ();
199     /* Spot-check: search for class 'Protocol' in the list.  */
200     for (i = 0; i < count; i++)
201       {
202         if (strcmp (class_getName (list[i]), "Protocol") == 0)
203           break;
204       }
205     if (i == count)
206       abort ();
207   }
209   /* This function does not exist with the GNU runtime.  */
210   /* printf ("Testing objc_getFutureClass ()...\n"); */
212   printf ("Testing objc_getMetaClass ()...\n");
213   {
214     if (! class_isMetaClass (objc_getMetaClass ("MyRootClass")))
215       abort ();
216   }
218   printf ("Testing objc_getProtocol ()...\n");
219   {
220     if (! protocol_isEqual (objc_getProtocol ("MyProtocol"), @protocol (MyProtocol)))
221       abort ();
222   }
224   printf ("Testing objc_getRequiredClass ()...\n");
225   {
226     if (strcmp (class_getName (objc_getRequiredClass ("MyRootClass")),
227                 "MyRootClass") != 0)
228       abort ();
229   }
231   printf ("Testing objc_lookUpClass ()...\n");
232   {
233     if (strcmp (class_getName (objc_lookUpClass ("MyRootClass")),
234                 "MyRootClass") != 0)
235       abort ();
236   }
238   /* This function does not exist with the GNU runtime.  */
239   /* printf ("Testing objc_setFutureClass ()...\n"); */
241   printf ("Testing objc_registerClassPair ()...\n");
242   {
243     Class new_class = objc_allocateClassPair (objc_getClass ("MySubClass"), "MySubSubClass", 0);
245     class_addProtocol (new_class, @protocol (MySecondProtocol));
246     
247     objc_registerClassPair (new_class);
248     
249     if (strcmp (class_getName (new_class), "MySubSubClass") != 0)
250       abort ();
252     if (class_getSuperclass (new_class) != objc_getClass ("MySubClass"))
253       abort ();
255     if (! class_conformsToProtocol (new_class, @protocol (MySecondProtocol)))
256       abort ();
257   }
259   /* TODO - Test it when implemented in the GNU Runtime */
260   /*  printf ("Testing objc_removeAssociatedObjects ()...\n");  */
262   /* TODO - Test it when implemented in the GNU Runtime */
263   /*  printf ("Testing objc_setAssociatedObject ()...\n");  */
265   return 0;