OSDN Git Service

In gcc/:
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / objc.dg / foreach-3.m
1 /* Test basic Objective-C foreach syntax.  This tests the mutation.
2 */
3 /* { dg-do compile } */
4
5 /* FIXME: This test should be run, and it succeeds if the program
6    aborts at the right time (when the mutation happens).  It currently
7    works, but how do we tell the testsuite to test for it ?
8 */
9
10 #import "../objc-obj-c++-shared/Object1.h"
11 #import "../objc-obj-c++-shared/next-mapping.h"
12 #ifndef __NEXT_RUNTIME__
13 #include <objc/NXConstStr.h>
14 #endif
15
16 extern int printf (const char *, ...);
17 #include <stdlib.h>
18
19 /*
20 struct __objcFastEnumerationState
21 {
22   unsigned long state;
23   id            *itemsPtr;
24   unsigned long *mutationsPtr;
25   unsigned long extra[5];
26 };
27 */
28
29  /* A mini-array implementation that can be used to test fast
30     enumeration.  You create the array with some objects; you can
31     mutate the array, and you can fast-enumerate it.
32  */
33 @interface MyArray : Object
34 {
35   unsigned int length;
36   id *objects;
37   unsigned long mutated;
38 }
39 - (id) initWithLength: (unsigned int)l  objects: (id *)o;
40 - (void) mutate;
41 - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
42                                      objects:(id *)stackbuf 
43                                        count:(unsigned long)len;
44 @end
45
46 @implementation MyArray : Object
47 - (id) initWithLength: (unsigned int)l
48               objects: (id *)o
49 {
50   length = l;
51   objects = o;
52   mutated = 0;
53 }
54 - (void) mutate
55 {
56   mutated = 1;
57 }
58 - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state 
59                                      objects: (id*)stackbuf
60                                        count: (unsigned long)len
61 {
62   unsigned long i, batch_size;
63
64   /* Change the mutationsPtr if 'mutate' is called.  */
65   state->mutationsPtr = &mutated;
66
67   /* We keep how many objects we served in the state->state counter.  So the next batch
68      will contain up to length - state->state objects.  */
69   batch_size = length - state->state;
70
71   /* Make obvious adjustments.  */
72   if (batch_size < 0)
73     batch_size = 0;
74
75   if (batch_size > len)
76     batch_size = len;
77
78   /* Copy the objects.  */
79   for (i = 0; i < batch_size; i++)
80     stackbuf[i] = objects[i];
81
82   state->state += batch_size;
83   state->itemsPtr = stackbuf;
84
85   return batch_size;
86 }
87 @end
88
89 int main (void)
90 {
91   MyArray *array;
92   Object *object;
93   int counter, i;
94   id *objects;
95
96   /* Test iterating over 20 objects, mutating after 15.  */
97   objects = malloc (sizeof (id) * 20);
98   for (i = 0; i < 20; i++)
99     objects[i] = @"object";
100   
101   array = [[MyArray alloc] initWithLength: 20
102                            objects: objects];
103   
104   counter = 0;
105   for (object in array)
106     {
107       counter++;
108       printf ("%d\n", counter);
109       if (counter == 14)
110         {
111           printf ("Mutating (should abort at next iteration)\n");
112           [array mutate];
113         }
114     }
115
116   return 0;
117 }