aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/objc.dg/objc-gc-2.m
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/objc.dg/objc-gc-2.m')
-rw-r--r--gcc/testsuite/objc.dg/objc-gc-2.m172
1 files changed, 172 insertions, 0 deletions
diff --git a/gcc/testsuite/objc.dg/objc-gc-2.m b/gcc/testsuite/objc.dg/objc-gc-2.m
new file mode 100644
index 00000000000..75c7aea45a3
--- /dev/null
+++ b/gcc/testsuite/objc.dg/objc-gc-2.m
@@ -0,0 +1,172 @@
+/* APPLE LOCAL file ObjC GC */
+/* A run-time test for insertion of write barriers. */
+
+/* { dg-do run { target *-*-darwin* } } */
+/* { dg-options "-fnext-runtime -fobjc-gc" } */
+
+#include <objc/objc.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef const struct __CFDictionary * CFDictionaryRef;
+
+// callouts to these are generated with cc -fobjc-gc
+
+int GlobalAssigns;
+int IvarAssigns;
+int StrongCastAssigns;
+
+
+id objc_assign_global(id value, id *dest) {
+ ++GlobalAssigns;
+ return (*dest = value);
+}
+
+id objc_assign_ivar(id value, id dest, unsigned int offset) {
+ id *slot = (id*) ((char *)dest + offset);
+
+ ++IvarAssigns;
+ return (*slot = value);
+}
+
+id objc_assign_strongCast(id value, id *dest) {
+ id base;
+
+ ++StrongCastAssigns ;
+ return (*dest = value);
+}
+
+// The test case elements;
+@class NSObject;
+@class NSString;
+
+typedef struct {
+ id element;
+ id elementArray[10];
+ __strong CFDictionaryRef cfElement;
+ __strong CFDictionaryRef cfElementArray[10];
+} struct_with_ids_t;
+
+@interface Foo {
+@public
+// assignments to any/all of these fields should generate objc_assign_ivar
+ __strong CFDictionaryRef dict;
+ __strong CFDictionaryRef dictArray[3];
+ id ivar;
+ id array[10];
+ NSObject *nsobject;
+ NSString *stringArray[10];
+ struct_with_ids_t inner;
+}
+
+@end
+
+// assignments to these should generate objc_assign_global
+id GlobalId;
+id GlobalArray[20];
+NSObject *GlobalObject;
+NSObject *GlobalObjectArray[20];
+__strong CFDictionaryRef Gdict;
+__strong CFDictionaryRef Gdictarray[10];
+struct_with_ids_t GlobalStruct;
+struct_with_ids_t GlobalStructArray[10];
+
+
+// The test cases
+void *rhs = 0;
+
+#define ASSIGNTEST(expr, global) expr = rhs; if (!global) { printf(# expr " is busted\n"); ++counter; } global = 0
+
+int testGlobals() {
+ // Everything in this function generates assign_global intercepts
+ int counter = 0;
+
+ static id staticGlobalId;
+ static id staticGlobalArray[20];
+ static NSObject *staticGlobalObject;
+ static NSObject *staticGlobalObjectArray[20];
+ static __strong CFDictionaryRef staticGdict;
+ static __strong CFDictionaryRef staticGdictarray[10];
+ static struct_with_ids_t staticGlobalStruct;
+ static struct_with_ids_t staticGlobalStructArray[10];
+
+ ASSIGNTEST(GlobalId, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalObject, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalObjectArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(Gdict, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(Gdictarray[1], GlobalAssigns); // objc_assign_global
+
+ ASSIGNTEST(GlobalStruct.element, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalStruct.cfElement, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global
+
+ ASSIGNTEST(staticGlobalId, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalObject, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalObjectArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGdict, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGdictarray[1], GlobalAssigns); // objc_assign_global
+
+ ASSIGNTEST(staticGlobalStruct.element, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalStruct.cfElement, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global
+
+ return counter;
+}
+
+
+int testIvars() {
+ Foo *foo = (Foo *)malloc(sizeof(Foo)); // don't call in ObjC
+ int counter = 0;
+
+ ASSIGNTEST(foo->ivar, IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->dict, IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->dictArray[0], IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->array[0], IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->nsobject, IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->stringArray[0], IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->inner.element, IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->inner.elementArray[0], IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->inner.cfElement, IvarAssigns); // objc_assign_ivar
+ ASSIGNTEST(foo->inner.cfElementArray[0], IvarAssigns); // objc_assign_ivar
+
+ return counter;
+}
+
+int testStrongCasts() {
+ id x = nil;
+ int counter = 0;
+ typedef struct { @defs(Foo) } Foo_defs;
+ Foo_defs *foo = (Foo_defs *)malloc(sizeof(Foo));
+
+ // strong casts should always be issued, even if the compiler could know better
+
+ ASSIGNTEST((__strong id)foo->ivar, StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->dict, StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->dictArray[0], StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->array[0], StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->nsobject, StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->stringArray[0], StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->inner.element, StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->inner.elementArray[0], StrongCastAssigns);// objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->inner.cfElement, StrongCastAssigns); // objc_assign_strongCast
+ ASSIGNTEST((__strong id)foo->inner.cfElementArray[0], StrongCastAssigns);// objc_assign_strongCast
+
+ // assignments to declared __strong on plain structure elements shouldn't work
+
+ return counter;
+}
+
+@implementation Foo
+@end
+
+int main(int argc, char *argv[]) {
+ int errors = 0;
+ errors += testGlobals();
+ errors += testIvars();
+ errors += testStrongCasts();
+ return (errors != 0);
+}