2 llvm-gcc unavoidably warns about our deliberately out-of-order handlers
5 .*exc.m: In function .*
6 .*exc.m:\d+: warning: exception of type .* will be caught
7 .*exc.m:\d+: warning: by earlier handler for .*
8 .*exc.m:\d+: warning: exception of type .* will be caught
9 .*exc.m:\d+: warning: by earlier handler for .*
10 .*exc.m:\d+: warning: exception of type .* will be caught
11 .*exc.m:\d+: warning: by earlier handler for .*
18 #include <objc/runtime.h>
19 #include <objc/objc-exception.h>
21 static volatile int state = 0;
24 #if defined(USE_FOUNDATION)
26 #include <Foundation/Foundation.h>
28 @interface Super : NSException @end
30 +(id)exception { return AUTORELEASE([[self alloc] initWithName:@"Super" reason:@"reason" userInfo:nil]); }
31 -(void)check { state++; }
32 +(void)check { testassert(!"caught class object, not instance"); }
35 #define FILENAME "nsexc.m"
39 @interface Super : TestRoot @end
41 +(id)exception { return AUTORELEASE([self new]); }
42 -(void)check { state++; }
43 +(void)check { testassert(!"caught class object, not instance"); }
46 #define FILENAME "exc.m"
50 @interface Sub : Super @end
55 #if __OBJC2__ && !TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE
56 void altHandlerFail(id unused __unused, void *context __unused)
58 fail("altHandlerFail called");
61 #define ALT_HANDLER(n) \
62 void altHandler##n(id unused __unused, void *context) \
64 testassert(context == (void*)&altHandler##n); \
65 testassert(state == n); \
78 static void throwWithAltHandler(void) __attribute__((noinline));
79 static void throwWithAltHandler(void)
83 uintptr_t token = objc_addExceptionHandler(altHandler3, (void*)altHandler3);
84 // state++ inside alt handler
85 @throw [Super exception];
87 objc_removeExceptionHandler(token);
96 static void throwWithAltHandlerAndRethrow(void) __attribute__((noinline));
97 static void throwWithAltHandlerAndRethrow(void)
101 uintptr_t token = objc_addExceptionHandler(altHandler3, (void*)altHandler3);
102 // state++ inside alt handler
103 @throw [Super exception];
105 objc_removeExceptionHandler(token);
108 testassert(state == 4);
117 #if __cplusplus && __OBJC2__
129 testprintf("try-catch-finally, exception caught exactly\n");
136 @throw [Super exception];
141 [e check]; // state++
151 testassert(state == 6);
154 testprintf("try-finally, no exception thrown\n");
170 testassert(state == 4);
173 testprintf("try-finally, with exception\n");
180 @throw [Super exception];
190 [e check]; // state++
192 testassert(state == 5);
195 testprintf("try-catch-finally, no exception\n");
213 testassert(state == 4);
216 testprintf("try-catch-finally, exception not caught\n");
223 @throw [Super exception];
236 [e check]; // state++
238 testassert(state == 5);
241 testprintf("try-catch-finally, exception caught exactly, rethrown\n");
248 @throw [Super exception];
253 [e check]; // state++
264 [e check]; // state++
266 testassert(state == 7);
269 testprintf("try-catch, no exception\n");
284 testassert(state == 3);
287 testprintf("try-catch, exception not caught\n");
294 @throw [Super exception];
304 [e check]; // state++
306 testassert(state == 4);
309 testprintf("try-catch, exception caught exactly\n");
316 @throw [Super exception];
321 [e check]; // state++
328 testassert(state == 5);
331 testprintf("try-catch, exception caught exactly, rethrown\n");
338 @throw [Super exception];
343 [e check]; // state++
351 [e check]; // state++
353 testassert(state == 6);
356 testprintf("try-catch, exception caught exactly, thrown again explicitly\n");
363 @throw [Super exception];
368 [e check]; // state++
376 [e check]; // state++
378 testassert(state == 6);
381 testprintf("try-catch, default catch, rethrown\n");
388 @throw [Super exception];
400 [e check]; // state++
402 testassert(state == 5);
405 testprintf("try-catch, default catch, rethrown and caught inside nested handler\n");
412 @throw [Super exception];
424 } @catch (Super *e) {
426 [e check]; // state++
440 testassert(state == 9);
443 testprintf("try-catch, default catch, rethrown inside nested handler but not caught\n");
450 @throw [Super exception];
474 [e check]; // state++
476 testassert(state == 7);
479 #if __cplusplus && __OBJC2__
480 testprintf("C++ try/catch, Objective-C exception superclass\n");
489 @throw [Super exception];
505 [e check]; // state++
512 [e check]; // state++;
514 testassert(state == 8);
517 testprintf("C++ try/catch, Objective-C exception subclass\n");
526 @throw [Sub exception];
540 [e check]; // state++
549 [e check]; // state++;
551 testassert(state == 8);
556 #if !__OBJC2__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
557 // alt handlers for modern Mac OS only
561 // run a lot to catch failed unregistration (runtime complains at 1000)
562 #define ALT_HANDLER_REPEAT 2000
565 testprintf("alt handler, no exception\n");
567 for (i = 0; i < ALT_HANDLER_REPEAT; i++) {
573 uintptr_t token = objc_addExceptionHandler(altHandlerFail, 0);
575 objc_removeExceptionHandler(token);
584 testassert(state == 3);
588 testprintf("alt handler, exception thrown through\n");
590 for (i = 0; i < ALT_HANDLER_REPEAT; i++) {
597 uintptr_t token = objc_addExceptionHandler(altHandler2, (void*)altHandler2);
598 // state++ inside alt handler
599 @throw [Super exception];
601 objc_removeExceptionHandler(token);
609 testassert(state == 3);
611 [e check]; // state++
613 testassert(state == 5);
618 testprintf("alt handler, nested\n");
620 for (i = 0; i < ALT_HANDLER_REPEAT; i++) {
627 // same-level handlers called in FIFO order (not stack-like)
628 uintptr_t token = objc_addExceptionHandler(altHandler4, (void*)altHandler4);
629 // state++ inside alt handler
630 uintptr_t token2 = objc_addExceptionHandler(altHandler5, (void*)altHandler5);
631 // state++ inside alt handler
632 throwWithAltHandler(); // state += 2 inside
634 objc_removeExceptionHandler(token);
635 objc_removeExceptionHandler(token2);
638 testassert(state == 6);
640 [e check]; // state++;
647 testassert(state == 9);
652 testprintf("alt handler, nested, rethrows in between\n");
654 for (i = 0; i < ALT_HANDLER_REPEAT; i++) {
661 // same-level handlers called in FIFO order (not stack-like)
662 uintptr_t token = objc_addExceptionHandler(altHandler5, (void*)altHandler5);
663 // state++ inside alt handler
664 uintptr_t token2 = objc_addExceptionHandler(altHandler6, (void*)altHandler6);
665 // state++ inside alt handler
666 throwWithAltHandlerAndRethrow(); // state += 3 inside
668 objc_removeExceptionHandler(token);
669 objc_removeExceptionHandler(token2);
672 testassert(state == 7);
679 testassert(state == 8);
681 [e check]; // state++
683 testassert(state == 10);
688 testprintf("alt handler, exception thrown and caught inside\n");
690 for (i = 0; i < ALT_HANDLER_REPEAT; i++) {
695 uintptr_t token = objc_addExceptionHandler(altHandlerFail, 0);
698 @throw [Super exception];
703 [e check]; // state++
706 objc_removeExceptionHandler(token);
711 testassert(state == 5);
716 #if defined(USE_FOUNDATION)
717 testprintf("alt handler, rdar://10055775\n");
719 for (i = 0; i < ALT_HANDLER_REPEAT; i++) {
723 uintptr_t token = objc_addExceptionHandler(altHandler1, (void*)altHandler1);
725 id x = [NSArray array];
729 // state++ inside alt handler
730 [NSException raise:@"foo" format:@"bar"];
732 objc_removeExceptionHandler(token);
734 testassert(state == 2);
738 // defined(USE_FOUNDATION)
747 #if __cplusplus && __OBJC2__
748 std::set_terminate(terminator);
750 fail("should not have returned from objc_terminate()");