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

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

        Implemented Objective-C 2.0 property accessors. 
        * objc-act.h (enum objc_tree_index): Added OCTI_GET_PROPERTY_DECL,
        OCTI_SET_PROPERTY_DECL, OCTI_COPY_STRUCT_DECL,
        OCTI_GET_PROPERTY_STRUCT_DECL and OCTI_SET_PROPERTY_STRUCT_DECL.
        (objc_getProperty_decl): New.
        (objc_setProperty_decl): New.
        (objc_copyStruct_decl): New.
        (objc_getPropertyStruct_decl): New.
        (objc_setPropertyStruct_decl): New.
        * objc-act.c (build_objc_property_accessor_helpers): New.
        (synth_module_prologue): Call
        build_objc_property_accessor_helpers.
        (lookup_ivar): New.
        (objc_synthesize_getter): Implemented synthesizing getters that
        work with properties that are not nonatomic, assign properties.
        (objc_synthesize_setter): Implemented synthesizing setters that
        work with properties that are not nonatomic, assign properties.

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

        Implemented Objective-C 2.0 property accessors.
        * objc.dg/property/at-property-6.m: Use nonatomic properties to
        avoid testing more complex accessors in this testcase which is not
        about them.
        * objc.dg/property/at-property-7.m: Same change.
        * objc.dg/property/at-property-8.m: Same change.
        * objc.dg/property/at-property-9.m: Same change.
        * objc.dg/property/at-property-10.m: Same change.
        * objc.dg/property/at-property-11.m: Same change.
        * obj-c++.dg/property/at-property-6.mm: Same change.
        * obj-c++.dg/property/at-property-7.mm: Same change.
        * obj-c++.dg/property/at-property-8.mm: Same change.
        * obj-c++.dg/property/at-property-9.mm: Same change.
        * obj-c++.dg/property/at-property-10.mm: Same change.
        * obj-c++.dg/property/at-property-11.mm: Same change.
        * objc.dg/property/at-property-12.m: New.
        * objc.dg/property/at-property-13.m: New.
        * obj-c++.dg/property/at-property-12.mm: New.
        * obj-c++.dg/property/at-property-13.mm: New.

From-SVN: r166143
This commit is contained in:
Nicola Pero 2010-11-01 20:06:36 +00:00 committed by Nicola Pero
parent 1fccc6c346
commit 8f07a2aa35
20 changed files with 703 additions and 52 deletions

View File

@ -1,3 +1,23 @@
2010-11-01 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented Objective-C 2.0 property accessors.
* objc-act.h (enum objc_tree_index): Added OCTI_GET_PROPERTY_DECL,
OCTI_SET_PROPERTY_DECL, OCTI_COPY_STRUCT_DECL,
OCTI_GET_PROPERTY_STRUCT_DECL and OCTI_SET_PROPERTY_STRUCT_DECL.
(objc_getProperty_decl): New.
(objc_setProperty_decl): New.
(objc_copyStruct_decl): New.
(objc_getPropertyStruct_decl): New.
(objc_setPropertyStruct_decl): New.
* objc-act.c (build_objc_property_accessor_helpers): New.
(synth_module_prologue): Call
build_objc_property_accessor_helpers.
(lookup_ivar): New.
(objc_synthesize_getter): Implemented synthesizing getters that
work with properties that are not nonatomic, assign properties.
(objc_synthesize_setter): Implemented synthesizing setters that
work with properties that are not nonatomic, assign properties.
2010-10-30 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented Objective-C 2.0 @property, @synthesize and @dynamic.

View File

