gcc/testsuite:
[official-gcc.git] / gcc / testsuite / objc.dg / foreach-2.m
blob1e9c515f600595748264a046fb8865c929e87fa7
1 /* Test basic Objective-C foreach syntax.  This tests iterations, with
2    the basic syntax 'for (object in array) statements'
3 */
4 /* { dg-do run } */
5 /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
6 /* { dg-additional-sources "../objc-obj-c++-shared/Object1.m" } */
8 #import "../objc-obj-c++-shared/Object1.h"
9 #import "../objc-obj-c++-shared/next-mapping.h"
10 #ifndef __NEXT_RUNTIME__
11 #include <objc/NXConstStr.h>
12 #endif
14 extern int printf (const char *, ...);
15 #include <stdlib.h>
18 struct __objcFastEnumerationState
20   unsigned long state;
21   id            *itemsPtr;
22   unsigned long *mutationsPtr;
23   unsigned long extra[5];
27  /* A mini-array implementation that can be used to test fast
28     enumeration.  You create the array with some objects; you can
29     mutate the array, and you can fast-enumerate it.
30  */
31 @interface MyArray : Object
33   unsigned int length;
34   id *objects;
35   unsigned long mutated;
37 - (id) initWithLength: (unsigned int)l  objects: (id *)o;
38 - (void) mutate;
39 - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
40                                      objects:(id *)stackbuf 
41                                        count:(unsigned long)len;
42 @end
44 @implementation MyArray : Object
45 - (id) initWithLength: (unsigned int)l
46               objects: (id *)o
48   length = l;
49   objects = o;
50   mutated = 0;
52 - (void) mutate
54   mutated = 1;
56 - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state 
57                                      objects: (id*)stackbuf
58                                        count: (unsigned long)len
60   unsigned long i, batch_size;
62   /* We keep how many objects we served in the state->state counter.  So the next batch
63      will contain up to length - state->state objects.  */
64   batch_size = length - state->state;
66   /* Make obvious adjustments.  */
67   if (batch_size < 0)
68     batch_size = 0;
70   if (batch_size > len)
71     batch_size = len;
73   /* Copy the objects.  */
74   for (i = 0; i < batch_size; i++)
75     stackbuf[i] = objects[i];
77   state->state += batch_size;
78   state->itemsPtr = stackbuf;
79   state->mutationsPtr = &mutated;
81   return batch_size;
83 @end
85 int main (void)
87   MyArray *array;
88   Object *object;
89   int test_variable, counter, i;
90   id *objects;
92   array = [[MyArray alloc] initWithLength: 0
93                            objects: NULL];
95   /* Test that an empty array does nothing.  */
96   for (object in array)
97     abort ();
99   if (object != nil)
100     abort ();
102   /* Test iterating over 1 object.  */
103   objects = malloc (sizeof (id) * 1);
104   objects[0] = @"One Object";
106   array = [[MyArray alloc] initWithLength: 1
107                            objects: objects];
108   
109   for (object in array)
110     printf ("%p\n", object);
111   
112   /* Test iterating over 20 objects.  */
113   objects = malloc (sizeof (id) * 20);
114   for (i = 0; i < 20; i++)
115     objects[i] = @"object";
116   
117   array = [[MyArray alloc] initWithLength: 20
118                            objects: objects];
119   
120   for (object in array)
121     printf ("%p\n", object);
123   /* Test iterating over 200 objects.  */
124   objects = malloc (sizeof (id) * 200);
125   for (i = 0; i < 200; i++)
126     objects[i] = @"object";
127   
128   array = [[MyArray alloc] initWithLength: 200
129                            objects: objects];
130   
131   counter = 0;
132   for (object in array)
133     {
134       if (object != nil)
135         counter++;
136     }
138   if (counter != 200)
139     abort ();
141   printf ("Counter was %d (should be 200)\n", counter);
143   /* Test iterating again over the same array.  */
144   counter = 0;
145   for (object in array)
146     {
147       if (object != nil)
148         counter++;
149     }
151   if (counter != 200)
152     abort ();
154   printf ("Counter was %d (should be 200)\n", counter);
156   /* Test nested iterations.  */
157   objects = malloc (sizeof (id) * 20);
158   for (i = 0; i < 20; i++)
159     objects[i] = @"object";
160   
161   array = [[MyArray alloc] initWithLength: 20
162                            objects: objects];
163   counter = 0;
164   for (object in array)
165     {
166       id another_object;
167       for (another_object in array)
168         if (another_object != nil)
169           counter++;
170     }
172   printf ("Counter was %d (should be 400)\n", counter);
174   if (counter != 400)
175     abort ();
177   /* Test 'continue'.  */
178   objects = malloc (sizeof (id) * 20);
179   for (i = 0; i < 20; i++)
180     objects[i] = @"object";
181   
182   array = [[MyArray alloc] initWithLength: 20
183                            objects: objects];
184   counter = 0;
185   for (object in array)
186     {
187       if (counter == 15)
188         continue;
190       counter++;
191     }
193   printf ("Counter was %d (should be 15)\n", counter);
195   if (counter != 15)
196     abort ();
198   /* Test 'break'.  */
199   objects = malloc (sizeof (id) * 20);
200   for (i = 0; i < 20; i++)
201     objects[i] = @"object";
202   
203   array = [[MyArray alloc] initWithLength: 20
204                            objects: objects];
205   counter = 0;
206   for (object in array)
207     {
208       counter++;
210       if (counter == 15)
211         break;
212     }
214   printf ("Counter was %d (should be 15)\n", counter);
216   if (counter != 15)
217     abort ();
219   /* Test 'break' and 'continue' in nested iterations.  */
220   objects = malloc (sizeof (id) * 20);
221   for (i = 0; i < 20; i++)
222     objects[i] = @"object";
223   
224   array = [[MyArray alloc] initWithLength: 20
225                            objects: objects];
226   counter = 0;
227   for (object in array)
228     {
229       int local_counter = 0;
230       id another_object;
232       /* Each internal loop should increase counter by 24.  */
233       for (another_object in array)
234         {
235           local_counter++;
236           
237           if (local_counter == 10)
238             {
239               counter = counter + 20;
240               break;
241             }
243           if (local_counter >= 5)
244             continue;
246           counter++;
247         }
249       /* Exit after 4 iterations.  */
250       if (counter == 96)
251         break;
252     }
254   printf ("Counter was %d (should be 96)\n", counter);
256   if (counter != 96)
257     abort ();
259   /* Test that if we 'break', the object is set to the last one, while
260      if we run out of objects, it is set to 'nil'.  */
261   for (object in array)
262     ;
264   if (object != nil)
265     abort ();
267   for (object in array)
268     break;
270   if (object == nil)
271     abort ();
273   /* Test that C for loops still work.  */
274   test_variable = 0;
276   for (counter = 0; counter < 4; counter++)
277     test_variable++;
279   if (test_variable != 4)
280     abort ();
282   return 0;