diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff7c15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*~ +.*.sw? +Build +Debug +Release diff --git a/Test/AssociatedObject2.m b/Test/AssociatedObject2.m new file mode 100644 index 0000000..e8f7d53 --- /dev/null +++ b/Test/AssociatedObject2.m @@ -0,0 +1,37 @@ +#include "Test.h" + +@interface MLTestClass : Test { +@public +} +- (void)someF; +@end + +@implementation MLTestClass +- (void)someF +{ +} + +@end + +static void ff(id obj, SEL _cmd) +{ +} + + +int main() +{ + static char static_char; + MLTestClass * tc; + tc = [MLTestClass new]; + objc_setAssociatedObject(tc, &static_char, (id)1223, OBJC_ASSOCIATION_ASSIGN); + [tc release]; + int i = 0; + tc = [MLTestClass new]; + objc_setAssociatedObject(tc, &static_char, (id)1223, OBJC_ASSOCIATION_ASSIGN); + SEL some_sel = sel_registerName(".some_sel"); + const char *types = "v@:"; + class_addMethod(object_getClass(tc), some_sel, + (IMP)ff, types); + int j = (int)objc_getAssociatedObject(tc, &static_char); + [tc release]; +} diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index e8db645..8e253ae 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -8,6 +8,7 @@ set(TESTS #alignTest.m AllocatePair.m AssociatedObject.m + AssociatedObject2.m BlockImpTest.m BlockTest_arc.m BoxedForeignException.m diff --git a/Test/Test.h b/Test/Test.h index d61d90b..6ca0261 100644 --- a/Test/Test.h +++ b/Test/Test.h @@ -15,6 +15,12 @@ __attribute__((objc_root_class)) @interface Test { id isa; } + (Class)class; + (id)new; +#if !__has_feature(objc_arc) +- (void)dealloc; +- (id)autorelease; +- (id)retain; +- (void)release; +#endif @end #if !__has_feature(objc_arc) diff --git a/associate.m b/associate.m index 0343363..3db8495 100644 --- a/associate.m +++ b/associate.m @@ -214,6 +214,7 @@ static Class allocateHiddenClass(Class superclass) newClass->dtable = uninstalled_dtable; newClass->instance_size = superclass->instance_size; + LOCK_RUNTIME_FOR_SCOPE(); newClass->sibling_class = superclass->subclass_list; superclass->subclass_list = newClass; @@ -238,14 +239,36 @@ static inline Class initHiddenClassForObject(id obj) static void deallocHiddenClass(id obj, SEL _cmd) { + LOCK_RUNTIME_FOR_SCOPE(); Class hiddenClass = findHiddenClass(obj); // After calling [super dealloc], the object will no longer exist. - // Free the hidden + // Free the hidden class. struct reference_list *list = object_getIndexedIvars(hiddenClass); DESTROY_LOCK(&list->lock); cleanupReferenceList(list); freeReferenceList(list->next); + fprintf(stderr, "Deallocating dtable %p\n", hiddenClass->dtable); free_dtable(hiddenClass->dtable); + // We shouldn't have any subclasses left at this point + assert(hiddenClass->subclass_list == 0); + // Remove the class from the subclass list of its superclass + Class sub = hiddenClass->super_class->subclass_list; + if (sub == hiddenClass) + { + hiddenClass->super_class->subclass_list = hiddenClass->sibling_class; + } + else + { + while (sub != NULL) + { + if ((Class)sub->sibling_class == hiddenClass) + { + sub->sibling_class = hiddenClass->sibling_class; + break; + } + sub = sub->sibling_class; + } + } // Free the class free(hiddenClass); } diff --git a/opts/CMakeLists.txt b/opts/CMakeLists.txt index aa3f794..5140443 100644 --- a/opts/CMakeLists.txt +++ b/opts/CMakeLists.txt @@ -1,7 +1,12 @@ cmake_minimum_required(VERSION 2.8) find_package(LLVM) -include(AddLLVM) +include(AddLLVM OPTIONAL RESULT_VARIABLE INCLUDED_LLVM) + +if (${INCLUDED_LLVM} STREQUAL "NOTFOUND") + message(WARNING "Failed to include AddLLVM CMake module") +else() +message("Included: '${INCLUDED_LLVM}'") add_definitions(${LLVM_DEFINITIONS}) include_directories(${LLVM_INCLUDE_DIRS}) @@ -39,3 +44,4 @@ string(REGEX REPLACE "([0-9]*).([0-9]*).*" "-DLLVM_MAJOR=\\1 -DLLVM_MINOR=\\2" L set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_VERSION} -fno-rtti") include_directories( ${LLVM_INCLUDE_DIRS} "${LLVM_SRC}/include/" "${LLVM_OBJ}/include/") +endif() # AddLLVM include failed