diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index 22b9577..bec7f2b 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -36,6 +36,7 @@ set(TESTS ProtocolCreation.m ResurrectInDealloc_arc.m RuntimeTest.m + SuperMethodMissing.m WeakBlock_arc.m WeakRefLoad.m WeakReferences_arc.m diff --git a/Test/SuperMethodMissing.m b/Test/SuperMethodMissing.m new file mode 100644 index 0000000..8ea581c --- /dev/null +++ b/Test/SuperMethodMissing.m @@ -0,0 +1,46 @@ +#include "Test.h" +#include "objc/hooks.h" +#include + +@interface Test (DoesNotExist) +- (void)run; +@end + +@interface Foo : Test +@end + +@implementation Foo +- (void)run +{ + [super run]; +} +@end + +static int missing_methods; + +id forward(id self, SEL cmd, ...) +{ + Class cls = object_getClass(self); + missing_methods++; + fprintf(stderr, "Missing method: %c[%s %s]\n", class_isMetaClass(cls) ? '+' : '-', class_getName(cls),sel_getName(cmd)); + return nil; +} + +IMP no_method(id self, SEL cmd) +{ + return forward; +} + + +int +main() +{ + __objc_msg_forward2 = no_method; + Test *t = [Test new]; + [t run]; + assert(missing_methods == 1); + Foo *f = [Foo new]; + [f run]; + assert(missing_methods == 2); + //[Test run]; +} diff --git a/sendmsg2.c b/sendmsg2.c index 78a2255..54e0d9c 100644 --- a/sendmsg2.c +++ b/sendmsg2.c @@ -302,7 +302,8 @@ struct objc_slot2 *objc_slot_lookup_super2(struct objc_super *super, SEL selecto objc_send_initialize((id)class); return objc_slot_lookup_super2(super, selector); } - return (struct objc_slot2*)&nil_slot; + uncacheable_slot.imp = __objc_msg_forward2(receiver, selector); + return (struct objc_slot2*)&uncacheable_slot; } return result; } @@ -335,7 +336,11 @@ struct objc_slot *objc_slot_lookup_super(struct objc_super *super, SEL selector) objc_send_initialize((id)class); return objc_slot_lookup_super(super, selector); } - return &nil_slot_v1; + uncacheable_slot_v1.owner = Nil; + uncacheable_slot_v1.types = sel_getType_np(selector); + uncacheable_slot_v1.selector = selector; + uncacheable_slot_v1.method = __objc_msg_forward2(receiver, selector); + return &uncacheable_slot_v1; } uncacheable_slot_v1.owner = Nil; uncacheable_slot_v1.types = sel_getType_np(((struct objc_method*)result)->selector);