// testroot.i // Implementation of class TestRoot // Include this file into your main test file to use it. #include "test.h" #include #include int TestRootLoad = 0; int TestRootInitialize = 0; int TestRootAlloc = 0; int TestRootAllocWithZone = 0; int TestRootCopy = 0; int TestRootCopyWithZone = 0; int TestRootMutableCopy = 0; int TestRootMutableCopyWithZone = 0; int TestRootInit = 0; int TestRootDealloc = 0; int TestRootFinalize = 0; int TestRootRetain = 0; int TestRootRelease = 0; int TestRootAutorelease = 0; int TestRootRetainCount = 0; int TestRootTryRetain = 0; int TestRootIsDeallocating = 0; int TestRootPlusRetain = 0; int TestRootPlusRelease = 0; int TestRootPlusAutorelease = 0; int TestRootPlusRetainCount = 0; @implementation TestRoot // These all use void* pending rdar://9310005. static void * retain_fn(void *self, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootRetain); void * (*fn)(void *) = (typeof(fn))_objc_rootRetain; return fn(self); } static void release_fn(void *self, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootRelease); void (*fn)(void *) = (typeof(fn))_objc_rootRelease; fn(self); } static void * autorelease_fn(void *self, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootAutorelease); void * (*fn)(void *) = (typeof(fn))_objc_rootAutorelease; return fn(self); } static unsigned long retaincount_fn(void *self, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootRetainCount); unsigned long (*fn)(void *) = (typeof(fn))_objc_rootRetainCount; return fn(self); } static void * copywithzone_fn(void *self, SEL _cmd __unused, void *zone) { OSAtomicIncrement32(&TestRootCopyWithZone); void * (*fn)(void *, void *) = (typeof(fn))dlsym(RTLD_DEFAULT, "object_copy"); return fn(self, zone); } static void * plusretain_fn(void *self __unused, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootPlusRetain); return self; } static void plusrelease_fn(void *self __unused, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootPlusRelease); } static void * plusautorelease_fn(void *self, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootPlusAutorelease); return self; } static unsigned long plusretaincount_fn(void *self __unused, SEL _cmd __unused) { OSAtomicIncrement32(&TestRootPlusRetainCount); return ULONG_MAX; } +(void) load { OSAtomicIncrement32(&TestRootLoad); // install methods that ARR refuses to compile class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, ""); class_addMethod(self, sel_registerName("release"), (IMP)release_fn, ""); class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, ""); class_addMethod(self, sel_registerName("retainCount"), (IMP)retaincount_fn, ""); class_addMethod(self, sel_registerName("copyWithZone:"), (IMP)copywithzone_fn, ""); class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)plusretain_fn, ""); class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)plusrelease_fn, ""); class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)plusautorelease_fn, ""); class_addMethod(object_getClass(self), sel_registerName("retainCount"), (IMP)plusretaincount_fn, ""); } +(void) initialize { OSAtomicIncrement32(&TestRootInitialize); } -(id) self { return self; } +(Class) class { return self; } -(Class) class { return object_getClass(self); } +(Class) superclass { return class_getSuperclass(self); } -(Class) superclass { return class_getSuperclass([self class]); } +(id) new { return [[self alloc] init]; } +(id) alloc { OSAtomicIncrement32(&TestRootAlloc); void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc; return objc_retainedObject(fn(self)); } +(id) allocWithZone:(void *)zone { OSAtomicIncrement32(&TestRootAllocWithZone); void * (*fn)(id __unsafe_unretained, void *) = (typeof(fn))_objc_rootAllocWithZone; return objc_retainedObject(fn(self, zone)); } +(id) copy { return self; } +(id) copyWithZone:(void *) __unused zone { return self; } -(id) copy { OSAtomicIncrement32(&TestRootCopy); return [self copyWithZone:NULL]; } +(id) mutableCopyWithZone:(void *) __unused zone { fail("+mutableCopyWithZone: called"); } -(id) mutableCopy { OSAtomicIncrement32(&TestRootMutableCopy); return [self mutableCopyWithZone:NULL]; } -(id) mutableCopyWithZone:(void *) __unused zone { OSAtomicIncrement32(&TestRootMutableCopyWithZone); void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc; return objc_retainedObject(fn(object_getClass(self))); } -(id) init { OSAtomicIncrement32(&TestRootInit); return _objc_rootInit(self); } +(void) dealloc { fail("+dealloc called"); } -(void) dealloc { OSAtomicIncrement32(&TestRootDealloc); _objc_rootDealloc(self); } +(void) finalize { fail("+finalize called"); } -(void) finalize { OSAtomicIncrement32(&TestRootFinalize); _objc_rootFinalize(self); } +(BOOL) _tryRetain { return YES; } -(BOOL) _tryRetain { OSAtomicIncrement32(&TestRootTryRetain); return _objc_rootTryRetain(self); } +(BOOL) _isDeallocating { return NO; } -(BOOL) _isDeallocating { OSAtomicIncrement32(&TestRootIsDeallocating); return _objc_rootIsDeallocating(self); } -(BOOL) allowsWeakReference { return ! [self _isDeallocating]; } -(BOOL) retainWeakReference { return [self _tryRetain]; } @end