@ -178,6 +178,7 @@ static int match_proto_with_proto (tree, tree, int);
static tree lookup_property (tree, tree);
static tree lookup_property_in_list (tree, tree);
static tree lookup_property_in_protocol_list (tree, tree);
static void build_objc_property_accessor_helpers (void);
static void objc_xref_basetypes (tree, tree);
@ -2348,6 +2349,10 @@ synth_module_prologue (void)
build_category_template ();
build_objc_exception_stuff ();
/* Declare objc_getProperty, object_setProperty and other property
accessor helpers. */
build_objc_property_accessor_helpers ();
if (flag_next_runtime)
build_next_objc_exception_stuff ();
@ -7938,6 +7943,7 @@ add_instance_variable (tree klass, objc_ivar_visibility_kind visibility,
return klass;
}
static tree
is_ivar (tree decl_chain, tree ident)
{
@ -8516,11 +8522,120 @@ objc_build_property_setter_name (tree ident)
return string;
}
/* This routine prepares the declarations of the property accessor
helper functions (objc_getProperty(), etc) that are used when
@synthesize is used. */
static void
build_objc_property_accessor_helpers (void)
{
tree type;
/* Declare the following function:
id
objc_getProperty (id self, SEL _cmd,
ptrdiff_t offset, BOOL is_atomic); */
type = build_function_type_list (objc_object_type,
objc_object_type,
objc_selector_type,
ptrdiff_type_node,
boolean_type_node,
NULL_TREE);
objc_getProperty_decl = add_builtin_function ("objc_getProperty",
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
TREE_NOTHROW (objc_getProperty_decl) = 0;
/* Declare the following function:
void
objc_setProperty (id self, SEL _cmd,
ptrdiff_t offset, id new_value,
BOOL is_atomic, BOOL should_copy); */
type = build_function_type_list (void_type_node,
objc_object_type,
objc_selector_type,
ptrdiff_type_node,
objc_object_type,
boolean_type_node,
boolean_type_node,
NULL_TREE);
objc_setProperty_decl = add_builtin_function ("objc_setProperty",
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
TREE_NOTHROW (objc_setProperty_decl) = 0;
/* This is the type of all of the following functions
(objc_copyStruct(), objc_getPropertyStruct() and
objc_setPropertyStruct()). */
type = build_function_type_list (void_type_node,
ptr_type_node,
const_ptr_type_node,
ptrdiff_type_node,
boolean_type_node,
boolean_type_node,
NULL_TREE);
if (flag_next_runtime)
{
/* Declare the following function:
void
objc_copyStruct (void *destination, const void *source,
ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
TREE_NOTHROW (objc_copyStruct_decl) = 0;
objc_getPropertyStruct_decl = NULL_TREE;
objc_setPropertyStruct_decl = NULL_TREE;
}
else
{
objc_copyStruct_decl = NULL_TREE;
/* Declare the following function:
void
objc_getPropertyStruct (void *destination, const void *source,
ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
/* Declare the following function:
void
objc_setPropertyStruct (void *destination, const void *source,
ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
}
}
/* This looks up an ivar in a class (including superclasses). */
static tree
lookup_ivar (tree interface, tree instance_variable_name)
{
while (interface)
{
tree decl_chain;
for (decl_chain = CLASS_IVARS (interface); decl_chain; decl_chain = DECL_CHAIN (decl_chain))
if (DECL_NAME (decl_chain) == instance_variable_name)
return decl_chain;
/* Not found. Search superclass if any. */
if (CLASS_SUPER_NAME (interface))
interface = lookup_interface (CLASS_SUPER_NAME (interface));
}
return NULL_TREE;
}
/* This routine synthesizes a 'getter' method. This is only called
for @synthesize properties. */
static void
objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
objc_synthesize_getter (tree klass, tree class_method, tree property)
{
location_t location = DECL_SOURCE_LOCATION (property);
tree fn, decl;
tree body;
tree ret_val;
@ -8543,29 +8658,150 @@ objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro
/* Adapt the 'decl'. Use the source location of the @synthesize
statement for error messages. */
decl = copy_node (decl);
DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property);
DECL_SOURCE_LOCATION (decl) = location;
objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
body = c_begin_compound_stmt (true);
/* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as
appropriate. The following code just always does direct ivar
access. */
/* Now we need to decide how we build the getter. There are three
cases:
/* return self->_property_name; */
for 'copy' or 'retain' properties we need to use the
objc_getProperty() accessor helper which knows about retain and
copy. It supports both 'nonatomic' and 'atomic' access.
for 'nonatomic, assign' properties we can access the instance
variable directly. 'nonatomic' means we don't have to use locks,
and 'assign' means we don't have to worry about retain or copy.
If you combine the two, it means we can just access the instance
variable directly.
for 'atomic, assign' properties we use objc_copyStruct() (for the
next runtime) or objc_getPropertyStruct() (for the GNU runtime). */
switch (PROPERTY_ASSIGN_SEMANTICS (property))
{
case OBJC_PROPERTY_RETAIN:
case OBJC_PROPERTY_COPY:
{
/* We build "return objc_getProperty (self, _cmd, offset, is_atomic);" */
tree cmd, ivar, offset, is_atomic;
cmd = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
/* Find the ivar to compute the offset. */
ivar = lookup_ivar (klass, PROPERTY_IVAR_NAME (property));
if (!ivar || is_private (ivar))
{
/* This should never happen. */
error_at (location,
"can not find instance variable associated with property");
ret_val = error_mark_node;
break;
}
offset = byte_position (ivar);
if (PROPERTY_NONATOMIC (property))
is_atomic = boolean_false_node;
else
is_atomic = boolean_true_node;
ret_val = build_function_call
(location,
/* Function prototype. */
objc_getProperty_decl,
/* Parameters. */
tree_cons /* self */
(NULL_TREE, self_decl,
tree_cons /* _cmd */
(NULL_TREE, cmd,
tree_cons /* offset */
(NULL_TREE, offset,
tree_cons /* is_atomic */
(NULL_TREE, is_atomic, NULL_TREE)))));
}
break;
case OBJC_PROPERTY_ASSIGN:
if (PROPERTY_NONATOMIC (property))
{
/* We build "return self->PROPERTY_IVAR_NAME;" */
ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
break;
}
else
{
/* We build
<property type> __objc_property_temp;
objc_getPropertyStruct (&__objc_property_temp,
&(self->PROPERTY_IVAR_NAME),
sizeof (type of self->PROPERTY_IVAR_NAME),
is_atomic,
false)
return __objc_property_temp;
For the NeXT runtime, we need to use objc_copyStruct
instead of objc_getPropertyStruct. */
tree objc_property_temp_decl, function_decl, function_call;
tree size_of, is_atomic;
objc_property_temp_decl = objc_create_temporary_var (TREE_TYPE (property), "__objc_property_temp");
DECL_SOURCE_LOCATION (objc_property_temp_decl) = location;
objc_property_temp_decl = lang_hooks.decls.pushdecl (objc_property_temp_decl);
/* sizeof (ivar type). Since the ivar and the property have
the same type, there is no need to lookup the ivar. */
size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property),
true /* is_sizeof */,
false /* complain */);
if (PROPERTY_NONATOMIC (property))
is_atomic = boolean_false_node;
else
is_atomic = boolean_true_node;
if (flag_next_runtime)
function_decl = objc_copyStruct_decl;
else
function_decl = objc_getPropertyStruct_decl;
function_call = build_function_call
(location,
/* Function prototype. */
function_decl,
/* Parameters. */
tree_cons /* &__objc_property_temp_decl */
/* Warning: note that using build_fold_addr_expr_loc()
here causes invalid code to be generated. */
(NULL_TREE, build_unary_op (location, ADDR_EXPR, objc_property_temp_decl, 0),
tree_cons /* &(self->PROPERTY_IVAR_NAME); */
(NULL_TREE, build_fold_addr_expr_loc (location,
objc_lookup_ivar
(NULL_TREE, PROPERTY_IVAR_NAME (property))),
tree_cons /* sizeof (PROPERTY_IVAR) */
(NULL_TREE, size_of,
tree_cons /* is_atomic */
(NULL_TREE, is_atomic,
/* TODO: This is currently ignored by the GNU
runtime, but what about the next one ? */
tree_cons /* has_strong */
(NULL_TREE, boolean_true_node, NULL_TREE))))));
add_stmt (function_call);
ret_val = objc_property_temp_decl;
}
break;
default:
gcc_unreachable ();
}
/* PROPERTY_IVAR_NAME is always defined if we got here, and should
be a valid instance variable. */
ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
gcc_assert (ret_val);
#ifdef OBJCPLUS
finish_return_stmt (ret_val);
#else
(void)c_finish_return (DECL_SOURCE_LOCATION (property), ret_val, NULL);
c_finish_return (location, ret_val, NULL_TREE);
#endif
add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (property), body, true));
add_stmt (c_end_compound_stmt (location, body, true));
fn = current_function_decl;
#ifdef OBJCPLUS
finish_function ();
@ -8578,8 +8814,10 @@ objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro
static void
objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
{
tree fn, decl, lhs, rhs;
location_t location = DECL_SOURCE_LOCATION (property);
tree fn, decl;
tree body;
tree new_value, statement;
/* If user has implemented a setter with same name then do nothing. */
if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
@ -8605,40 +8843,153 @@ objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro
body = c_begin_compound_stmt (true);
/* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as
appropriate. The following code just always does direct ivar
access. */
/* _property_name = _value; */
/* PROPERTY_IVAR_NAME is always defined if we got here, and should
be a valid instance variable. */
lhs = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
gcc_assert (lhs);
/* TODO: Lookup the argument in a more robust way so that it works
even if the method prototype does not call it '_value'. */
rhs = lookup_name (get_identifier ("_value"));
/* The 'new_value' is the only argument to the method, which is the
3rd argument of the function, after self and _cmd. We use twice
TREE_CHAIN to move forward two arguments. */
new_value = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)));
/* This would presumably happen if the user has specified a
prototype for the setter that is not the correct one. */
if (rhs == NULL_TREE)
prototype for the setter that does not have an argument! */
if (new_value == NULL_TREE)
{
/* TODO: This should be caught much earlier than this. */
/* We couldn't find the '_value' identifier in the current
context; presumably the user didn't have a '_value'
argument. */
error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, missing _value argument");
/* Just recover somehow. */
rhs = lhs;
error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, it must have one argument");
/* Try to recover somehow. */
new_value = error_mark_node;
}
/* FIXME: NULL types to get compile. */
add_stmt (build_modify_expr (DECL_SOURCE_LOCATION (decl),
lhs, NULL_TREE, NOP_EXPR,
DECL_SOURCE_LOCATION (decl), rhs, NULL_TREE));
add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (decl), body, true));
/* Now we need to decide how we build the setter. There are three
cases:
for 'copy' or 'retain' properties we need to use the
objc_setProperty() accessor helper which knows about retain and
copy. It supports both 'nonatomic' and 'atomic' access.
for 'nonatomic, assign' properties we can access the instance
variable directly. 'nonatomic' means we don't have to use locks,
and 'assign' means we don't have to worry about retain or copy.
If you combine the two, it means we can just access the instance
variable directly.
for 'atomic, assign' properties we use objc_copyStruct() (for the
next runtime) or objc_setPropertyStruct() (for the GNU runtime). */
switch (PROPERTY_ASSIGN_SEMANTICS (property))
{
case OBJC_PROPERTY_RETAIN:
case OBJC_PROPERTY_COPY:
{
/* We build "objc_setProperty (self, _cmd, new_value, offset, is_atomic, should_copy);" */
tree cmd, ivar, offset, is_atomic, should_copy;
cmd = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
/* Find the ivar to compute the offset. */
ivar = lookup_ivar (klass, PROPERTY_IVAR_NAME (property));
if (!ivar || is_private (ivar))
{
error_at (location,
"can not find instance variable associated with property");
statement = error_mark_node;
break;
}
offset = byte_position (ivar);
if (PROPERTY_NONATOMIC (property))
is_atomic = boolean_false_node;
else
is_atomic = boolean_true_node;
if (PROPERTY_ASSIGN_SEMANTICS (property) == OBJC_PROPERTY_COPY)
should_copy = boolean_true_node;
else
should_copy = boolean_false_node;
statement = build_function_call
(location,
/* Function prototype. */
objc_setProperty_decl,
/* Parameters. */
tree_cons /* self */
(NULL_TREE, self_decl,
tree_cons /* _cmd */
(NULL_TREE, cmd,
tree_cons /* offset */
(NULL_TREE, offset,
tree_cons /* new_value */
(NULL_TREE, new_value,
tree_cons /* is_atomic */
(NULL_TREE, is_atomic,
tree_cons /* should_copy */
(NULL_TREE, should_copy, NULL_TREE)))))));
}
break;
case OBJC_PROPERTY_ASSIGN:
if (PROPERTY_NONATOMIC (property))
{
/* We build "self->PROPERTY_IVAR_NAME = new_value;" */
statement = build_modify_expr
(location,
objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property)),
NULL_TREE, NOP_EXPR,
location, new_value, NULL_TREE);
break;
}
else
{
/* We build
objc_setPropertyStruct (&(self->PROPERTY_IVAR_NAME),
&new_value,
sizeof (type of self->PROPERTY_IVAR_NAME),
is_atomic,
false)
For the NeXT runtime, we need to use objc_copyStruct
instead of objc_getPropertyStruct. */
tree function_decl, size_of, is_atomic;
/* sizeof (ivar type). Since the ivar and the property have
the same type, there is no need to lookup the ivar. */
size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property),
true /* is_sizeof */,
false /* complain */);
if (PROPERTY_NONATOMIC (property))
is_atomic = boolean_false_node;
else
is_atomic = boolean_true_node;
if (flag_next_runtime)
function_decl = objc_copyStruct_decl;
else
function_decl = objc_setPropertyStruct_decl;
statement = build_function_call
(location,
/* Function prototype. */
function_decl,
/* Parameters. */
tree_cons /* &(self->PROPERTY_IVAR_NAME); */
(NULL_TREE, build_fold_addr_expr_loc (location,
objc_lookup_ivar
(NULL_TREE, PROPERTY_IVAR_NAME (property))),
tree_cons /* &new_value */
(NULL_TREE, build_fold_addr_expr_loc (location, new_value),
tree_cons /* sizeof (PROPERTY_IVAR) */
(NULL_TREE, size_of,
tree_cons /* is_atomic */
(NULL_TREE, is_atomic,
/* TODO: This is currently ignored by the GNU
runtime, but what about the next one ? */
tree_cons /* has_strong */
(NULL_TREE, boolean_true_node, NULL_TREE))))));
}
break;
default:
gcc_unreachable ();
}
gcc_assert (statement);
add_stmt (statement);
add_stmt (c_end_compound_stmt (location, body, true));
fn = current_function_decl;
#ifdef OBJCPLUS
finish_function ();

