In some irritating circumstances, the load order can cause a +load message to trigger other code, which sends messages with selectors that have not been mapped yet.

The runtime was handling the message lookup correctly in this case, but only as a side-effect of the fallback code from when type-dependent dispatch is not possible.  This resulted in a confusing warning message, telling you that you were calling a method with an incorrect signature, when the two signatures that it printed were the same.

This case is now handled correctly, so the warning disappears (unless you really are calling a method with the wrong signature and have TDD enabled).
This commit is contained in:
theraven 2010-08-31 20:40:08 +00:00
parent e9b129d878
commit 42a545fc7c
4 changed files with 25 additions and 3 deletions

View File

@ -131,7 +131,7 @@ void __objc_init_class_tables(void)
// Loader functions
////////////////////////////////////////////////////////////////////////////////
BOOL objc_resolve_class(Class cls)
BOOL objc_resolve_class(Class cls)
{
// Skip this if the class is already resolved.
if (objc_test_class_flag(cls, objc_class_flag_resolved)) { return YES; }

View File

@ -33,5 +33,14 @@ static uint32_t get_untyped_idx(SEL aSel)
return (uint32_t)(uintptr_t)untyped->name;
}
/**
* Returns whether a selector is mapped.
*/
BOOL sel_is_mapped(SEL selector);
/**
* Registers the selector. This selector may be returned later, so it must not
* be freed.
*/
SEL objc_register_selector(SEL aSel);
#endif // OBJC_SELECTOR_H_INCLUDED

View File

@ -256,7 +256,7 @@ static inline void register_selector_locked(SEL aSel)
/**
* Registers a selector. This assumes that the argument is never deallocated.
*/
static SEL objc_register_selector(SEL aSel)
SEL objc_register_selector(SEL aSel)
{
if (isSelRegistered(aSel))
{
@ -486,7 +486,7 @@ SEL sel_register_name(const char *name)
return sel_registerName(name);
}
SEL sel_register_typed_name (const char *name, const char *type)
SEL sel_register_typed_name(const char *name, const char *type)
{
return sel_registerTypedName_np(name, type);
}

View File

@ -35,6 +35,7 @@ Slot_t objc_msg_lookup_internal(id *receiver,
SEL selector,
id sender)
{
retry:;
Slot_t result = objc_dtable_lookup((*receiver)->isa->dtable,
PTR_TO_IDX(selector->name));
if (0 == result)
@ -56,6 +57,13 @@ Slot_t objc_msg_lookup_internal(id *receiver,
}
if (0 == result)
{
if (!sel_is_mapped(selector))
{
objc_register_selector(selector);
// This should be a tail call, but GCC is stupid and won't let
// us tail call an always_inline function.
goto retry;
}
if ((result = objc_dtable_lookup(dtable, get_untyped_idx(selector))))
{
fprintf(stderr, "Calling %s with incorrect signature. "
@ -250,6 +258,11 @@ Slot_t objc_get_slot(Class cls, SEL selector)
}
if (NULL == result)
{
if (!sel_is_mapped(selector))
{
objc_register_selector(selector);
return objc_get_slot(cls, selector);
}
if ((result = objc_dtable_lookup(dtable, get_untyped_idx(selector))))
{
fprintf(stderr, "Calling %s with incorrect signature. "