| /* APPLE LOCAL file radar 3742561 */ |
| /* Test that we generate void * objc_memmove_collectable(void *dst, const void *src, size_t size) |
| API when struct has a 'strong' object pointer in a variety of situations. */ |
| /* { dg-options "-fobjc-gc -mmacosx-version-min=10.5 -framework Cocoa" } */ |
| /* { dg-do run { target *-*-darwin* } } */ |
| /* { dg-require-effective-target objc_gc } */ |
| |
| #define objc_copyStruct X_objc_copyStruct |
| #define objc_memmove_collectable X_objc_memmove_collectable |
| #include <Cocoa/Cocoa.h> |
| #undef objc_memmove_collectable |
| #undef objc_copyStruct |
| |
| static int count; |
| |
| /* Only ppc32 API for property assignment makes the call to objc_copyStruct. */ |
| static void |
| objc_copyStruct (void *dst, const void * src, size_t size, bool arg, bool arg2) |
| { |
| memcpy (dst, src, size); |
| count++; |
| } |
| |
| typedef struct S { |
| int ii; |
| } SS; |
| |
| struct type_s { |
| SS may_recurse; |
| id id_val; |
| }; |
| |
| struct nono { |
| nono & operator = (const nono & arg) |
| { |
| memcpy (this, &arg, sizeof(nono)); |
| return *this; |
| } |
| struct type_s nono_val; |
| id id_nono; |
| nono (int val) |
| { |
| nono_val.may_recurse.ii = val; |
| } |
| }; |
| |
| @interface NamedObject : NSObject |
| { |
| struct type_s type_s_ivar; |
| } |
| - (void) setSome : (struct type_s) arg; |
| - (struct type_s) getSome; |
| @property(assign) struct type_s aggre_prop; |
| @end |
| |
| @implementation NamedObject |
| @synthesize aggre_prop = type_s_ivar; |
| - (void) setSome : (struct type_s) arg |
| { |
| type_s_ivar = arg; |
| } |
| - (struct type_s) getSome |
| { |
| return type_s_ivar; |
| } |
| @end |
| |
| struct type_s some = {{1234}, (id)0}; |
| |
| struct type_s get(void) |
| { |
| return some; |
| } |
| |
| struct type_s GlobalVariable; |
| |
| static void * |
| objc_memmove_collectable(void *dst, const void *src, size_t size) |
| { |
| memcpy (dst, src, size); |
| count++; |
| } |
| |
| int main(void) { |
| struct type_s local; |
| struct type_s *p; |
| int old_count; |
| |
| NamedObject *object = [[NamedObject alloc] init]; |
| |
| /* Assigning into a global */ |
| GlobalVariable = get(); |
| if (count != 1 || GlobalVariable.may_recurse.ii != 1234) |
| abort (); |
| |
| /* Assigning into a local */ |
| local = GlobalVariable; |
| if (count != 2 || local.may_recurse.ii != 1234) |
| abort (); |
| |
| p = (struct type_s *) malloc (sizeof (struct type_s)); |
| /* Assigning thourgh a pointer */ |
| *p = local; |
| if (count != 3 || p->may_recurse.ii != 1234) |
| abort (); |
| |
| /* Assigning to an ivar */ |
| [object setSome:GlobalVariable]; |
| if (count != 4 || [object getSome].may_recurse.ii != 1234) |
| abort (); |
| |
| local.may_recurse.ii = 6578; |
| object.aggre_prop = local; |
| if (count != 5 || object.aggre_prop.may_recurse.ii != 6578) |
| abort (); |
| |
| /* class assignment with overloaded '=' operator must NOT call the new API. */ |
| old_count = count; |
| nono nono_rhs (89); |
| nono nono_lhs (100); |
| nono_lhs = nono_rhs; |
| if (count != old_count || nono_lhs.nono_val.may_recurse.ii != 89) |
| abort (); |
| |
| return 0; |
| } |