1// 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 2// 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 3 4// WinEH requires funclet tokens on nounwind intrinsics if they can lower to 5// regular function calls in the course of IR transformations. 6// 7// This is the case for ObjC ARC runtime intrinsics. Test that clang emits the 8// funclet tokens for llvm.objc.* calls inside catch- and cleanup-pads and that 9// they refer to their pad's SSA value. 10 11void do_something(); 12void may_throw(id); 13 14void try_catch_with_objc_intrinsic() { 15 id ex; 16 @try { 17 may_throw(ex); 18 } @catch (id ex_caught) { 19 do_something(); 20 may_throw(ex_caught); 21 } 22} 23 24// CHECK-LABEL: try_catch_with_objc_intrinsic 25// 26// CHECK: catch.dispatch: 27// CHECK-NEXT: [[CATCHSWITCH:%[0-9]+]] = catchswitch within none [label %catch] 28// CHECK-O0: unwind label %[[CLEANUP1:.*]] 29// CHECK-O2: unwind to caller 30// 31// All calls within a catchpad must have funclet tokens that refer to it: 32// CHECK: catch: 33// CHECK-NEXT: [[CATCHPAD:%[0-9]+]] = catchpad within [[CATCHSWITCH]] 34// CHECK: call 35// CHECK: @llvm.objc.retain 36// CHECK: [ "funclet"(token [[CATCHPAD]]) ] 37// CHECK: invoke 38// CHECK: do_something 39// CHECK: [ "funclet"(token [[CATCHPAD]]) ] 40// CHECK: unwind label %[[CLEANUP2:.*]] 41// CHECK: invoke 42// CHECK: may_throw 43// CHECK: [ "funclet"(token [[CATCHPAD]]) ] 44// CHECK: unwind label %[[CLEANUP2]] 45// CHECK: call 46// CHECK-O0: @llvm.objc.storeStrong 47// CHECK-O2: @llvm.objc.release 48// CHECK: [ "funclet"(token [[CATCHPAD]]) ] 49// CHECK-O0: catchret from [[CATCHPAD]] to label %catchret.dest 50// CHECK-O2: catchret from [[CATCHPAD]] to label %eh.cont 51// 52// In debug mode, this block exists and it's empty: 53// CHECK-O0: catchret.dest: 54// CHECK-O0-NEXT: br label %eh.cont 55// 56// CHECK: [[CLEANUP2]]: 57// CHECK-NEXT: [[CLEANUPPAD2:%[0-9]+]] = cleanuppad within [[CATCHPAD]] 58// CHECK: call 59// CHECK-O0: @llvm.objc.storeStrong 60// CHECK-O2: @llvm.objc.release 61// CHECK: [ "funclet"(token [[CLEANUPPAD2]]) ] 62// CHECK: cleanupret from [[CLEANUPPAD2]] 63// CHECK-O0: unwind label %[[CLEANUP1]] 64// CHECK-O2: unwind to caller 65// 66// CHECK-O0: [[CLEANUP1]]: 67// CHECK-O0-NEXT: [[CLEANUPPAD1:%[0-9]+]] = cleanuppad within none 68// CHECK-O0: call 69// CHECK-O0: @llvm.objc.storeStrong 70// CHECK-O0: [ "funclet"(token [[CLEANUPPAD1]]) ] 71// CHECK-O0: cleanupret from [[CLEANUPPAD1]] unwind to caller 72