1// testroot.i 2// Implementation of class TestRoot 3// Include this file into your main test file to use it. 4 5#include "test.h" 6#include <dlfcn.h> 7#include <objc/objc-internal.h> 8 9int TestRootLoad = 0; 10int TestRootInitialize = 0; 11int TestRootAlloc = 0; 12int TestRootAllocWithZone = 0; 13int TestRootCopy = 0; 14int TestRootCopyWithZone = 0; 15int TestRootMutableCopy = 0; 16int TestRootMutableCopyWithZone = 0; 17int TestRootInit = 0; 18int TestRootDealloc = 0; 19int TestRootFinalize = 0; 20int TestRootRetain = 0; 21int TestRootRelease = 0; 22int TestRootAutorelease = 0; 23int TestRootRetainCount = 0; 24int TestRootTryRetain = 0; 25int TestRootIsDeallocating = 0; 26int TestRootPlusRetain = 0; 27int TestRootPlusRelease = 0; 28int TestRootPlusAutorelease = 0; 29int TestRootPlusRetainCount = 0; 30 31 32@implementation TestRoot 33 34// These all use void* pending rdar://9310005. 35 36static void * 37retain_fn(void *self, SEL _cmd __unused) { 38 OSAtomicIncrement32(&TestRootRetain); 39 void * (*fn)(void *) = (typeof(fn))_objc_rootRetain; 40 return fn(self); 41} 42 43static void 44release_fn(void *self, SEL _cmd __unused) { 45 OSAtomicIncrement32(&TestRootRelease); 46 void (*fn)(void *) = (typeof(fn))_objc_rootRelease; 47 fn(self); 48} 49 50static void * 51autorelease_fn(void *self, SEL _cmd __unused) { 52 OSAtomicIncrement32(&TestRootAutorelease); 53 void * (*fn)(void *) = (typeof(fn))_objc_rootAutorelease; 54 return fn(self); 55} 56 57static unsigned long 58retaincount_fn(void *self, SEL _cmd __unused) { 59 OSAtomicIncrement32(&TestRootRetainCount); 60 unsigned long (*fn)(void *) = (typeof(fn))_objc_rootRetainCount; 61 return fn(self); 62} 63 64static void * 65copywithzone_fn(void *self, SEL _cmd __unused, void *zone) { 66 OSAtomicIncrement32(&TestRootCopyWithZone); 67 void * (*fn)(void *, void *) = (typeof(fn))dlsym(RTLD_DEFAULT, "object_copy"); 68 return fn(self, zone); 69} 70 71static void * 72plusretain_fn(void *self __unused, SEL _cmd __unused) { 73 OSAtomicIncrement32(&TestRootPlusRetain); 74 return self; 75} 76 77static void 78plusrelease_fn(void *self __unused, SEL _cmd __unused) { 79 OSAtomicIncrement32(&TestRootPlusRelease); 80} 81 82static void * 83plusautorelease_fn(void *self, SEL _cmd __unused) { 84 OSAtomicIncrement32(&TestRootPlusAutorelease); 85 return self; 86} 87 88static unsigned long 89plusretaincount_fn(void *self __unused, SEL _cmd __unused) { 90 OSAtomicIncrement32(&TestRootPlusRetainCount); 91 return ULONG_MAX; 92} 93 94+(void) load { 95 OSAtomicIncrement32(&TestRootLoad); 96 97 // install methods that ARR refuses to compile 98 class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, ""); 99 class_addMethod(self, sel_registerName("release"), (IMP)release_fn, ""); 100 class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, ""); 101 class_addMethod(self, sel_registerName("retainCount"), (IMP)retaincount_fn, ""); 102 class_addMethod(self, sel_registerName("copyWithZone:"), (IMP)copywithzone_fn, ""); 103 104 class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)plusretain_fn, ""); 105 class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)plusrelease_fn, ""); 106 class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)plusautorelease_fn, ""); 107 class_addMethod(object_getClass(self), sel_registerName("retainCount"), (IMP)plusretaincount_fn, ""); 108} 109 110 111+(void) initialize { 112 OSAtomicIncrement32(&TestRootInitialize); 113} 114 115-(id) self { 116 return self; 117} 118 119+(Class) class { 120 return self; 121} 122 123-(Class) class { 124 return object_getClass(self); 125} 126 127+(Class) superclass { 128 return class_getSuperclass(self); 129} 130 131-(Class) superclass { 132 return class_getSuperclass([self class]); 133} 134 135+(id) new { 136 return [[self alloc] init]; 137} 138 139+(id) alloc { 140 OSAtomicIncrement32(&TestRootAlloc); 141 void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc; 142 return objc_retainedObject(fn(self)); 143} 144 145+(id) allocWithZone:(void *)zone { 146 OSAtomicIncrement32(&TestRootAllocWithZone); 147 void * (*fn)(id __unsafe_unretained, void *) = (typeof(fn))_objc_rootAllocWithZone; 148 return objc_retainedObject(fn(self, zone)); 149} 150 151+(id) copy { 152 return self; 153} 154 155+(id) copyWithZone:(void *) __unused zone { 156 return self; 157} 158 159-(id) copy { 160 OSAtomicIncrement32(&TestRootCopy); 161 return [self copyWithZone:NULL]; 162} 163 164+(id) mutableCopyWithZone:(void *) __unused zone { 165 fail("+mutableCopyWithZone: called"); 166} 167 168-(id) mutableCopy { 169 OSAtomicIncrement32(&TestRootMutableCopy); 170 return [self mutableCopyWithZone:NULL]; 171} 172 173-(id) mutableCopyWithZone:(void *) __unused zone { 174 OSAtomicIncrement32(&TestRootMutableCopyWithZone); 175 void * (*fn)(id __unsafe_unretained) = (typeof(fn))_objc_rootAlloc; 176 return objc_retainedObject(fn(object_getClass(self))); 177} 178 179-(id) init { 180 OSAtomicIncrement32(&TestRootInit); 181 return _objc_rootInit(self); 182} 183 184+(void) dealloc { 185 fail("+dealloc called"); 186} 187 188-(void) dealloc { 189 OSAtomicIncrement32(&TestRootDealloc); 190 _objc_rootDealloc(self); 191} 192 193+(void) finalize { 194 fail("+finalize called"); 195} 196 197-(void) finalize { 198 OSAtomicIncrement32(&TestRootFinalize); 199 _objc_rootFinalize(self); 200} 201 202+(BOOL) _tryRetain { 203 return YES; 204} 205 206-(BOOL) _tryRetain { 207 OSAtomicIncrement32(&TestRootTryRetain); 208 return _objc_rootTryRetain(self); 209} 210 211+(BOOL) _isDeallocating { 212 return NO; 213} 214 215-(BOOL) _isDeallocating { 216 OSAtomicIncrement32(&TestRootIsDeallocating); 217 return _objc_rootIsDeallocating(self); 218} 219 220-(BOOL) allowsWeakReference { 221 return ! [self _isDeallocating]; 222} 223 224-(BOOL) retainWeakReference { 225 return [self _tryRetain]; 226} 227 228 229@end 230