| /* APPLE LOCAL file radar 4426814 */ |
| /* A run-time test for insertion of read barriers for __weak objects. */ |
| |
| /* { dg-do run { target *-*-darwin* } } */ |
| /* { dg-options "-fnext-runtime -fobjc-gc" } */ |
| |
| #include <objc/objc.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| typedef struct __CFDictionary * CFDictionaryRef; |
| |
| // callouts to these are generated with cc -fobjc-gc |
| |
| int GlobalReads; |
| |
| |
| static id objc_read_weak(id *location) { |
| ++GlobalReads; |
| return *location; |
| } |
| |
| static id objc_assign_weak(id value, id *dest) { |
| return ((__weak id)*dest = value); |
| } |
| |
| |
| // The test case elements; |
| @class NSObject; |
| @class NSString; |
| |
| @interface Foo |
| { |
| @public |
| // read of __weak fields should generate objc_read_weak |
| __weak CFDictionaryRef dict; |
| __weak CFDictionaryRef dictArray[3]; |
| __weak id ivar; |
| __weak id array[10]; |
| __weak NSObject *nsobject; |
| __weak NSString *stringArray[10]; |
| } |
| @end |
| |
| @implementation Foo |
| - (void)message {} |
| - (void)message1 : (id)arg {} |
| @end |
| |
| #define READTEST(expr, count) if (GlobalReads != count) { printf(# expr " is busted\n"); ++counter; } --GlobalReads; |
| |
| id get_id() |
| { |
| static id x; |
| return (id)&x; |
| } |
| |
| int testGlobals() { |
| // Everything in this function generates objc_assign_weak intercepts |
| int counter = 0; |
| |
| static __weak id staticGlobalId = 0; |
| static __weak id staticGlobalArray[20] = {0}; |
| static __weak NSObject *staticGlobalObject; |
| static __weak NSObject *staticGlobalObjectArray[20]; |
| static __weak CFDictionaryRef staticGdict; |
| static __weak CFDictionaryRef staticGdictarray[10] = {0,0,0}; |
| |
| |
| if (!staticGlobalId) |
| READTEST(staticGlobalId,1); |
| |
| if (!staticGlobalArray[0]) |
| READTEST(staticGlobalArray[0],1); |
| |
| staticGlobalObject = get_id(); |
| |
| if (staticGlobalObject) |
| READTEST(staticGlobalObject,1); |
| |
| staticGdict = (__weak CFDictionaryRef)get_id(); |
| READTEST(get_id, 1); |
| if (staticGlobalId || staticGdictarray[1] || staticGdict) |
| { |
| READTEST(staticGlobalId,3); |
| READTEST(staticGlobalArray[1],2); |
| READTEST(staticGdict,1); |
| } |
| |
| return counter; |
| } |
| |
| |
| int testIvars() { |
| int counter = 0; |
| Foo *foo = (Foo *)calloc(sizeof(Foo), 1); // don't call in ObjC |
| |
| if (!foo->ivar) |
| READTEST(foo->ivar, 1); |
| if (!foo->dict) |
| READTEST(foo->dict, 1); |
| |
| foo->ivar = get_id(); |
| if (foo->dict || foo->dictArray[0] || foo->stringArray[0] || foo->ivar) |
| { |
| READTEST(foo->dict, 4); |
| READTEST(foo->dictArray[0], 3); |
| READTEST(foo->stringArray[0], 2); |
| READTEST(foo->ivar, 1); |
| } |
| [foo->array[0] message]; |
| READTEST(foo->array, 1); |
| |
| [foo->array[0] message1 : foo->ivar]; |
| READTEST(foo->array, 2); |
| |
| return counter; |
| } |
| |
| int main(int argc, char *argv[]) { |
| int errors = 0; |
| errors += testGlobals(); |
| errors += testIvars(); |
| return (errors); |
| } |