unwind.m 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // TEST_CONFIG
  2. #include "test.h"
  3. #include <objc/objc-exception.h>
  4. #include <Foundation/NSObject.h>
  5. static int state;
  6. @interface Foo : NSObject @end
  7. @interface Bar : NSObject @end
  8. @interface Foo (Unimplemented)
  9. +(void)method;
  10. @end
  11. @implementation Bar @end
  12. @implementation Foo
  13. -(void)check { state++; }
  14. +(void)check { testassert(!"caught class object, not instance"); }
  15. static id exc;
  16. static void handler(id unused, void *ctx) __attribute__((used));
  17. static void handler(id unused __unused, void *ctx __unused)
  18. {
  19. testassert(state == 3); state++;
  20. }
  21. +(BOOL) resolveClassMethod:(SEL)__unused name
  22. {
  23. testassert(state == 1); state++;
  24. #if TARGET_OS_OSX
  25. objc_addExceptionHandler(&handler, 0);
  26. testassert(state == 2);
  27. #else
  28. state++; // handler would have done this
  29. #endif
  30. state++;
  31. exc = [Foo new];
  32. @throw exc;
  33. }
  34. @end
  35. int main()
  36. {
  37. // unwind exception and alt handler through objc_msgSend()
  38. PUSH_POOL {
  39. const int count = is_guardmalloc() ? 1000 : 100000;
  40. state = 0;
  41. for (int i = 0; i < count; i++) {
  42. @try {
  43. testassert(state == 0); state++;
  44. [Foo method];
  45. testassert(0);
  46. } @catch (Bar *e) {
  47. testassert(0);
  48. } @catch (Foo *e) {
  49. testassert(e == exc);
  50. testassert(state == 4); state++;
  51. testassert(state == 5); [e check]; // state++
  52. RELEASE_VAR(exc);
  53. } @catch (id e) {
  54. testassert(0);
  55. } @catch (...) {
  56. testassert(0);
  57. } @finally {
  58. testassert(state == 6); state++;
  59. }
  60. testassert(state == 7); state = 0;
  61. }
  62. } POP_POOL;
  63. succeed(__FILE__);
  64. }