From 44d05e58a6cae3e2b985f8fd4a7e850e288a2f02 Mon Sep 17 00:00:00 2001 From: David Lobron Date: Fri, 22 Dec 2017 10:14:17 -0500 Subject: [PATCH 1/2] Minimal reproducing test case. This creates a test number 47 in the unit test suite, which fails with an exception. The exception reproduces the bug. --- Test/CMakeLists.txt | 29 ++++++++++++---------------- Test/MyException.h | 16 +++++++++++++++ Test/MyException.m | 47 +++++++++++++++++++++++++++++++++++++++++++++ Test/minRep.mm | 17 ++++++++++++++++ Test/minRep1.h | 9 +++++++++ Test/minRep1.mm | 17 ++++++++++++++++ Test/minRep2.h | 6 ++++++ Test/minRep2.mm | 24 +++++++++++++++++++++++ Test/minRepM.h | 10 ++++++++++ Test/minRepM.m | 26 +++++++++++++++++++++++++ 10 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 Test/MyException.h create mode 100644 Test/MyException.m create mode 100644 Test/minRep.mm create mode 100644 Test/minRep1.h create mode 100644 Test/minRep1.mm create mode 100644 Test/minRep2.h create mode 100644 Test/minRep2.mm create mode 100644 Test/minRepM.h create mode 100644 Test/minRepM.m diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index 4baf428..f295235 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -5,7 +5,7 @@ # List of single-file tests. set(TESTS - alignTest.m + #alignTest.m AllocatePair.m AssociatedObject.m AssociatedObject2.m @@ -19,53 +19,48 @@ set(TESTS NestedExceptions.m PropertyAttributeTest.m PropertyIntrospectionTest.m - PropertyIntrospectionTest2_arc.m + PropertyIntrospectionTest2.m ProtocolCreation.m ResurrectInDealloc_arc.m RuntimeTest.m - WeakBlock_arc.m WeakReferences_arc.m - ivar_arc.m - IVarOverlap.m objc_msgSend.m msgInterpose.m NilException.m MethodArguments.m - zeroSizedIVar.m - exchange.m ) # Function for adding a test. This takes the name of the test and the list of # source files as arguments. -function(addtest_flags TEST_NAME FLAGS TEST_SOURCE) - if (${TEST_NAME} MATCHES ".*_arc") +function(addtest_flags TEST FLAGS TEST_SOURCE) + if (TEST MATCHES ".*_arc") # Only compile the main file with ARC set_source_files_properties(${TEST_SOURCE} COMPILE_FLAGS "-fobjc-arc") # Add the ARC-incompatible definitions of the test class. list(APPEND TEST_SOURCE "Test.m") endif() - add_executable(${TEST_NAME} ${TEST_SOURCE}) - add_test(${TEST_NAME} ${TEST_NAME}) + add_executable(${TEST} ${TEST_SOURCE}) + add_test(${TEST} ${TEST}) set(ARC "") - set_target_properties(${TEST_NAME} PROPERTIES + set_target_properties(${TEST} PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}" COMPILE_FLAGS "-fobjc-runtime=gnustep-1.7 -fblocks ${FLAGS}" LINKER_LANGUAGE C ) - set_property(TEST ${TEST_NAME} PROPERTY + set_property(TEST ${TEST} PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=" ) - target_link_libraries(${TEST_NAME} objc) + target_link_libraries(${TEST} objc) endfunction(addtest_flags) foreach(TEST_SOURCE ${TESTS}) get_filename_component(TEST ${TEST_SOURCE} NAME_WE) - addtest_flags(${TEST} "-O0 -UNDEBUG" ${TEST_SOURCE}) - addtest_flags("${TEST}_optimised" "-O3 -UNDEBUG" ${TEST_SOURCE}) + addtest_flags(${TEST} "-O0" ${TEST_SOURCE}) + addtest_flags("${TEST}_optimised" "-O3" ${TEST_SOURCE}) endforeach() # Tests that are more than a single file. addtest_flags(CXXExceptions "-O0" "CXXException.m;CXXException.cc") addtest_flags(CXXExceptions_optimised "-O3" "CXXException.m;CXXException.cc") - +addtest_flags(MinRep "-O0" "minRep1.mm;minRep2.mm;minRep.mm;minRepM.m;ModTest.m;MyException.m") diff --git a/Test/MyException.h b/Test/MyException.h new file mode 100644 index 0000000..8ca3d4c --- /dev/null +++ b/Test/MyException.h @@ -0,0 +1,16 @@ +#include "ModTest.h" + +@interface MyException : Test { +@private + char *_name; + char *_reason; +} ++ (void) raise: (char *)name + format: (char *)reason; +- (void) raise; +- (char *)name; +- (char *)reason; +- (MyException *)initWithName:(char *)name + reason:(char *)reason; + +@end diff --git a/Test/MyException.m b/Test/MyException.m new file mode 100644 index 0000000..316f5cf --- /dev/null +++ b/Test/MyException.m @@ -0,0 +1,47 @@ +#import "MyException.h" + +@implementation MyException + +- (MyException *)initWithName:(char *)name + reason:(char *)reason +{ + if ((self = [super init]) != nil) { + _name = name; + _reason = reason; + } + return self; +} + ++ (void) raise: (char *)name + format: (char *)reason +{ + MyException *e = [[[MyException alloc] initWithName:name + reason:reason] autorelease]; + [e raise]; +} + +- (void) dealloc +{ + if (_name) { + free(_name); + } + if (_reason) { + free(_reason); + } +} + +- (void) raise { + @throw self; +} + +- (char*)name +{ + return _name; +} + +- (char*)reason +{ + return _reason; +} + +@end diff --git a/Test/minRep.mm b/Test/minRep.mm new file mode 100644 index 0000000..6d75f60 --- /dev/null +++ b/Test/minRep.mm @@ -0,0 +1,17 @@ +#import "ModTest.h" + +#import "minRepM.h" + +#import "stdio.h" + +int main (int iArgc, const char *iArgv[]) +{ + @autoreleasepool { + MinRepM *mrm = [MinRepM new]; + printf("Poking\n"); + [mrm poke]; + printf("Poked\n"); + } + + return 0; +} diff --git a/Test/minRep1.h b/Test/minRep1.h new file mode 100644 index 0000000..b92e360 --- /dev/null +++ b/Test/minRep1.h @@ -0,0 +1,9 @@ +#import "ModTest.h" + +#import "minRep2.h" + +@interface MinRep1 : Test { +} +- (void)poke; + +@end diff --git a/Test/minRep1.mm b/Test/minRep1.mm new file mode 100644 index 0000000..88a2ad4 --- /dev/null +++ b/Test/minRep1.mm @@ -0,0 +1,17 @@ +#import "ModTest.h" + +#import "minRep1.h" + +#import "stdio.h" + +@implementation MinRep1 + +- (void)poke +{ + MinRep2 *mr2 = [MinRep2 new]; + printf("Poking from minRep1\n"); + [mr2 poke]; + [mr2 release]; +} + +@end diff --git a/Test/minRep2.h b/Test/minRep2.h new file mode 100644 index 0000000..3522281 --- /dev/null +++ b/Test/minRep2.h @@ -0,0 +1,6 @@ +#import "ModTest.h" + +@interface MinRep2 : Test { +} +- (void)poke; +@end diff --git a/Test/minRep2.mm b/Test/minRep2.mm new file mode 100644 index 0000000..592e98e --- /dev/null +++ b/Test/minRep2.mm @@ -0,0 +1,24 @@ +#import "ModTest.h" + +#import "minRep2.h" +#import "MyException.h" + +#import "stdio.h" + +@implementation MinRep2 + +- (void)poke { + @try { + printf("Raising MyException\n"); + MyException *e = [MyException new]; + @throw e; + } @catch (MyException *localException) { + printf("Caught - re-raising\n"); + [localException retain]; + [[localException autorelease] raise]; + } @catch(...) { + printf("Caught in general block\n"); + } +} + +@end diff --git a/Test/minRepM.h b/Test/minRepM.h new file mode 100644 index 0000000..da5631e --- /dev/null +++ b/Test/minRepM.h @@ -0,0 +1,10 @@ +#import "ModTest.h" + +#import "minRep1.h" + +@interface MinRepM : Test { + MinRep1 *_mr1; +} +- (void)poke; + +@end; diff --git a/Test/minRepM.m b/Test/minRepM.m new file mode 100644 index 0000000..eaa011d --- /dev/null +++ b/Test/minRepM.m @@ -0,0 +1,26 @@ +#import "ModTest.h" + +#import "minRepM.h" +#import "minRep1.h" + +#import "MyException.h" + +#import "stdio.h" + +@implementation MinRepM + +- (void)poke { + _mr1 = [MinRep1 new]; + @try { + printf("Poking from minRepM\n"); + if (_mr1) { + [_mr1 poke]; + } + printf("Poked from minRepM\n"); + } @catch (MyException *localException) { + printf("In NS_HANDLER block, %s %s\n", + [localException name], [localException reason]); + } +} + +@end From c036265ecee4eda632bd91e6bbc9b49a33bebb3e Mon Sep 17 00:00:00 2001 From: David Lobron Date: Fri, 22 Dec 2017 10:44:27 -0500 Subject: [PATCH 2/2] Remove changes introduced accidentally because I was using an older version of this file (sync with 0b5f66393a6d81e86028c4d91f7866d7482acd1c). --- Test/CMakeLists.txt | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index f295235..074827f 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -5,7 +5,7 @@ # List of single-file tests. set(TESTS - #alignTest.m + alignTest.m AllocatePair.m AssociatedObject.m AssociatedObject2.m @@ -19,45 +19,50 @@ set(TESTS NestedExceptions.m PropertyAttributeTest.m PropertyIntrospectionTest.m - PropertyIntrospectionTest2.m + PropertyIntrospectionTest2_arc.m ProtocolCreation.m ResurrectInDealloc_arc.m RuntimeTest.m + WeakBlock_arc.m WeakReferences_arc.m + ivar_arc.m + IVarOverlap.m objc_msgSend.m msgInterpose.m NilException.m MethodArguments.m + zeroSizedIVar.m + exchange.m ) # Function for adding a test. This takes the name of the test and the list of # source files as arguments. -function(addtest_flags TEST FLAGS TEST_SOURCE) - if (TEST MATCHES ".*_arc") +function(addtest_flags TEST_NAME FLAGS TEST_SOURCE) + if (${TEST_NAME} MATCHES ".*_arc") # Only compile the main file with ARC set_source_files_properties(${TEST_SOURCE} COMPILE_FLAGS "-fobjc-arc") # Add the ARC-incompatible definitions of the test class. list(APPEND TEST_SOURCE "Test.m") endif() - add_executable(${TEST} ${TEST_SOURCE}) - add_test(${TEST} ${TEST}) + add_executable(${TEST_NAME} ${TEST_SOURCE}) + add_test(${TEST_NAME} ${TEST_NAME}) set(ARC "") - set_target_properties(${TEST} PROPERTIES + set_target_properties(${TEST_NAME} PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}" COMPILE_FLAGS "-fobjc-runtime=gnustep-1.7 -fblocks ${FLAGS}" LINKER_LANGUAGE C ) - set_property(TEST ${TEST} PROPERTY + set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=" ) - target_link_libraries(${TEST} objc) + target_link_libraries(${TEST_NAME} objc) endfunction(addtest_flags) foreach(TEST_SOURCE ${TESTS}) get_filename_component(TEST ${TEST_SOURCE} NAME_WE) - addtest_flags(${TEST} "-O0" ${TEST_SOURCE}) - addtest_flags("${TEST}_optimised" "-O3" ${TEST_SOURCE}) + addtest_flags(${TEST} "-O0 -UNDEBUG" ${TEST_SOURCE}) + addtest_flags("${TEST}_optimised" "-O3 -UNDEBUG" ${TEST_SOURCE}) endforeach() # Tests that are more than a single file.