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