View File

@ -339,6 +339,12 @@ enum objc_tree_index
OCTI_FAST_ENUM_STATE_TEMP,
OCTI_ENUM_MUTATION_DECL,
OCTI_GET_PROPERTY_DECL,
OCTI_SET_PROPERTY_DECL,
OCTI_COPY_STRUCT_DECL,
OCTI_GET_PROPERTY_STRUCT_DECL,
OCTI_SET_PROPERTY_STRUCT_DECL,
OCTI_MAX
};
@ -506,4 +512,13 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_enumeration_mutation_decl \
objc_global_trees[OCTI_ENUM_MUTATION_DECL]
/* Declarations of functions used when synthesizing property
accessors. */
#define objc_getProperty_decl objc_global_trees[OCTI_GET_PROPERTY_DECL]
#define objc_setProperty_decl objc_global_trees[OCTI_SET_PROPERTY_DECL]
#define objc_copyStruct_decl objc_global_trees[OCTI_COPY_STRUCT_DECL]
#define objc_getPropertyStruct_decl objc_global_trees[OCTI_GET_PROPERTY_STRUCT_DECL]
#define objc_setPropertyStruct_decl objc_global_trees[OCTI_SET_PROPERTY_STRUCT_DECL]
#endif /* GCC_OBJC_ACT_H */

