/* Test basic Objective-C foreach syntax. This tests the mutation. */ /* { dg-do compile } */ /* FIXME: This test should be run, and it succeeds if the program aborts at the right time (when the mutation happens). It currently works, but how do we tell the testsuite to test for it ? */ #include "../objc-obj-c++-shared/TestsuiteObject.m" #ifndef __NEXT_RUNTIME__ #include #endif extern int printf (const char *, ...); #include /* struct __objcFastEnumerationState { unsigned long state; id *itemsPtr; unsigned long *mutationsPtr; unsigned long extra[5]; }; */ /* A mini-array implementation that can be used to test fast enumeration. You create the array with some objects; you can mutate the array, and you can fast-enumerate it. */ @interface MyArray : TestsuiteObject { unsigned int length; id *objects; unsigned long mutated; } - (id) initWithLength: (unsigned int)l objects: (id *)o; - (void) mutate; - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects:(id *)stackbuf count:(unsigned long)len; @end @implementation MyArray : TestsuiteObject - (id) initWithLength: (unsigned int)l objects: (id *)o { length = l; objects = o; mutated = 0; return self; } - (void) mutate { mutated = 1; } - (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state objects: (id*)stackbuf count: (unsigned long)len { unsigned long i, batch_size; /* Change the mutationsPtr if 'mutate' is called. */ state->mutationsPtr = &mutated; /* We keep how many objects we served in the state->state counter. So the next batch will contain up to length - state->state objects. */ batch_size = length - state->state; /* Make obvious adjustments. */ if (batch_size < 0) batch_size = 0; if (batch_size > len) batch_size = len; /* Copy the objects. */ for (i = 0; i < batch_size; i++) stackbuf[i] = objects[i]; state->state += batch_size; state->itemsPtr = stackbuf; return batch_size; } @end int main (void) { MyArray *array; TestsuiteObject *object; int counter, i; id *objects; /* Test iterating over 20 objects, mutating after 15. */ objects = malloc (sizeof (id) * 20); for (i = 0; i < 20; i++) objects[i] = @"object"; array = [[MyArray alloc] initWithLength: 20 objects: objects]; counter = 0; for (object in array) { counter++; printf ("%d\n", counter); if (counter == 14) { printf ("Mutating (should abort at next iteration)\n"); [array mutate]; } } return 0; }