Commit f05b9d93 by Nicola Pero Committed by Nicola Pero

In gcc/: 2010-10-06 Nicola Pero <nicola.pero@meta-innovation.com>

In gcc/:
2010-10-06  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented fast enumeration for Objective-C.
        * c-parser.c (objc_could_be_foreach_context): New.
        (c_lex_one_token): Recognize RID_IN keyword in a potential
        Objective-C foreach context.
        (c_parser_declaration_or_fndef): Added parameter.  Accept
        Objective-C RID_IN keyword as terminating a declaration; in that
        case, return the declaration in the new parameter.
        (c_parser_extenral_declaration): Updated calls to
        c_parser_declaration_or_fndef.
        (c_parser_declaration_or_fndef): Same change.
        (c_parser_compound_statement_nostart): Same change.
        (c_parser_label): Same change.
        (c_parser_objc_methodprotolist): Same change.
        (c_parser_omp_for_loop): Same change.
        (c_parser_for_statement): Detect and parse Objective-C foreach
        statements.
        (c_parser_omp_for_loop): Updated call to check_for_loop_decls().
        * c-decl.c (check_for_loop_decls): Added parameter to allow ObjC
        fast enumeration parsing code to turn off the c99 error but still
        perform checks on the loop declarations.
        * c-tree.h (check_for_loop_decls): Updated declaration.
        * doc/objc.texi: Document fast enumeration.

In gcc/c-family/:
2010-10-06  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented fast enumeration for Objective-C.
        * c-common.h (objc_finish_foreach_loop): New.
        * stub-objc.c (objc_finish_foreach_loop): New.

In gcc/objc/:
2010-10-06  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented fast enumeration for Objective-C.
        * objc-act.c (build_fast_enumeration_state_template): New.
        (TAG_ENUMERATION_MUTATION): New.
        (TAG_FAST_ENUMERATION_STATE): New.
        (synth_module_prologue): Call build_fast_enumeration_state_template() and set up
        objc_enumeration_mutation_decl.
        (objc_create_temporary_var): Allow providing a name to temporary
        variables.
        (objc_build_exc_ptr): Updated calls to
        objc_create_temporary_var().
        (next_sjlj_build_try_catch_finally): Same change.
        (objc_finish_foreach_loop): New.
        * objc-act.h: Added OCTI_FAST_ENUM_STATE_TEMP,
        OCTI_ENUM_MUTATION_DECL, objc_fast_enumeration_state_template,
        objc_enumeration_mutation_decl.

        Merge from 'apple/trunk' branch on FSF servers.

        2006-04-12 Fariborz Jahanian <fjahanian@apple.com>

        Radar 4507230
        * objc-act.c (objc_type_valid_for_messaging): New routine to check
        for valid objc object types.
        (objc_finish_foreach_loop): Check for invalid objc objects in
        foreach header.

In gcc/testsuite/:
2010-10-05  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented fast enumeration for Objective-C.
        * objc.dg/foreach-1.m: New.
        * objc.dg/foreach-2.m: New.
        * objc.dg/foreach-3.m: New.
        * objc.dg/foreach-4.m: New.
        * objc.dg/foreach-5.m: New.
        * objc.dg/foreach-6.m: New.
        * objc.dg/foreach-7.m: New.

        Merge from 'apple/trunk' branch on FSF servers:
        2006-04-13 Fariborz Jahanian <fjahanian@apple.com>

        Radar 4502236
        * objc.dg/objc-foreach-5.m: New.

        2006-04-12 Fariborz Jahanian <fjahanian@apple.com>

        Radar 4507230
        * objc.dg/objc-foreach-4.m: New.

        2006-03-13  Fariborz Jahanian <fjahanian@apple.com>

        Radar 4472881
        * objc.dg/objc-foreach-3.m: New.

        2005-03-07 Fariborz Jahanian <fjahanian@apple.com>

        Radar 4468498
        * objc.dg/objc-foreach-2.m: New.

        2006-02-15   Fariborz Jahanian <fjahanian@apple.com>

        Radar 4294910
        * objc.dg/objc-foreach-1.m: New

In libobjc/:
2010-10-06  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented fast enumeration for Objective-C.
        * Makefile.in (C_SOURCE_FILES): Added objc-foreach.c.
        (OBJC_H): Added runtime.h
        * objc-foreach.c: New file.
        * objc/runtime.h: New file.

