1 // RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s 2 3 // Test we maintain at least a basic amount of interoperation between 4 // ObjC and C++ exceptions in the legacy runtime. 5 6 // rdar://12364847 7 8 void foo(void); 9 10 void test0(id obj) { 11 @synchronized(obj) { 12 foo(); 13 } 14 } 15 // CHECK-LABEL: define void @_Z5test0P11objc_object( 16 // Enter the @synchronized block. 17 // CHECK: call i32 @objc_sync_enter(i8* [[OBJ:%.*]]) 18 // CHECK: call void @objc_exception_try_enter([[BUF_T:%.*]]* nonnull [[BUF:%.*]]) 19 // CHECK-NEXT: [[T0:%.*]] = getelementptr [[BUF_T]], [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0 20 // CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* [[T0]]) 21 // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 22 // CHECK-NEXT: br i1 [[T2]], 23 24 // Body. 25 // CHECK: invoke void @_Z3foov() 26 27 // Leave the @synchronized. The reload of obj here is unnecessary. 28 // CHECK: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]]) 29 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** 30 // CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T0]]) 31 // CHECK-NEXT: ret void 32 33 // Real EH cleanup. 34 // CHECK: [[T0:%.*]] = landingpad 35 // CHECK-NEXT: cleanup 36 // CHECK-NEXT: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]]) 37 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** 38 // CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T0]]) 39 // CHECK-NEXT: resume 40 41 // ObjC EH "cleanup". 42 // CHECK: [[T0:%.*]] = load i8*, i8** 43 // CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T0]]) 44 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_exception_extract([[BUF_T]]* nonnull [[BUF]]) 45 // CHECK-NEXT: call void @objc_exception_throw(i8* [[T0]]) 46 // CHECK-NEXT: unreachable 47 48 void test1(id obj, bool *failed) { 49 @try { 50 foo(); 51 } @catch (...) { 52 *failed = true; 53 } 54 } 55 // CHECK-LABEL: define void @_Z5test1P11objc_objectPb( 56 // Enter the @try block. 57 // CHECK: call void @objc_exception_try_enter([[BUF_T]]* nonnull [[BUF:%.*]]) 58 // CHECK-NEXT: [[T0:%.*]] = getelementptr [[BUF_T]], [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0 59 // CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* [[T0]]) 60 // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 61 // CHECK-NEXT: br i1 [[T2]], 62 63 // Body. 64 // CHECK: invoke void @_Z3foov() 65 66 // Leave the @try. 67 // CHECK: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]]) 68 // CHECK-NEXT: br label 69 // CHECK: ret void 70 71 // Real EH cleanup. 72 // CHECK: [[T0:%.*]] = landingpad 73 // CHECK-NEXT: cleanup 74 // CHECK-NEXT: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]]) 75 // CHECK-NEXT: resume 76 77 // Catch handler. Reload of 'failed' address is unnecessary. 78 // CHECK: [[T0:%.*]] = load i8*, i8** 79 // CHECK-NEXT: store i8 1, i8* [[T0]], 80 // CHECK-NEXT: br label 81