// RUN: %clang_cc1 -O0 -triple x86_64-pc-windows-msvc -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fobjc-arc-exceptions -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-O0 // RUN: %clang_cc1 -O2 -triple x86_64-pc-windows-msvc -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fobjc-arc-exceptions -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-O2 // WinEH requires funclet tokens on nounwind intrinsics if they can lower to // regular function calls in the course of IR transformations. // // This is the case for ObjC ARC runtime intrinsics. Test that clang emits the // funclet tokens for llvm.objc.* calls inside catch- and cleanup-pads and that // they refer to their pad's SSA value. void do_something(); void may_throw(id); void try_catch_with_objc_intrinsic() { id ex; @try { may_throw(ex); } @catch (id ex_caught) { do_something(); may_throw(ex_caught); } } // CHECK-LABEL: try_catch_with_objc_intrinsic // // CHECK: catch.dispatch: // CHECK-NEXT: [[CATCHSWITCH:%[0-9]+]] = catchswitch within none [label %catch] // CHECK-O0: unwind label %[[CLEANUP1:.*]] // CHECK-O2: unwind to caller // // All calls within a catchpad must have funclet tokens that refer to it: // CHECK: catch: // CHECK-NEXT: [[CATCHPAD:%[0-9]+]] = catchpad within [[CATCHSWITCH]] // CHECK: call // CHECK: @llvm.objc.retain // CHECK: [ "funclet"(token [[CATCHPAD]]) ] // CHECK: invoke // CHECK: do_something // CHECK: [ "funclet"(token [[CATCHPAD]]) ] // CHECK: unwind label %[[CLEANUP2:.*]] // CHECK: invoke // CHECK: may_throw // CHECK: [ "funclet"(token [[CATCHPAD]]) ] // CHECK: unwind label %[[CLEANUP2]] // CHECK: call // CHECK-O0: @llvm.objc.storeStrong // CHECK-O2: @llvm.objc.release // CHECK: [ "funclet"(token [[CATCHPAD]]) ] // CHECK-O0: catchret from [[CATCHPAD]] to label %catchret.dest // CHECK-O2: catchret from [[CATCHPAD]] to label %eh.cont // // In debug mode, this block exists and it's empty: // CHECK-O0: catchret.dest: // CHECK-O0-NEXT: br label %eh.cont // // CHECK: [[CLEANUP2]]: // CHECK-NEXT: [[CLEANUPPAD2:%[0-9]+]] = cleanuppad within [[CATCHPAD]] // CHECK: call // CHECK-O0: @llvm.objc.storeStrong // CHECK-O2: @llvm.objc.release // CHECK: [ "funclet"(token [[CLEANUPPAD2]]) ] // CHECK: cleanupret from [[CLEANUPPAD2]] // CHECK-O0: unwind label %[[CLEANUP1]] // CHECK-O2: unwind to caller // // CHECK-O0: [[CLEANUP1]]: // CHECK-O0-NEXT: [[CLEANUPPAD1:%[0-9]+]] = cleanuppad within none // CHECK-O0: call // CHECK-O0: @llvm.objc.storeStrong // CHECK-O0: [ "funclet"(token [[CLEANUPPAD1]]) ] // CHECK-O0: cleanupret from [[CLEANUPPAD1]] unwind to caller