OSDN Git Service

Backported from mainline
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / objc.dg / foreach-2.m
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-skip-if "No NeXT fast enum. pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
6 /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
7 /* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
8 /* { dg-additional-sources "../objc-obj-c++-shared/nsconstantstring-class-impl.m" } */
9
10 #include "../objc-obj-c++-shared/TestsuiteObject.m"
11 #ifndef __NEXT_RUNTIME__
12 #include <objc/NXConstStr.h>
13 #else
14 #include "../objc-obj-c++-shared/nsconstantstring-class.h"
15 #endif
16
17 extern int printf (const char *, ...);
18 #include <stdlib.h>
19
20 /*
21 struct __objcFastEnumerationState
22 {
23   unsigned long state;
24   id            *itemsPtr;
25   unsigned long *mutationsPtr;
26   unsigned long extra[5];
27 };
28 */
29
30  /* A mini-array implementation that can be used to test fast
31     enumeration.  You create the array with some objects; you can
32     mutate the array, and you can fast-enumerate it.
33  */
34 @interface MyArray : TestsuiteObject
35 {
36   unsigned int length;
37   id *objects;
38   unsigned long mutated;
39 }
40 - (id) initWithLength: (unsigned int)l  objects: (id *)o;
41 - (void) mutate;
42 - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
43                                      objects:(id *)stackbuf 
44                                        count:(unsigned long)len;
45 @end
46
47 @implementation MyArray : TestsuiteObject
48 - (id) initWithLength: (unsigned int)l
49               objects: (id *)o
50 {
51   length = l;
52   objects = o;
53   mutated = 0;
54   return self;
55 }
56 - (void) mutate
57 {
58   mutated = 1;
59 }
60 - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state 
61                                      objects: (id*)stackbuf
62                                        count: (unsigned long)len
63 {
64   unsigned long i, batch_size;
65
66   /* We keep how many objects we served in the state->state counter.  So the next batch
67      will contain up to length - state->state objects.  */
68   batch_size = length - state->state;
69
70   /* Make obvious adjustments.  */
71   if (batch_size < 0)
72     batch_size = 0;
73
74   if (batch_size > len)
75     batch_size = len;
76
77   /* Copy the objects.  */
78   for (i = 0; i < batch_size; i++)
79     stackbuf[i] = objects[i];
80
81   state->state += batch_size;
82   state->itemsPtr = stackbuf;
83   state->mutationsPtr = &mutated;
84
85   return batch_size;
86 }
87 @end
88
89 int main (void)
90 {
91   MyArray *array;
92   TestsuiteObject *object;
93   int test_variable, counter, i;
94   id *objects;
95
96   array = [[MyArray alloc] initWithLength: 0
97                            objects: NULL];
98
99   /* Test that an empty array does nothing.  */
100   for (object in array)
101     abort ();
102
103   if (object != nil)
104     abort ();
105
106   /* Test iterating over 1 object.  */
107   objects = malloc (sizeof (id) * 1);
108   objects[0] = @"One Object";
109
110   array = [[MyArray alloc] initWithLength: 1
111                            objects: objects];
112   
113   for (object in array)
114     printf ("%p\n", object);
115   
116   /* Test iterating over 20 objects.  */
117   objects = malloc (sizeof (id) * 20);
118   for (i = 0; i < 20; i++)
119     objects[i] = @"object";
120   
121   array = [[MyArray alloc] initWithLength: 20
122                            objects: objects];
123   
124   for (object in array)
125     printf ("%p\n", object);
126
127   /* Test iterating over 200 objects.  */
128   objects = malloc (sizeof (id) * 200);
129   for (i = 0; i < 200; i++)
130     objects[i] = @"object";
131   
132   array = [[MyArray alloc] initWithLength: 200
133                            objects: objects];
134   
135   counter = 0;
136   for (object in array)
137     {
138       if (object != nil)
139         counter++;
140     }
141
142   if (counter != 200)
143     abort ();
144
145   printf ("Counter was %d (should be 200)\n", counter);
146
147   /* Test iterating again over the same array.  */
148   counter = 0;
149   for (object in array)
150     {
151       if (object != nil)
152         counter++;
153     }
154
155   if (counter != 200)
156     abort ();
157
158   printf ("Counter was %d (should be 200)\n", counter);
159
160   /* Test nested iterations.  */
161   objects = malloc (sizeof (id) * 20);
162   for (i = 0; i < 20; i++)
163     objects[i] = @"object";
164   
165   array = [[MyArray alloc] initWithLength: 20
166                            objects: objects];
167   counter = 0;
168   for (object in array)
169     {
170       id another_object;
171       for (another_object in array)
172         if (another_object != nil)
173           counter++;
174     }
175
176   printf ("Counter was %d (should be 400)\n", counter);
177
178   if (counter != 400)
179     abort ();
180
181   /* Test 'continue'.  */
182   objects = malloc (sizeof (id) * 20);
183   for (i = 0; i < 20; i++)
184     objects[i] = @"object";
185   
186   array = [[MyArray alloc] initWithLength: 20
187                            objects: objects];
188   counter = 0;
189   for (object in array)
190     {
191       if (counter == 15)
192         continue;
193
194       counter++;
195     }
196
197   printf ("Counter was %d (should be 15)\n", counter);
198
199   if (counter != 15)
200     abort ();
201
202   /* Test 'break'.  */
203   objects = malloc (sizeof (id) * 20);
204   for (i = 0; i < 20; i++)
205     objects[i] = @"object";
206   
207   array = [[MyArray alloc] initWithLength: 20
208                            objects: objects];
209   counter = 0;
210   for (object in array)
211     {
212       counter++;
213
214       if (counter == 15)
215         break;
216     }
217
218   printf ("Counter was %d (should be 15)\n", counter);
219
220   if (counter != 15)
221     abort ();
222
223   /* Test 'break' and 'continue' in nested iterations.  */
224   objects = malloc (sizeof (id) * 20);
225   for (i = 0; i < 20; i++)
226     objects[i] = @"object";
227   
228   array = [[MyArray alloc] initWithLength: 20
229                            objects: objects];
230   counter = 0;
231   for (object in array)
232     {
233       int local_counter = 0;
234       id another_object;
235
236       /* Each internal loop should increase counter by 24.  */
237       for (another_object in array)
238         {
239           local_counter++;
240           
241           if (local_counter == 10)
242             {
243               counter = counter + 20;
244               break;
245             }
246
247           if (local_counter >= 5)
248             continue;
249
250           counter++;
251         }
252
253       /* Exit after 4 iterations.  */
254       if (counter == 96)
255         break;
256     }
257
258   printf ("Counter was %d (should be 96)\n", counter);
259
260   if (counter != 96)
261     abort ();
262
263   /* Test that if we 'break', the object is set to the last one, while
264      if we run out of objects, it is set to 'nil'.  */
265   for (object in array)
266     ;
267
268   if (object != nil)
269     abort ();
270
271   for (object in array)
272     break;
273
274   if (object == nil)
275     abort ();
276
277   /* Test that C for loops still work.  */
278   test_variable = 0;
279
280   for (counter = 0; counter < 4; counter++)
281     test_variable++;
282
283   if (test_variable != 4)
284     abort ();
285
286   return 0;
287 }