2010-11-11 Jakub Jelinek <jakub@redhat.com>
[official-gcc.git] / gcc / testsuite / objc.dg / foreach-5.m
blobae06d670257e262546d36a1f9e68dde83341b71f
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" } */
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
15 extern int printf (const char *, ...);
16 #include <stdlib.h>
18 typedef struct
20   unsigned long state;
21   id            *itemsPtr;
22   unsigned long *mutationsPtr;
23   unsigned long extra[5];
24 } NSFastEnumerationState;
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.
30 @interface MyArray : Object
32   unsigned int length;
33   id *objects;
34   unsigned long mutated;
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
43 @implementation MyArray : Object
44 - (id) initWithLength: (unsigned int)l
45               objects: (id *)o
47   length = l;
48   objects = o;
49   mutated = 0;
51 - (void) mutate
53   mutated = 1;
55 - (unsigned long)countByEnumeratingWithState: (NSFastEnumerationState*)state 
56                                      objects: (id*)stackbuf
57                                        count: (unsigned long)len
59   unsigned long i, batch_size;
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;
65   /* Make obvious adjustments.  */
66   if (batch_size < 0)
67     batch_size = 0;
69   if (batch_size > len)
70     batch_size = len;
72   /* Copy the objects.  */
73   for (i = 0; i < batch_size; i++)
74     stackbuf[i] = objects[i];
76   state->state += batch_size;
77   state->itemsPtr = stackbuf;
78   state->mutationsPtr = &mutated;
80   return batch_size;
82 @end
84 int main (void)
86   MyArray *array;
87   int test_variable, counter, i;
88   id *objects;
90   array = [[MyArray alloc] initWithLength: 0
91                            objects: NULL];
93   /* Test that an empty array does nothing.  */
94   for (id object in array)
95     abort ();
97   /* Test iterating over 1 object.  */
98   objects = malloc (sizeof (id) * 1);
99   objects[0] = @"One Object";
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);
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     }
133   if (counter != 200)
134     abort ();
136   printf ("Counter was %d (should be 200)\n", counter);
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     }
146   if (counter != 200)
147     abort ();
149   printf ("Counter was %d (should be 200)\n", counter);
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     }
166   printf ("Counter was %d (should be 400)\n", counter);
168   if (counter != 400)
169     abort ();
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;
184       counter++;
185     }
187   printf ("Counter was %d (should be 15)\n", counter);
189   if (counter != 15)
190     abort ();
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++;
204       if (counter == 15)
205         break;
206     }
208   printf ("Counter was %d (should be 15)\n", counter);
210   if (counter != 15)
211     abort ();
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;
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             }
236           if (local_counter >= 5)
237             continue;
239           counter++;
240         }
242       /* Exit after 4 iterations.  */
243       if (counter == 96)
244         break;
245     }
247   printf ("Counter was %d (should be 96)\n", counter);
249   if (counter != 96)
250     abort ();
252   /* Test that C for loops still work.  */
253   test_variable = 0;
255   for (counter = 0; counter < 4; counter++)
256     test_variable++;
258   if (test_variable != 4)
259     abort ();
261   return 0;