Raise when attempting to use unimplemented classes. Check for null pointers

in more runtime functions (probably still many cases where we crash if null
pointers are passed to the API and Apple behave more tolrantly).


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@32124 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2011-02-13 06:31:05 +00:00
parent 730ecc942f
commit 0592b48e55
6 changed files with 114 additions and 27 deletions

View file

@ -1,3 +1,16 @@
2011-02-13 Richard Frith-Macdonald <rfm@gnu.org>
* 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 <rfm@gnu.org> 2011-02-12 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSObject.m: Obtain NSZombie class pointer using * Source/NSObject.m: Obtain NSZombie class pointer using

View file

@ -76,6 +76,13 @@ extern "C" {
*/ */
- (id) notImplemented: (SEL)aSel GS_NORETURN_METHOD; - (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 * Message sent when an implementation wants to explicitly require a subclass
* to implement a method (but cannot at compile time since there is no * to implement a method (but cannot at compile time since there is no

View file

@ -90,32 +90,48 @@
- (id) notImplemented: (SEL)aSel - (id) notImplemented: (SEL)aSel
{ {
char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-');
[NSException [NSException
raise: NSGenericException 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)", aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)",
NSStringFromClass([self class]), reason];
GSObjCIsInstance(self) ? "instance" : "class"];
return nil; return nil;
} }
- (id) shouldNotImplement: (SEL)aSel - (id) shouldNotImplement: (SEL)aSel
{ {
char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-');
[NSException [NSException
raise: NSGenericException raise: NSGenericException
format: @"%@(%s) should not implement %@", format: @"[%@%c%@] should not be implemented",
NSStringFromClass([self class]), NSStringFromClass([self class]), c,
GSObjCIsInstance(self) ? "instance" : "class",
aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"]; aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"];
return nil; return nil;
} }
- (id) subclassResponsibility: (SEL)aSel - (id) subclassResponsibility: (SEL)aSel
{ {
[NSException raise: NSInvalidArgumentException char c = (class_isMetaClass(object_getClass(self)) ? '+' : '-');
format: @"subclass %@(%s) should override %@",
NSStringFromClass([self class]), [NSException raise: NSGenericException
GSObjCIsInstance(self) ? "instance" : "class", format: @"[%@%c%@] should be overridden by subclass",
NSStringFromClass([self class]), c,
aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"]; aSel ? (id)NSStringFromSelector(aSel) : (id)@"(null)"];
return nil; return nil;
} }

View file

@ -155,6 +155,14 @@ static UCalendarDateFields _NSCalendarUnitToDateField (NSCalendarUnit unit)
static NSCalendar *autoupdatingCalendar = nil; static NSCalendar *autoupdatingCalendar = nil;
static NSRecursiveLock *classLock = 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 + (void) initialize
{ {
if (self == [NSLocale class]) if (self == [NSLocale class])

View file

@ -179,6 +179,14 @@ static NSMutableDictionary *allLocales = nil;
static NSDictionary *canonicalLocales = nil; static NSDictionary *canonicalLocales = nil;
static NSRecursiveLock *classLock = 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 + (void) initialize
{ {
if (self == [NSLocale class]) if (self == [NSLocale class])

View file

@ -102,21 +102,24 @@ skip_argspec(const char *types)
static Method static Method
class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector) class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector)
{ {
struct objc_method_list *methods; if (Nil != aClass)
for (methods = aClass->methods;
methods != NULL; methods = methods->method_next)
{ {
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) for (i = 0; i < methods->method_count; i++)
{ {
return method; Method_t method = &methods->method_list[i];
}
if (method->method_name->sel_id == aSelector->sel_id)
{
return method;
}
}
} }
} }
return NULL; return NULL;
@ -148,7 +151,7 @@ class_addIvar(Class cls, const char *name,
unsigned off; unsigned off;
Ivar ivar; Ivar ivar;
if (CLS_ISRESOLV(cls) || CLS_ISMETA(cls)) if (Nil == cls || CLS_ISRESOLV(cls) || CLS_ISMETA(cls))
{ {
return NO; return NO;
} }
@ -380,6 +383,10 @@ class_getInstanceMethod(Class aClass, SEL aSelector)
Method Method
class_getClassMethod(Class aClass, SEL aSelector) class_getClassMethod(Class aClass, SEL aSelector)
{ {
if (Nil == aClass)
{
return NULL;
}
return class_getInstanceMethod(aClass->class_pointer, aSelector); return class_getInstanceMethod(aClass->class_pointer, aSelector);
} }
@ -393,13 +400,17 @@ class_getClassVariable(Class cls, const char *name)
size_t size_t
class_getInstanceSize(Class cls) class_getInstanceSize(Class cls)
{ {
if (Nil == cls)
{
return 0;
}
return cls->instance_size; return cls->instance_size;
} }
Ivar Ivar
class_getInstanceVariable(Class cls, const char *name) class_getInstanceVariable(Class cls, const char *name)
{ {
if (name != NULL) if (Nil != cls && NULL != name)
{ {
while (cls != Nil) while (cls != Nil)
{ {
@ -430,6 +441,10 @@ class_getInstanceVariable(Class cls, const char *name)
const char * const char *
class_getIvarLayout(Class cls) class_getIvarLayout(Class cls)
{ {
if (Nil == cls)
{
return 0;
}
return (char *) cls->ivars; return (char *) cls->ivars;
} }
@ -444,18 +459,26 @@ class_getIvarLayout(Class cls)
IMP IMP
class_getMethodImplementation(Class cls, SEL name) class_getMethodImplementation(Class cls, SEL name)
{ {
if (Nil == cls || 0 == name)
{
return 0;
}
return (IMP) get_imp(cls, name); return (IMP) get_imp(cls, name);
} }
IMP IMP
class_getMethodImplementation_stret(Class cls, SEL name) class_getMethodImplementation_stret(Class cls, SEL name)
{ {
if (Nil == cls || 0 == name)
{
return 0;
}
return (IMP) get_imp(cls, name); return (IMP) get_imp(cls, name);
} }
const char * const char *
class_getName(Class cls) class_getName(Class cls)
{ {
if (cls == Nil) if (Nil == cls)
{ {
return "nil"; // This is what OSX does. return "nil"; // This is what OSX does.
} }
@ -471,6 +494,10 @@ void __objc_resolve_class_links(void);
Class Class
class_getSuperclass(Class cls) class_getSuperclass(Class cls)
{ {
if (Nil == cls)
{
return 0;
}
if (!CLS_ISRESOLV(cls)) if (!CLS_ISRESOLV(cls))
{ {
/* This class is not yet resolved ... so lookup superclass by name. /* This class is not yet resolved ... so lookup superclass by name.
@ -485,9 +512,13 @@ class_getSuperclass(Class cls)
} }
int 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 * const char *
@ -500,7 +531,11 @@ class_getWeakIvarLayout(Class cls)
BOOL BOOL
class_isMetaClass(Class cls) class_isMetaClass(Class cls)
{ {
return CLS_ISMETA(cls); if (Nil == cls || !CLS_ISMETA(cls))
{
return NO;
}
return YES;
} }
IMP IMP