OSDN Git Service

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