Added a hook that defines the behaviour when you call a method with the wrong signature.

This commit is contained in:
theraven 2010-09-01 12:48:39 +00:00
parent 06015757a7
commit 0284155f2d
3 changed files with 27 additions and 15 deletions

View File

@ -56,3 +56,11 @@ OBJC_HOOK void (*_objc_unexpected_exception)(id exception);
* to
*/
OBJC_HOOK Class (*_objc_class_for_boxing_foreign_exception)(int64_t exceptionClass);
/**
* Hook called when selector type does not match the method type in the
* receiver. This should return the slot to use instead, although it may throw
* an exception or perform some other action.
*/
extern struct objc_slot* (*_objc_selector_type_mismatch)(Class cls,
SEL selector, struct objc_slot *result);

View File

@ -54,8 +54,6 @@ inline static BOOL isSelRegistered(SEL sel)
return NO;
}
#ifdef TYPE_DEPENDENT_DISPATCH
/**
* Skip anything in a type encoding that is irrelevant to the comparison
* between selectors, including type qualifiers and argframe info.
@ -90,6 +88,8 @@ static BOOL selector_types_equal(const char *t1, const char *t2)
return YES;
}
#ifdef TYPE_DEPENDENT_DISPATCH
static BOOL selector_types_equivalent(const char *t1, const char *t2)
{
// We always treat untyped selectors as having the same type as typed
@ -202,7 +202,6 @@ static inline void add_selector_to_table(SEL aSel, int32_t uid, uint32_t idx)
static inline void register_selector_locked(SEL aSel)
{
uintptr_t idx = selector_count++;
SEL original = selector_lookup(aSel->name, 0);
if (NULL == aSel->types)
{
fprintf(stderr, "Registering selector %d %s\n", idx, sel_getName(aSel));

View File

@ -27,6 +27,20 @@ static Slot_t objc_msg_forward3_null(id receiver, SEL op) { return &nil_slot; }
id (*objc_proxy_lookup)(id receiver, SEL op) = objc_proxy_lookup_null;
Slot_t (*__objc_msg_forward3)(id receiver, SEL op) = objc_msg_forward3_null;
static struct objc_slot* objc_selector_type_mismatch(Class cls, SEL
selector, Slot_t result)
{
fprintf(stderr, "Calling [%s %c%s] with incorrect signature. "
"Method has %s, selector has %s\n",
cls->name,
class_isMetaClass(cls) ? '+' : '-',
sel_getName(selector),
result->types,
sel_getType_np(selector));
return result;
}
struct objc_slot* (*_objc_selector_type_mismatch)(Class cls, SEL
selector, struct objc_slot *result) = objc_selector_type_mismatch;
static
// Uncomment for debugging
//__attribute__((noinline))
@ -66,12 +80,8 @@ retry:;
}
if ((result = objc_dtable_lookup(dtable, get_untyped_idx(selector))))
{
fprintf(stderr, "Calling %s with incorrect signature. "
"Method has %s, selector has %s\n",
sel_getName(selector),
result->types,
sel_getType_np(selector));
return result;
return _objc_selector_type_mismatch((*receiver)->isa, selector,
result);
}
id newReceiver = objc_proxy_lookup(*receiver, selector);
// If some other library wants us to play forwarding games, try
@ -265,12 +275,7 @@ Slot_t objc_get_slot(Class cls, SEL selector)
}
if ((result = objc_dtable_lookup(dtable, get_untyped_idx(selector))))
{
fprintf(stderr, "Calling %s with incorrect signature. "
"Method has %s, selector has %s\n",
sel_getName(selector),
result->types,
sel_getType_np(selector));
return result;
return _objc_selector_type_mismatch(cls, selector, result);
}
}
}