From fb2e6756f6a43bb040721029daadb4f6f5f49499 Mon Sep 17 00:00:00 2001 From: theraven Date: Mon, 14 Jan 2013 10:34:17 +0000 Subject: [PATCH] Fix (and add test case for) a bug where objc_allocateClassPair() failed if the superclass had not yet been loaded. --- Test/AllocatePair.m | 38 ++++++++++++++++++++++++++++++++++++++ Test/CMakeLists.txt | 1 + class_table.c | 2 +- runtime.c | 14 ++++++++++++-- 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 Test/AllocatePair.m diff --git a/Test/AllocatePair.m b/Test/AllocatePair.m new file mode 100644 index 0000000..fd892f2 --- /dev/null +++ b/Test/AllocatePair.m @@ -0,0 +1,38 @@ +#include "Test.h" +#include +#include + +// Regression test for a bug where allocating a class as a subclass of an +// unresolved class failed. + +static int loaded; + +static void load(Class self, SEL _cmd) +{ + loaded++; +} + +int main() +{ + Class a, b, c, d, e; + + a = objc_allocateClassPair([Test class], "A", 0); + objc_registerClassPair(a); + + b = objc_allocateClassPair(a, "B", 0); + class_addMethod(object_getClass(b), @selector(load), (IMP)load, "@:"); + objc_registerClassPair(b); + class_getSuperclass(b); + + c = objc_allocateClassPair(b, "C", 0); + objc_registerClassPair(c); + d = objc_allocateClassPair(c, "D", 0); + objc_registerClassPair(d); + e = objc_allocateClassPair(d, "E", 0); + objc_registerClassPair(e); + assert(loaded == 0); + + return 0; +} + + diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index a8cb573..7893406 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -5,6 +5,7 @@ # List of single-file tests. set(TESTS + AllocatePair.m BlockImpTest.m BoxedForeignException.m ExceptionTest.m diff --git a/class_table.c b/class_table.c index 8feb1f4..d0eb7be 100644 --- a/class_table.c +++ b/class_table.c @@ -486,7 +486,7 @@ Class class_getSuperclass(Class cls) if (Nil == cls) { return Nil; } if (!objc_test_class_flag(cls, objc_class_flag_resolved)) { - objc_resolve_class(cls); + return objc_getClass((const char*)cls->super_class); } return cls->super_class; } diff --git a/runtime.c b/runtime.c index 5160855..197bcca 100644 --- a/runtime.c +++ b/runtime.c @@ -698,8 +698,18 @@ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraByt // Initialize the metaclass // Set the meta-metaclass pointer to the name. The runtime will fix this // in objc_resolve_class(). - metaClass->isa = (Class)superclass->isa->isa->name; - metaClass->super_class = superclass->isa; + // If the superclass is not yet resolved, then we need to look it up + // via the class table. + if (!objc_test_class_flag(superclass, objc_class_flag_resolved)) + { + metaClass->super_class = (Class)objc_getClass((char*)superclass->super_class); + metaClass->isa = (Class)metaClass->super_class->isa->name; + } + else + { + metaClass->isa = (Class)superclass->isa->isa->name; + metaClass->super_class = superclass->isa; + } } metaClass->name = strdup(name); metaClass->info = objc_class_flag_meta | objc_class_flag_user_created |