OSDN Git Service

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