PR c/47043
[official-gcc.git] / gcc / testsuite / objc.dg / foreach-5.m
blobdce26fa3e9395e4769f249384d6ffaf8413e8960
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-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" } */
10 #import "../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
17 extern int printf (const char *, ...);
18 #include <stdlib.h>
20 typedef struct
22   unsigned long state;
23   id            *itemsPtr;
24   unsigned long *mutationsPtr;
25   unsigned long extra[5];
26 } NSFastEnumerationState;
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.
32 @interface MyArray : TestsuiteObject
34   unsigned int length;
35   id *objects;
36   unsigned long mutated;
38 - (id) initWithLength: (unsigned int)l  objects: (id *)o;
39 - (void) mutate;
40 - (unsigned long)countByEnumeratingWithState: (NSFastEnumerationState *)state
41                                      objects:(id *)stackbuf 
42                                        count:(unsigned long)len;
43 @end
45 @implementation MyArray : TestsuiteObject
46 - (id) initWithLength: (unsigned int)l
47               objects: (id *)o
49   length = l;
50   objects = o;
51   mutated = 0;
52   return self;
54 - (void) mutate
56   mutated = 1;
58 - (unsigned long)countByEnumeratingWithState: (NSFastEnumerationState*)state 
59                                      objects: (id*)stackbuf
60                                        count: (unsigned long)len
62   unsigned long i, batch_size;
64   /* We keep how many objects we served in the state->state counter.  So the next batch
65      will contain up to length - state->state objects.  */
66   batch_size = length - state->state;
68   /* Make obvious adjustments.  */
69   if (batch_size < 0)
70     batch_size = 0;
72   if (batch_size > len)
73     batch_size = len;
75   /* Copy the objects.  */
76   for (i = 0; i < batch_size; i++)
77     stackbuf[i] = objects[i];
79   state->state += batch_size;
80   state->itemsPtr = stackbuf;
81   state->mutationsPtr = &mutated;
83   return batch_size;
85 @end
87 int main (void)
89   MyArray *array;
90   int test_variable, counter, i;
91   id *objects;
93   array = [[MyArray alloc] initWithLength: 0
94                            objects: NULL];
96   /* Test that an empty array does nothing.  */
97   for (id object in array)
98     abort ();
100   /* Test iterating over 1 object.  */
101   objects = malloc (sizeof (id) * 1);
102   objects[0] = @"One Object";
104   array = [[MyArray alloc] initWithLength: 1
105                            objects: objects];
106   
107   for (id object in array)
108     printf ("%p\n", object);
109   
110   /* Test iterating over 20 objects.  */
111   objects = malloc (sizeof (id) * 20);
112   for (i = 0; i < 20; i++)
113     objects[i] = @"object";
114   
115   array = [[MyArray alloc] initWithLength: 20
116                            objects: objects];
117   
118   for (id object in array)
119     printf ("%p\n", object);
121   /* Test iterating over 200 objects.  */
122   objects = malloc (sizeof (id) * 200);
123   for (i = 0; i < 200; i++)
124     objects[i] = @"object";
125   
126   array = [[MyArray alloc] initWithLength: 200
127                            objects: objects];
128   
129   counter = 0;
130   for (id object in array)
131     {
132       if (object != nil)
133         counter++;
134     }
136   if (counter != 200)
137     abort ();
139   printf ("Counter was %d (should be 200)\n", counter);
141   /* Test iterating again over the same array.  */
142   counter = 0;
143   for (id object in array)
144     {
145       if (object != nil)
146         counter++;
147     }
149   if (counter != 200)
150     abort ();
152   printf ("Counter was %d (should be 200)\n", counter);
154   /* Test nested iterations.  */
155   objects = malloc (sizeof (id) * 20);
156   for (i = 0; i < 20; i++)
157     objects[i] = @"object";
158   
159   array = [[MyArray alloc] initWithLength: 20
160                            objects: objects];
161   counter = 0;
162   for (id object in array)
163     {
164       for (id another_object in array)
165         if (another_object != nil)
166           counter++;
167     }
169   printf ("Counter was %d (should be 400)\n", counter);
171   if (counter != 400)
172     abort ();
174   /* Test 'continue'.  */
175   objects = malloc (sizeof (id) * 20);
176   for (i = 0; i < 20; i++)
177     objects[i] = @"object";
178   
179   array = [[MyArray alloc] initWithLength: 20
180                            objects: objects];
181   counter = 0;
182   for (id object in array)
183     {
184       if (counter == 15)
185         continue;
187       counter++;
188     }
190   printf ("Counter was %d (should be 15)\n", counter);
192   if (counter != 15)
193     abort ();
195   /* Test 'break'.  */
196   objects = malloc (sizeof (id) * 20);
197   for (i = 0; i < 20; i++)
198     objects[i] = @"object";
199   
200   array = [[MyArray alloc] initWithLength: 20
201                            objects: objects];
202   counter = 0;
203   for (id object in array)
204     {
205       counter++;
207       if (counter == 15)
208         break;
209     }
211   printf ("Counter was %d (should be 15)\n", counter);
213   if (counter != 15)
214     abort ();
216   /* Test 'break' and 'continue' in nested iterations.  */
217   objects = malloc (sizeof (id) * 20);
218   for (i = 0; i < 20; i++)
219     objects[i] = @"object";
220   
221   array = [[MyArray alloc] initWithLength: 20
222                            objects: objects];
223   counter = 0;
224   for (id object in array)
225     {
226       int local_counter = 0;
228       /* Each internal loop should increase counter by 24.  */
229       for (id another_object in array)
230         {
231           local_counter++;
232           
233           if (local_counter == 10)
234             {
235               counter = counter + 20;
236               break;
237             }
239           if (local_counter >= 5)
240             continue;
242           counter++;
243         }
245       /* Exit after 4 iterations.  */
246       if (counter == 96)
247         break;
248     }
250   printf ("Counter was %d (should be 96)\n", counter);
252   if (counter != 96)
253     abort ();
255   /* Test that C for loops still work.  */
256   test_variable = 0;
258   for (counter = 0; counter < 4; counter++)
259     test_variable++;
261   if (test_variable != 4)
262     abort ();
264   return 0;