View File

@ -1,3 +1,25 @@
2010-11-01 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented Objective-C 2.0 property accessors.
* objc.dg/property/at-property-6.m: Use nonatomic properties to
avoid testing more complex accessors in this testcase which is not
about them.
* objc.dg/property/at-property-7.m: Same change.
* objc.dg/property/at-property-8.m: Same change.
* objc.dg/property/at-property-9.m: Same change.
* objc.dg/property/at-property-10.m: Same change.
* objc.dg/property/at-property-11.m: Same change.
* obj-c++.dg/property/at-property-6.mm: Same change.
* obj-c++.dg/property/at-property-7.mm: Same change.
* obj-c++.dg/property/at-property-8.mm: Same change.
* obj-c++.dg/property/at-property-9.mm: Same change.
* obj-c++.dg/property/at-property-10.mm: Same change.
* obj-c++.dg/property/at-property-11.mm: Same change.
* objc.dg/property/at-property-12.m: New.
* objc.dg/property/at-property-13.m: New.
* obj-c++.dg/property/at-property-12.mm: New.
* obj-c++.dg/property/at-property-13.mm: New.
2010-11-01 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/46152

View File

@ -12,7 +12,7 @@
Class isa;
int a;
}
@property int a;
@property (nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -12,7 +12,7 @@
Class isa;
int a;
}
@property int a;
@property (nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -0,0 +1,46 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do run } */
/* Test atomic, assign synthesized methods. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int a;
id b;
}
@property int a;
@property (assign) id b;
+ (id) initialize;
+ (id) alloc;
- (id) init;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
@synthesize a;
@synthesize b;
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
object.a = 40;
if (object.a != 40)
abort ();
object.b = object;
if (object.b != object)
abort ();
return (0);
}

View File

@ -0,0 +1,71 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do run } */
/* Test retain and copy synthesized methods. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int copy_count;
id a;
id b;
}
@property (copy) id a;
@property (retain) id b;
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (id) copyWithZone: (void *)zone;
- (int) copyCount;
- (id) autorelease;
- (oneway void) release;
- (id) retain;
@end
/* This class implements copyWithZone, which doesn't do anything other
than increasing a counter of how many copies were made. */
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
- (id) copyWithZone: (void *)zone { copy_count++; return self; }
- (int) copyCount { return copy_count; }
- (id) autorelease { return self; }
- (oneway void) release { return; }
- (id) retain { return self; }
@synthesize a;
@synthesize b;
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
MyRootClass *argument = [[MyRootClass alloc] init];
/* This should copy argument. */
object.a = argument;
if (object.a != argument)
abort ();
/* Test that it was copied. */
if ([object.a copyCount] != 1)
abort ();
/* We just test that the retain accessors seem to work and that they
don't copy. We don't test that retain was actually called,
because if garbage collection is enabled, it may never be
called! */
object.b = argument;
if (object.b != argument)
abort ();
/* Test that it was not copied. */
if ([object.b copyCount] != 1)
abort ();
return (0);
}

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property int a;
@property (nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property (getter = getA) int a;
@property (getter = getA, nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property (setter = writeA:) int a;
@property (setter = writeA:, nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property (getter = giveMeA, setter = writeA:) int a;
@property (getter = giveMeA, setter = writeA:, nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -12,7 +12,10 @@
Class isa;
int a;
}
@property int a;
/* Use the simplest synthesized accessor (assign, nonatomic) as we are
not testing the synthesized accessors in this test, just the
property syntax. */
@property (nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -12,7 +12,10 @@
Class isa;
int a;
}
@property int a;
/* Use the simplest synthesized accessor (assign, nonatomic) as we are
not testing the synthesized accessors in this test, just the
property syntax. */
@property (nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -0,0 +1,46 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do run } */
/* Test atomic, assign synthesized methods. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int a;
id b;
}
@property int a;
@property (assign) id b;
+ (id) initialize;
+ (id) alloc;
- (id) init;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
@synthesize a;
@synthesize b;
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
object.a = 40;
if (object.a != 40)
abort ();
object.b = object;
if (object.b != object)
abort ();
return 0;
}

View File

@ -0,0 +1,71 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do run } */
/* Test retain and copy synthesized methods. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int copy_count;
id a;
id b;
}
@property (copy) id a;
@property (retain) id b;
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (id) copyWithZone: (void *)zone;
- (int) copyCount;
- (id) autorelease;
- (oneway void) release;
- (id) retain;
@end
/* This class implements copyWithZone, which doesn't do anything other
than increasing a counter of how many copies were made. */
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
- (id) copyWithZone: (void *)zone { copy_count++; return self; }
- (int) copyCount { return copy_count; }
- (id) autorelease { return self; }
- (oneway void) release { return; }
- (id) retain { return self; }
@synthesize a;
@synthesize b;
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
MyRootClass *argument = [[MyRootClass alloc] init];
/* This should copy argument. */
object.a = argument;
if (object.a != argument)
abort ();
/* Test that it was copied. */
if ([object.a copyCount] != 1)
abort ();
/* We just test that the retain accessors seem to work and that they
don't copy. We don't test that retain was actually called,
because if garbage collection is enabled, it may never be
called! */
object.b = argument;
if (object.b != argument)
abort ();
/* Test that it was not copied. */
if ([object.b copyCount] != 1)
abort ();
return 0;
}

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property int a;
@property (nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property (getter = getA) int a;
@property (getter = getA, nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -13,7 +13,7 @@
Class isa;
int a;
}
@property (setter = writeA:) int a;
@property (setter = writeA:, nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;

View File

@ -13,7 +13,10 @@
Class isa;
int a;
}
@property (getter = giveMeA, setter = writeA:) int a;
/* Use the simplest synthesized accessor (assign, nonatomic) as we are
not testing the synthesized accessors in this test, just the
property syntax. */
@property (getter = giveMeA, setter = writeA:, nonatomic) int a;
+ (id) initialize;
+ (id) alloc;
- (id) init;