diff --git a/ChangeLog b/ChangeLog index c572ca7be..bf8a97133 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-02-13 Richard Frith-Macdonald + + * Headers/Additions/GNUstepBase/NSObject+GNUstepBase.h: + * Source/Additions/NSObject+GNUstepBase.m: + Add -notImplemented:reason: to raise an exception when someone used + a class/method which depends on another library not present at + configure time. + * Source/NSCalendar.m: + * Source/NSLocale.m: + Raise exception if used when not implmented because of no UCU + * Source/ObjectiveC2/runtime.c: Fix some cases of dereferencing null + pointers. + 2011-02-12 Richard Frith-Macdonald * Source/NSObject.m: Obtain NSZombie class pointer using diff --git a/Headers/Additions/GNUstepBase/NSObject+GNUstepBase.h b/Headers/Additions/GNUstepBase/NSObject+GNUstepBase.h index 6859ec78d..84a95aa2c 100644 --- a/Headers/Additions/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/Additions/GNUstepBase/NSObject+GNUstepBase.h @@ -76,6 +76,13 @@ extern "C" { */ - (id) notImplemented: (SEL)aSel GS_NORETURN_METHOD; +/** + * Message sent when an implementation wants to explicitly exclude a method + * (but cannot due to compiler constraint), and wants to make sure it is not + * called by mistake. Default implementation raises an exception at runtime. + */ +- (id) notImplemented: (SEL)aSel reason: (NSString*)reason GS_NORETURN_METHOD; + /** * Message sent when an implementation wants to explicitly require a subclass * to implement a method (but cannot at compile time since there is no diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index 46da2321a..0bf0325c2 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -90,32 +90,48 @@ - (id) notImplemented: (SEL)aSel { + char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-'); + [NSException raise: NSGenericException - format: @"method %@ not implemented in %@(%s)", + format: @"[%@%c%@] not implemented", + NSStringFromClass([self class]), c, + aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"]; + return nil; +} + +- (id) notImplemented: (SEL)aSel reason: (NSString*)reason +{ + char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-'); + + [NSException + raise: NSGenericException + format: @"[%@%c%@] not implemented ... %@", + NSStringFromClass([self class]), c, aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)", - NSStringFromClass([self class]), - GSObjCIsInstance(self) ? "instance" : "class"]; + reason]; return nil; } - (id) shouldNotImplement: (SEL)aSel { + char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-'); + [NSException raise: NSGenericException - format: @"%@(%s) should not implement %@", - NSStringFromClass([self class]), - GSObjCIsInstance(self) ? "instance" : "class", + format: @"[%@%c%@] should not be implemented", + NSStringFromClass([self class]), c, aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"]; return nil; } - (id) subclassResponsibility: (SEL)aSel { - [NSException raise: NSInvalidArgumentException - format: @"subclass %@(%s) should override %@", - NSStringFromClass([self class]), - GSObjCIsInstance(self) ? "instance" : "class", + char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-'); + + [NSException raise: NSGenericException + format: @"[%@%c%@] should be overridden by subclass", + NSStringFromClass([self class]), c, aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"]; return nil; } diff --git a/Source/NSCalendar.m b/Source/NSCalendar.m index d3cdd522d..ec77a0876 100644 --- a/Source/NSCalendar.m +++ b/Source/NSCalendar.m @@ -155,6 +155,14 @@ static UCalendarDateFields _NSCalendarUnitToDateField (NSCalendarUnit unit) static NSCalendar *autoupdatingCalendar = nil; static NSRecursiveLock *classLock = nil; +#if GS_USE_ICU == 0 ++ (id) allocWithZone: (NSZone*)z +{ + [self notImplemented: _cmd + reason: @"missing ICU support at configure time."]; +} +#endif + + (void) initialize { if (self == [NSLocale class]) diff --git a/Source/NSLocale.m b/Source/NSLocale.m index 32d01e674..12873feed 100644 --- a/Source/NSLocale.m +++ b/Source/NSLocale.m @@ -179,6 +179,14 @@ static NSMutableDictionary *allLocales = nil; static NSDictionary *canonicalLocales = nil; static NSRecursiveLock *classLock = nil; +#if GS_USE_ICU == 0 ++ (id) allocWithZone: (NSZone*)z +{ + [self notImplemented: _cmd + reason: @"missing ICU support at configure time."]; +} +#endif + + (void) initialize { if (self == [NSLocale class]) diff --git a/Source/ObjectiveC2/runtime.c b/Source/ObjectiveC2/runtime.c index e800b15f6..5309f6fe5 100644 --- a/Source/ObjectiveC2/runtime.c +++ b/Source/ObjectiveC2/runtime.c @@ -102,21 +102,24 @@ skip_argspec(const char *types) static Method class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector) { - struct objc_method_list *methods; - - for (methods = aClass->methods; - methods != NULL; methods = methods->method_next) + if (Nil != aClass) { - int i; + struct objc_method_list *methods; - for (i = 0; i < methods->method_count; i++) + for (methods = aClass->methods; + methods != NULL; methods = methods->method_next) { - Method_t method = &methods->method_list[i]; + int i; - if (method->method_name->sel_id == aSelector->sel_id) - { - return method; - } + for (i = 0; i < methods->method_count; i++) + { + Method_t method = &methods->method_list[i]; + + if (method->method_name->sel_id == aSelector->sel_id) + { + return method; + } + } } } return NULL; @@ -148,7 +151,7 @@ class_addIvar(Class cls, const char *name, unsigned off; Ivar ivar; - if (CLS_ISRESOLV(cls) || CLS_ISMETA(cls)) + if (Nil == cls || CLS_ISRESOLV(cls) || CLS_ISMETA(cls)) { return NO; } @@ -380,6 +383,10 @@ class_getInstanceMethod(Class aClass, SEL aSelector) Method class_getClassMethod(Class aClass, SEL aSelector) { + if (Nil == aClass) + { + return NULL; + } return class_getInstanceMethod(aClass->class_pointer, aSelector); } @@ -393,13 +400,17 @@ class_getClassVariable(Class cls, const char *name) size_t class_getInstanceSize(Class cls) { + if (Nil == cls) + { + return 0; + } return cls->instance_size; } Ivar class_getInstanceVariable(Class cls, const char *name) { - if (name != NULL) + if (Nil != cls && NULL != name) { while (cls != Nil) { @@ -430,6 +441,10 @@ class_getInstanceVariable(Class cls, const char *name) const char * class_getIvarLayout(Class cls) { + if (Nil == cls) + { + return 0; + } return (char *) cls->ivars; } @@ -444,18 +459,26 @@ class_getIvarLayout(Class cls) IMP class_getMethodImplementation(Class cls, SEL name) { + if (Nil == cls || 0 == name) + { + return 0; + } return (IMP) get_imp(cls, name); } IMP class_getMethodImplementation_stret(Class cls, SEL name) { + if (Nil == cls || 0 == name) + { + return 0; + } return (IMP) get_imp(cls, name); } const char * class_getName(Class cls) { - if (cls == Nil) + if (Nil == cls) { return "nil"; // This is what OSX does. } @@ -471,6 +494,10 @@ void __objc_resolve_class_links(void); Class class_getSuperclass(Class cls) { + if (Nil == cls) + { + return 0; + } if (!CLS_ISRESOLV(cls)) { /* This class is not yet resolved ... so lookup superclass by name. @@ -485,9 +512,13 @@ class_getSuperclass(Class cls) } int -class_getVersion(Class theClass) +class_getVersion(Class cls) { - return class_get_version(theClass); + if (Nil == cls) + { + return 0; + } + return class_get_version(cls); } const char * @@ -500,7 +531,11 @@ class_getWeakIvarLayout(Class cls) BOOL class_isMetaClass(Class cls) { - return CLS_ISMETA(cls); + if (Nil == cls || !CLS_ISMETA(cls)) + { + return NO; + } + return YES; } IMP