From-SVN: r165019
parent b938bc48
2010-10-06 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented fast enumeration for Objective-C.
* c-parser.c (objc_could_be_foreach_context): New.
(c_lex_one_token): Recognize RID_IN keyword in a potential
Objective-C foreach context.
(c_parser_declaration_or_fndef): Added parameter. Accept
Objective-C RID_IN keyword as terminating a declaration; in that
case, return the declaration in the new parameter.
(c_parser_extenral_declaration): Updated calls to
c_parser_declaration_or_fndef.
(c_parser_declaration_or_fndef): Same change.
(c_parser_compound_statement_nostart): Same change.
(c_parser_label): Same change.
(c_parser_objc_methodprotolist): Same change.
(c_parser_omp_for_loop): Same change.
(c_parser_for_statement): Detect and parse Objective-C foreach
statements.
(c_parser_omp_for_loop): Updated call to check_for_loop_decls().
* c-decl.c (check_for_loop_decls): Added parameter to allow ObjC
fast enumeration parsing code to turn off the c99 error but still
perform checks on the loop declarations.
* c-tree.h (check_for_loop_decls): Updated declaration.
* doc/objc.texi: Document fast enumeration.
2010-10-06 Nick Clifton <nickc@redhat.com>
* config/mn10300/mn10300.h (FIRST_PSEUDO_REGISTER): Increment by
......@@ -8310,16 +8310,23 @@ finish_function (void)
/* Check the declarations given in a for-loop for satisfying the C99
constraints. If exactly one such decl is found, return it. LOC is
the location of the opening parenthesis of the for loop. */
the location of the opening parenthesis of the for loop. The last
parameter allows you to control the "for loop initial declarations
are only allowed in C99 mode". Normally, you should pass
flag_isoc99 as that parameter. But in some cases (Objective-C
foreach loop, for example) we want to run the checks in this
function even if not in C99 mode, so we allow the caller to turn
off the error about not being in C99 mode.
*/
tree
check_for_loop_decls (location_t loc)
check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
{
struct c_binding *b;
tree one_decl = NULL_TREE;
int n_decls = 0;
if (!flag_isoc99)
if (!turn_off_iso_c99_error)
{
static bool hint = true;
/* If we get here, declarations have been used in a for loop without
......
2010-10-06 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented fast enumeration for Objective-C.
* c-common.h (objc_finish_foreach_loop): New.
* stub-objc.c (objc_finish_foreach_loop): New.
2010-10-05 Joseph Myers <joseph@codesourcery.com>
* c-common.h (struct diagnostic_context): Don't declare here.
......
......@@ -1007,6 +1007,7 @@ extern int objc_static_init_needed_p (void);
extern tree objc_generate_static_init_call (tree);
extern tree objc_generate_write_barrier (tree, enum tree_code, tree);
extern void objc_set_method_opt (bool);
extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree);
/* The following are provided by the C and C++ front-ends, and called by
ObjC/ObjC++. */
......
......@@ -355,3 +355,11 @@ objc_generate_write_barrier (tree ARG_UNUSED (lhs),
{
return 0;
}
void
objc_finish_foreach_loop (location_t ARG_UNUSED (location), tree ARG_UNUSED (object_expression),
tree ARG_UNUSED (collection_expression), tree ARG_UNUSED (for_body),
tree ARG_UNUSED (break_label), tree ARG_UNUSED (continue_label))
{
return;
}
......@@ -429,7 +429,7 @@ extern struct c_declarator *build_array_declarator (location_t, tree,
bool, bool);
extern tree build_enumerator (location_t, location_t, struct c_enum_contents *,
tree, tree);
extern tree check_for_loop_decls (location_t);
extern tree check_for_loop_decls (location_t, bool);
extern void mark_forward_parm_decls (void);
extern void declare_parm_level (void);
extern void undeclared_variable (location_t, tree);
......
......@@ -20,6 +20,7 @@ several resources on the Internet that present the language.
* compatibility_alias::
* Exceptions::
* Synchronization::
* Fast enumeration::
@end menu
@node Executing code before main
......@@ -739,3 +740,218 @@ Because of the interactions between synchronization and exception
handling, you can only use @code{@@synchronized} when compiling with
exceptions enabled, that is with the command line option
@option{-fobjc-exceptions}.
@c =========================================================================
@node Fast enumeration
@section Fast enumeration
@menu
* Using fast enumeration::
* c99-like fast enumeration syntax::
* Fast enumeration details::
* Fast enumeration protocol::
@end menu
@c ================================
@node Using fast enumeration
@subsection Using fast enumeration
GNU Objective-C provides support for the fast enumeration syntax:
@smallexample
id array = @dots{};
id object;
for (object in array)
@{
/* Do something with 'object' */
@}
@end smallexample
@code{array} needs to be an Objective-C object (usually a collection
object, for example an array, a dictionary or a set) which implements
the ``Fast Enumeration Protocol'' (see below). If you are using a
Foundation library such as GNUstep Base or Apple Cocoa Foundation, all
collection objects in the library implement this protocol and can be
used in this way.
The code above would iterate over all objects in @code{array}. For
each of them, it assigns it to @code{object}, then executes the
@code{Do something with 'object'} statements.
Here is a fully worked-out example using a Foundation library (which
provides the implementation of @code{NSArray}, @code{NSString} and
@code{NSLog}):
@smallexample
NSArray *array = [NSArray arrayWithObjects: @@"1", @@"2", @@"3", nil];
NSString *object;
for (object in array)
NSLog (@@"Iterating over %@@", object);
@end smallexample
@c ================================
@node c99-like fast enumeration syntax
@subsection c99-like fast enumeration syntax
A c99-like declaration syntax is also allowed:
@smallexample
id array = @dots{};
for (id object in array)
@{
/* Do something with 'object' */
@}
@end smallexample
this is completely equivalent to:
@smallexample
id array = @dots{};
@{
id object;
for (object in array)
@{
/* Do something with 'object' */
@}
@}
@end smallexample
but can save some typing.
Note that the option @option{-std=c99} is not required to allow this
syntax in Objective-C.
@c ================================
@node Fast enumeration details
@subsection Fast enumeration details
Here is a more technical description with the gory details. Consider the code
@smallexample
for (@var{object expression} in @var{collection expression})
@{
@var{statements}
@}
@end smallexample
here is what happens when you run it:
@itemize @bullet
@item
@code{@var{collection expression}} is evaluated exactly once and the
result is used as the collection object to iterate over. This means
it is safe to write code such as @code{for (object in [NSDictionary
keyEnumerator]) @dots{}}.
@item
the iteration is implemented by the compiler by repeatedly getting
batches of objects from the collection object using the fast
enumeration protocol (see below), then iterating over all objects in
the batch. This is faster than a normal enumeration where objects are
retrieved one by one (hence the name ``fast enumeration'').
@item
if there are no objects in the collection, then
@code{@var{object expression}} is set to @code{nil} and the loop
immediately terminates.
@item
if there are objects in the collection, then for each object in the
collection (in the order they are returned) @code{@var{object expression}}
is set to the object, then @code{@var{statements}} are executed.
@item
@code{@var{statements}} can contain @code{break} and @code{continue}
commands, which will abort the iteration or skip to the next loop
iteration as expected.
@item
when the iteration ends because there are no more objects to iterate
over, @code{@var{object expression}} is set to @code{nil}. This allows
you to determine whether the iteration finished because a @code{break}
command was used (in which case @code{@var{object expression}} will remain
set to the last object that was iterated over) or because it iterated
over all the objects (in which case @code{@var{object expression}} will be
set to @code{nil}).
@item
@code{@var{statements}} must not make any changes to the collection
object; if they do, it is a hard error and the fast enumeration
terminates by invoking @code{objc_enumerationMutation}, a runtime
function that normally aborts the program but which can be customized
by Foundation libraries via @code{objc_set_mutation_handler} to do
something different, such as raising an exception.
@end itemize
@c ================================
@node Fast enumeration protocol
@subsection Fast enumeration protocol
If you want your own collection object to be usable with fast
enumeration, you need to have it implement the method
@smallexample
- (unsigned long) countByEnumeratingWithState: (NSFastEnumerationState *)state
objects: (id *)objects
count: (unsigneld long)len;
@end smallexample
where @code{NSFastEnumerationState} must be defined in your code as follows:
@smallexample
typdef struct
@{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
@} NSFastEnumerationState;
@end smallexample
If no @code{NSFastEnumerationState} is defined in your code, the
compiler will automatically replace @code{NSFastEnumerationState *}
with @code{struct __objcFastEnumerationState *}, where that type is
silently defined by the compiler in an identical way. This can be
confusing and we recommend that you define
@code{NSFastEnumerationState} (as shown above) instead.
The method is called repeatedly during a fast enumeration to retrieve
batches of objects. Each invocation of the method should retrieve the
next batch of objects.
The return value of the method is the number of objects in the current
batch; this should not exceed @code{len}, which is the maximum size of
a batch as requested by the caller. The batch itself is returned in
the @code{itemsPtr} field of the @code{NSFastEnumerationState} struct.
To help with returning the objects, the @code{objects} array is a C
array preallocated by the caller (on the stack) of size @code{len}.
In many cases you can put the objects you want to return in that
@code{objects} array, then do @code{itemsPtr = objects}. But you
don't have to; if your collection already has the objects to return in
some form of C array, it could return them from there instead.
The @code{state} and @code{extra} fields of the
@code{NSFastEnumerationState} structure allows your collection object
to keep track of the state of the enumeration. In a simple array
implementation, @code{state} may keep track of the index of the last
object that was returned, and @code{extra} may be unused.
The @code{mutationsPtr} field of the @code{NSFastEnumerationState} is
used to keep track of mutations. It should point to a number; before
working on each object, the fast enumeration loop will check that this
number has not changed. If it has, a mutation has happened and the
fast enumeration will abort. So, @code{mutationsPtr} could be set to
point to some sort of version number of your collection, which is
increased by one every time there is a change (for example when an
object is added or removed). Or, if you are content with less strict
mutation checks, it could point to the number of objects in your
collection or some other value that can be checked to perform an
approximate check that the collection has not been mutated.
2010-10-06 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented fast enumeration for Objective-C.
* objc-act.c (build_fast_enumeration_state_template): New.
(TAG_ENUMERATION_MUTATION): New.
(TAG_FAST_ENUMERATION_STATE): New.
(synth_module_prologue): Call build_fast_enumeration_state_template() and set up
objc_enumeration_mutation_decl.
(objc_create_temporary_var): Allow providing a name to temporary
variables.
(objc_build_exc_ptr): Updated calls to
objc_create_temporary_var().
(next_sjlj_build_try_catch_finally): Same change.
(objc_finish_foreach_loop): New.
* objc-act.h: Added OCTI_FAST_ENUM_STATE_TEMP,
OCTI_ENUM_MUTATION_DECL, objc_fast_enumeration_state_template,
objc_enumeration_mutation_decl.
Merge from 'apple/trunk' branch on FSF servers.
2006-04-12 Fariborz Jahanian <fjahanian@apple.com>
Radar 4507230
* objc-act.c (objc_type_valid_for_messaging): New routine to check
for valid objc object types.
(objc_finish_foreach_loop): Check for invalid objc objects in
foreach header.
2010-10-05 Nicola Pero <nicola.pero@meta-innovation.com>
Merge from 'apple/trunk' branch on FSF servers.
......@@ -5,8 +33,8 @@
2005-10-17 Fariborz Jahanian <fjahanian@apple.com>
Radar 4290840
* objc-act.c (objc_start_method_definition): Check for error_mark_node for
the selector name and make a quick exit.
* objc-act.c (objc_start_method_definition): Check for
error_mark_node for the selector name and make a quick exit.
2010-10-04 Andi Kleen <ak@linux.intel.com>
......
......@@ -269,6 +269,9 @@ enum objc_tree_index
OCTI_ASSIGN_GLOBAL_DECL,
OCTI_ASSIGN_STRONGCAST_DECL,
OCTI_FAST_ENUM_STATE_TEMP,
OCTI_ENUM_MUTATION_DECL,
OCTI_MAX
};
......@@ -433,5 +436,9 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define string_class_decl objc_global_trees[OCTI_STRING_CLASS_DECL]
#define internal_const_str_type objc_global_trees[OCTI_INTERNAL_CNST_STR_TYPE]
#define UOBJC_SUPER_decl objc_global_trees[OCTI_SUPER_DECL]
#define objc_fast_enumeration_state_template \
objc_global_trees[OCTI_FAST_ENUM_STATE_TEMP]
#define objc_enumeration_mutation_decl \
objc_global_trees[OCTI_ENUM_MUTATION_DECL]
#endif /* GCC_OBJC_ACT_H */
2010-10-05 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented fast enumeration for Objective-C.
* objc.dg/foreach-1.m: New.
* objc.dg/foreach-2.m: New.
* objc.dg/foreach-3.m: New.
* objc.dg/foreach-4.m: New.
* objc.dg/foreach-5.m: New.
* objc.dg/foreach-6.m: New.
* objc.dg/foreach-7.m: New.
Merge from 'apple/trunk' branch on FSF servers:
2006-04-13 Fariborz Jahanian <fjahanian@apple.com>
Radar 4502236
* objc.dg/objc-foreach-5.m: New.
2006-04-12 Fariborz Jahanian <fjahanian@apple.com>
Radar 4507230
* objc.dg/objc-foreach-4.m: New.
2006-03-13 Fariborz Jahanian <fjahanian@apple.com>
Radar 4472881
* objc.dg/objc-foreach-3.m: New.
2005-03-07 Fariborz Jahanian <fjahanian@apple.com>
Radar 4468498
* objc.dg/objc-foreach-2.m: New.
2006-02-15 Fariborz Jahanian <fjahanian@apple.com>
Radar 4294910
* objc.dg/objc-foreach-1.m: New
2010-10-06 Hariharan Sandanagobalane <hariharan@picochip.com>
* gcc.c-torture/execute/cmpsi-2.c : Unsigned comparisons should use
unsigned values.
2010-10-05 Nicola Pero <nicola.pero@meta-innovation.com>
PR objc++/28050
......
/* Test basic Objective-C foreach syntax. This tests iterations that
do nothing.
*/
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort (void);
/*
struct __objcFastEnumerationState
{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
};
*/
@interface Object (NSFastEnumeration)
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
objects:(id *)stackbuf
count:(unsigned int)len;
@end
int main (void)
{
int test_variable = 0;
int counter = 0;
id array = nil;
id object = nil;
/* Test that 'for (object in array)' is recognized and that nothing
happens if array is nil. */
for (object in array)
test_variable = 8;
if (test_variable == 8)
abort ();
if (object != nil)
abort ();
/* Test that if nothing is done, object is set to nil. */
object = [Object new];
for (object in array)
;
if (object != nil)
abort ();
/* Test that you can reference 'object' inside the body. */
for (object in array)
object = nil;
if (object != nil)
abort ();
/* Test that 'for (id element in array) is recognized (and works). */
for (id element in array)
test_variable = 8;
if (test_variable == 8)
abort ();
/* Test that you can reference 'object' inside the body. */
for (id element in array)
element = nil;
/* Test that C for loops still work. */
test_variable = 0;
for (counter = 0; counter < 4; counter++)
test_variable++;
if (test_variable != 4)
abort ();
return 0;
}
/* Test basic Objective-C foreach syntax. This tests iterations, with
the basic syntax 'for (object in array) statements'
*/
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
#include <objc/NXConstStr.h>
#include <stdlib.h>
extern void abort (void);
/*
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 : Object
{
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 : Object
- (id) initWithLength: (unsigned int)l
objects: (id *)o
{
length = l;
objects = o;
mutated = 0;
}
- (void) mutate
{
mutated = 1;
}
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state
objects: (id*)stackbuf
count: (unsigned long)len
{
unsigned long i, batch_size;
/* 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;
state->mutationsPtr = &mutated;
return batch_size;
}
@end
int main (void)
{
MyArray *array;
Object *object;
int test_variable, counter, i;
id *objects;
array = [[MyArray alloc] initWithLength: 0
objects: NULL];
/* Test that an empty array does nothing. */
for (object in array)
abort ();
if (object != nil)
abort ();
/* Test iterating over 1 object. */
objects = malloc (sizeof (id) * 1);
objects[0] = @"One Object";
array = [[MyArray alloc] initWithLength: 1
objects: objects];
for (object in array)
printf ("%p\n", object);
/* Test iterating over 20 objects. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
for (object in array)
printf ("%p\n", object);
/* Test iterating over 200 objects. */
objects = malloc (sizeof (id) * 200);
for (i = 0; i < 200; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 200
objects: objects];
counter = 0;
for (object in array)
{
if (object != nil)
counter++;
}
if (counter != 200)
abort ();
printf ("Counter was %d (should be 200)\n", counter);
/* Test iterating again over the same array. */
counter = 0;
for (object in array)
{
if (object != nil)
counter++;
}
if (counter != 200)
abort ();
printf ("Counter was %d (should be 200)\n", counter);
/* Test nested iterations. */
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)
{
id another_object;
for (another_object in array)
if (another_object != nil)
counter++;
}
printf ("Counter was %d (should be 400)\n", counter);
if (counter != 400)
abort ();
/* Test 'continue'. */
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)
{
if (counter == 15)
continue;
counter++;
}
printf ("Counter was %d (should be 15)\n", counter);
if (counter != 15)
abort ();
/* Test 'break'. */
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++;
if (counter == 15)
break;
}
printf ("Counter was %d (should be 15)\n", counter);
if (counter != 15)
abort ();
/* Test 'break' and 'continue' in nested iterations. */
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)
{
int local_counter = 0;
id another_object;
/* Each internal loop should increase counter by 24. */
for (another_object in array)
{
local_counter++;
if (local_counter == 10)
{
counter = counter + 20;
break;
}
if (local_counter >= 5)
continue;
counter++;
}
/* Exit after 4 iterations. */
if (counter == 96)
break;
}
printf ("Counter was %d (should be 96)\n", counter);
if (counter != 96)
abort ();
/* Test that if we 'break', the object is set to the last one, while
if we run out of objects, it is set to 'nil'. */
for (object in array)
;
if (object != nil)
abort ();
for (object in array)
break;
if (object == nil)
abort ();
/* Test that C for loops still work. */
test_variable = 0;
for (counter = 0; counter < 4; counter++)
test_variable++;
if (test_variable != 4)
abort ();
return 0;
}
/* Test basic Objective-C foreach syntax. This tests the mutation.
*/
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* 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 ?
*/
/* { dg-do compile } */
#include <objc/objc.h>
#include <objc/Object.h>
#include <objc/NXConstStr.h>
#include <stdlib.h>
extern void abort (void);
/*
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 : Object
{
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 : Object
- (id) initWithLength: (unsigned int)l
objects: (id *)o
{
length = l;
objects = o;
mutated = 0;
}
- (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;
Object *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;
}
/* Test basic Objective-C foreach syntax. This tests iterations, with
the declaration syntax 'for (id object in array) statements'
*/
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
#include <objc/NXConstStr.h>
#include <stdlib.h>
extern void abort (void);
/*
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 : Object
{
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 : Object
- (id) initWithLength: (unsigned int)l
objects: (id *)o
{
length = l;
objects = o;
mutated = 0;
}
- (void) mutate
{
mutated = 1;
}
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state
objects: (id*)stackbuf
count: (unsigned long)len
{
unsigned long i, batch_size;
/* 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;
state->mutationsPtr = &mutated;
return batch_size;
}
@end
int main (void)
{
MyArray *array;
int test_variable, counter, i;
id *objects;
array = [[MyArray alloc] initWithLength: 0
objects: NULL];
/* Test that an empty array does nothing. */
for (id object in array)
abort ();
/* Test iterating over 1 object. */
objects = malloc (sizeof (id) * 1);
objects[0] = @"One Object";
array = [[MyArray alloc] initWithLength: 1
objects: objects];
for (id object in array)
printf ("%p\n", object);
/* Test iterating over 20 objects. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
for (id object in array)
printf ("%p\n", object);
/* Test iterating over 200 objects. */
objects = malloc (sizeof (id) * 200);
for (i = 0; i < 200; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 200
objects: objects];
counter = 0;
for (id object in array)
{
if (object != nil)
counter++;
}
if (counter != 200)
abort ();
printf ("Counter was %d (should be 200)\n", counter);
/* Test iterating again over the same array. */
counter = 0;
for (id object in array)
{
if (object != nil)
counter++;
}
if (counter != 200)
abort ();
printf ("Counter was %d (should be 200)\n", counter);
/* Test nested iterations. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
for (id another_object in array)
if (another_object != nil)
counter++;
}
printf ("Counter was %d (should be 400)\n", counter);
if (counter != 400)
abort ();
/* Test 'continue'. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
if (counter == 15)
continue;
counter++;
}
printf ("Counter was %d (should be 15)\n", counter);
if (counter != 15)
abort ();
/* Test 'break'. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
counter++;
if (counter == 15)
break;
}
printf ("Counter was %d (should be 15)\n", counter);
if (counter != 15)
abort ();
/* Test 'break' and 'continue' in nested iterations. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
int local_counter = 0;
/* Each internal loop should increase counter by 24. */
for (id another_object in array)
{
local_counter++;
if (local_counter == 10)
{
counter = counter + 20;
break;
}
if (local_counter >= 5)
continue;
counter++;
}
/* Exit after 4 iterations. */
if (counter == 96)
break;
}
printf ("Counter was %d (should be 96)\n", counter);
if (counter != 96)
abort ();
/* Test that C for loops still work. */
test_variable = 0;
for (counter = 0; counter < 4; counter++)
test_variable++;
if (test_variable != 4)
abort ();
return 0;
}
/* Test basic Objective-C foreach syntax. This tests that if you
define your own NSFastEnumeration struct, the compiler picks it up.
*/
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
#include <objc/NXConstStr.h>
#include <stdlib.h>
extern void abort (void);
typedef struct
{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
} NSFastEnumerationState;
/* 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 : Object
{
unsigned int length;
id *objects;
unsigned long mutated;
}
- (id) initWithLength: (unsigned int)l objects: (id *)o;
- (void) mutate;
- (unsigned long)countByEnumeratingWithState: (NSFastEnumerationState *)state
objects:(id *)stackbuf
count:(unsigned long)len;
@end
@implementation MyArray : Object
- (id) initWithLength: (unsigned int)l
objects: (id *)o
{
length = l;
objects = o;
mutated = 0;
}
- (void) mutate
{
mutated = 1;
}
- (unsigned long)countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (id*)stackbuf
count: (unsigned long)len
{
unsigned long i, batch_size;
/* 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;
state->mutationsPtr = &mutated;
return batch_size;
}
@end
int main (void)
{
MyArray *array;
int test_variable, counter, i;
id *objects;
array = [[MyArray alloc] initWithLength: 0
objects: NULL];
/* Test that an empty array does nothing. */
for (id object in array)
abort ();
/* Test iterating over 1 object. */
objects = malloc (sizeof (id) * 1);
objects[0] = @"One Object";
array = [[MyArray alloc] initWithLength: 1
objects: objects];
for (id object in array)
printf ("%p\n", object);
/* Test iterating over 20 objects. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
for (id object in array)
printf ("%p\n", object);
/* Test iterating over 200 objects. */
objects = malloc (sizeof (id) * 200);
for (i = 0; i < 200; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 200
objects: objects];
counter = 0;
for (id object in array)
{
if (object != nil)
counter++;
}
if (counter != 200)
abort ();
printf ("Counter was %d (should be 200)\n", counter);
/* Test iterating again over the same array. */
counter = 0;
for (id object in array)
{
if (object != nil)
counter++;
}
if (counter != 200)
abort ();
printf ("Counter was %d (should be 200)\n", counter);
/* Test nested iterations. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
for (id another_object in array)
if (another_object != nil)
counter++;
}
printf ("Counter was %d (should be 400)\n", counter);
if (counter != 400)
abort ();
/* Test 'continue'. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
if (counter == 15)
continue;
counter++;
}
printf ("Counter was %d (should be 15)\n", counter);
if (counter != 15)
abort ();
/* Test 'break'. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
counter++;
if (counter == 15)
break;
}
printf ("Counter was %d (should be 15)\n", counter);
if (counter != 15)
abort ();
/* Test 'break' and 'continue' in nested iterations. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (id object in array)
{
int local_counter = 0;
/* Each internal loop should increase counter by 24. */
for (id another_object in array)
{
local_counter++;
if (local_counter == 10)
{
counter = counter + 20;
break;
}
if (local_counter >= 5)
continue;
counter++;
}
/* Exit after 4 iterations. */
if (counter == 96)
break;
}
printf ("Counter was %d (should be 96)\n", counter);
if (counter != 96)
abort ();
/* Test that C for loops still work. */
test_variable = 0;
for (counter = 0; counter < 4; counter++)
test_variable++;
if (test_variable != 4)
abort ();
return 0;
}
/* Test basic Objective-C foreach syntax. This tests warnings and errors. */
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* { dg-do compile } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort (void);
/*
struct __objcFastEnumerationState
{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
};
*/
@interface Object (NSFastEnumeration)
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
objects:(id *)stackbuf
count:(unsigned int)len;
- (id) enumerator;
@end
int main (void)
{
id array = nil;
id object = nil;
for (object in array) /* Ok */
;
for (object in nil) /* Ok */
;
for (object in) /* { dg-error "missing collection in fast enumeration" } */
;
for (object = nil in array) /* { dg-error "invalid iterating variable in fast enumeration" } */
;
for (object in [object enumerator]) /* Ok */
;
for (12 in array) /* { dg-error "invalid iterating variable in fast enumeration" } */
; /* { dg-error "iterating variable in fast enumeration is not an object" } */
for (object in 12)
; /* { dg-error "collection in fast enumeration is not an object" } */
return 0;
}
/* Test basic Objective-C foreach syntax. This tests warnings and errors. */
/* FIXME: Run this test with the NeXT runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
/* { dg-do compile } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort (void);
/*
struct __objcFastEnumerationState
{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
};
*/
@interface Object (NSFastEnumeration)
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
objects:(id *)stackbuf
count:(unsigned int)len;
- (id) enumerator;
@end
void function (void)
{
return;
}
id object_function (void)
{
return nil;
}
int main (void)
{
id array = nil;
id object = nil;
for (typedef int my_typedef in array) /* { dg-error "declaration of non-variable" } */
; /* { dg-error "iterating variable in fast enumeration is not an object" } */
for (function () in nil) /* { dg-error "invalid iterating variable in fast enumeration" } */
; /* { dg-error "iterating variable in fast enumeration is not an object" } */
for (object_function () in nil) /* { dg-error "invalid iterating variable in fast enumeration" } */
;
for ([object enumerator] in array) /* { dg-error "invalid iterating variable in fast enumeration" } */
;
for (object = nil in array) /* { dg-error "invalid iterating variable in fast enumeration" } */
;
for (id key, value in array) /* { dg-error "multiple iterating variables in fast enumeration" } */
;
return 0;
}
/* Syntax check for the new foreach statement. */
/* { dg-do compile } */
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
@interface MyList
@end
@implementation MyList
- (unsigned int)countByEnumeratingWithState:(struct __objcFastEnumerationState *)state objects:(id *)items count:(unsigned int)stackcount
{
return 0;
}
- (void)addObject:object {
}
@end
@interface MyList (BasicTest)
- (void)compilerTestAgainst;
@end
void BEGIN();
void INFORLOOP();
void END();
@implementation MyList (BasicTest)
- (void)compilerTestAgainst {
BEGIN();
for (id elem in (self))
if (elem)
INFORLOOP();
END();
}
@end
/* Syntax check for the new foreach statement. */
/* { dg-do compile } */
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
@interface MyList
@end
@implementation MyList
- (unsigned int)countByEnumeratingWithState:(struct __objcFastEnumerationState *)state objects:(id *)items count:(unsigned int)stackcount
{
return 0;
}
- (void)addObject:object {
}
@end
@interface MyList (BasicTest)
- (void)compilerTestAgainst;
@end
void BEGIN();
void INFORLOOP();
void END();
@implementation MyList (BasicTest)
- (void)compilerTestAgainst {
id elem;
BEGIN();
for (elem in (self))
if (elem)
INFORLOOP();
END();
}
@end
/* Syntax check for the new foreach statement.
Use of declaration in loop-header without requiring c99 mode. */
/* { dg-do compile } */
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
@interface MyList
@end
@implementation MyList
- (unsigned int)countByEnumeratingWithState:(struct __objcFastEnumerationState *)state objects:(id *)items count:(unsigned int)stackcount
{
return 0;
}
- (void)addObject:object {
}
@end
@interface MyList (BasicTest)
- (void)compilerTestAgainst;
@end
void BEGIN();
void INFORLOOP();
void END();
@implementation MyList (BasicTest)
- (void)compilerTestAgainst {
BEGIN();
for (id elem in (self))
if (elem)
INFORLOOP();
END();
}
@end
/* Test for valid objc objects used in a for-each statement. */
/* FIXME: Run this test with the GNU runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-do compile { target *-*-darwin* } } */
#include <Foundation/Foundation.h>
// gcc -o foo foo.m -framework Foundation
int main (int argc, char const* argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray * arr = [NSArray arrayWithObjects:@"A", @"B", @"C", nil];
for (NSString * foo in arr) {
NSLog(@"foo is %@", foo);
}
[pool release];
return 0;
}
/* FIXME: Run this test with the GNU runtime as well. */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-do compile { target *-*-darwin* } } */
#import <Foundation/Foundation.h>
NSArray * createTestVictim(unsigned capacity) {
NSMutableArray * arr = [[NSMutableArray alloc] initWithCapacity:capacity];
int x = 0;
for(x = 0; x < capacity; x++) {
NSNumber * num = [NSNumber numberWithInteger:x];
[arr addObject:num];
}
NSArray * immutableCopy = [arr copy];
[arr release];
return immutableCopy;
}
void addStuffUp(NSArray * values) {
NSInteger accumulator = 0;
// for (id item in values) {
id item;
for (item in values) {
accumulator += [item integerValue];
}
}
int main (int argc, char const* argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray * target = createTestVictim(10);
addStuffUp(target);
[pool release];
return 0;
}
/* { dg-final { scan-assembler "_addStuffUp:" } } */
2010-10-06 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented fast enumeration for Objective-C.
* Makefile.in (C_SOURCE_FILES): Added objc-foreach.c.
(OBJC_H): Added runtime.h
* objc-foreach.c: New file.
* objc/runtime.h: New file.
2010-09-30 Kai Tietz <kai.tietz@onevision.com>
* objc/deprecated/struct_objc_class.h: Add padding
......
......@@ -120,6 +120,7 @@ OBJC_H = \
message.h \
objc-api.h \
objc-decls.h \
runtime.h \
thr.h \
\
hash.h \
......@@ -163,6 +164,7 @@ C_SOURCE_FILES = \
init.c \
memory.c \
nil_method.c \
objc-foreach.c \
objc-sync.c \
objects.c \
sarray.c \
......
/* GNU Objective C Runtime 'fast enumeration' implementation
Copyright (C) 2010 Free Software Foundation, Inc.
Contributed by Nicola Pero <nicola.pero@meta-innovation.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/*
This file implements objc_enumeration_mutation() and
objc_set_enumeration_mutation_handler(), the two functions required
to handle mutations during a fast enumeration.
*/
#include "objc/runtime.h" /* For objc_enumerationMutation() and objc_set_enumeration_mutation_handler() */
#include "objc-private/error.h" /* For _objc_abort() */
/* The enumeration mutation handler currently in use. */
static void (*__objc_enumeration_mutation_handler)(id) = NULL;
void
objc_set_enumeration_mutation_handler (void (*handler)(id))
{
__objc_enumeration_mutation_handler = handler;
}
void
objc_enumerationMutation (id collection)
{
if (__objc_enumeration_mutation_handler != NULL)
(*__objc_enumeration_mutation_handler) (collection);
/* We always abort if we get here; there is no point in going on as
the next iteration in the fast enumeration would probably go
deeply wrong. */
_objc_abort ("Collection %p mutated during fast enumeration", collection);
}
/* GNU Objective-C Runtime API.
Copyright (C) 2010 Free Software Foundation, Inc.
Contributed by Nicola Pero <nicola.pero@meta-innovation.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef __objc_runtime_INCLUDE_GNU
#define __objc_runtime_INCLUDE_GNU
#include "objc.h"
/* The following is temporary, until all code from objc-api.h has been
moved into this file and objc-api.h will include runtime.h. */
#include "objc-api.h"
/* 'objc_enumerationMutation()' is called when a collection is
mutated while being "fast enumerated". That is a hard error, and
objc_enumerationMutation is called to deal with it. 'collection'
is the collection object that was mutated during an enumeration.
objc_enumerationMutation() will invoke the mutation handler if any
is set. Then, it will abort the program.
Compatibility note: the Apple runtime will not abort the program
after calling the mutation handler.
*/
objc_EXPORT void objc_enumerationMutation (id collection);
/* 'objc_set_enumeration_mutation_handler' can be used to set a
function that will be called (instead of aborting) when a fast
enumeration is mutated during enumeration. The handler will be
called with the 'collection' being mutated as the only argument and
it should not return; it should either exit the program, or could
throw an exception. The recommended implementation is to throw an
exception - the user can then use exception handlers to deal with
it.
This function is not thread safe (other threads may be trying to
invoke the enumeration mutation handler while you are changing it!)
and should be called during during the program initialization
before threads are started. It is mostly reserved for "Foundation"
libraries; in the case of GNUstep, GNUstep Base may be using this
function to improve the standard enumeration mutation handling.
You probably shouldn't use this function unless you are writing
your own Foundation library.
*/
objc_EXPORT void objc_set_enumeration_mutation_handler (void (*handler)(id));
/* This structure (used during fast enumeration) is automatically
defined by the compiler (it is as if this definition was always
included in all Objective-C files). Note that it is usually
defined again with the name of NSFastEnumeration by "Foundation"
libraries such as GNUstep Base. And if NSFastEnumeration is
defined, the compiler will use it instead of
__objcFastEnumerationState when doing fast enumeration.
*/
/*
struct __objcFastEnumerationState
{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
};
*/
/* For compatibility with the Apple/NeXT runtime. */
#define objc_setEnumerationMutationHandler objc_set_enumeration_mutation_handler
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment