1*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \ 2*67e74705SXin Li // RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \ 3*67e74705SXin Li // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH 4*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \ 5*67e74705SXin Li // RUN: -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \ 6*67e74705SXin Li // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX 7*67e74705SXin Li 8*67e74705SXin Li extern "C" unsigned long _exception_code(); 9*67e74705SXin Li extern "C" void might_throw(); 10*67e74705SXin Li 11*67e74705SXin Li struct HasCleanup { 12*67e74705SXin Li HasCleanup(); 13*67e74705SXin Li ~HasCleanup(); 14*67e74705SXin Li int padding; 15*67e74705SXin Li }; 16*67e74705SXin Li use_cxx()17*67e74705SXin Liextern "C" void use_cxx() { 18*67e74705SXin Li HasCleanup x; 19*67e74705SXin Li might_throw(); 20*67e74705SXin Li } 21*67e74705SXin Li 22*67e74705SXin Li // Make sure we use __CxxFrameHandler3 for C++ EH. 23*67e74705SXin Li 24*67e74705SXin Li // CXXEH-LABEL: define void @use_cxx() 25*67e74705SXin Li // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 26*67e74705SXin Li // CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 27*67e74705SXin Li // CXXEH: invoke void @might_throw() 28*67e74705SXin Li // CXXEH: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 29*67e74705SXin Li // 30*67e74705SXin Li // CXXEH: [[cont]] 31*67e74705SXin Li // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 32*67e74705SXin Li // CXXEH: ret void 33*67e74705SXin Li // 34*67e74705SXin Li // CXXEH: [[lpad]] 35*67e74705SXin Li // CXXEH: cleanuppad 36*67e74705SXin Li // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 37*67e74705SXin Li // CXXEH: cleanupret 38*67e74705SXin Li 39*67e74705SXin Li // NOCXX-LABEL: define void @use_cxx() 40*67e74705SXin Li // NOCXX-NOT: invoke 41*67e74705SXin Li // NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 42*67e74705SXin Li // NOCXX-NOT: invoke 43*67e74705SXin Li // NOCXX: call void @might_throw() 44*67e74705SXin Li // NOCXX-NOT: invoke 45*67e74705SXin Li // NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 46*67e74705SXin Li // NOCXX-NOT: invoke 47*67e74705SXin Li // NOCXX: ret void 48*67e74705SXin Li use_seh()49*67e74705SXin Liextern "C" void use_seh() { 50*67e74705SXin Li __try { 51*67e74705SXin Li might_throw(); 52*67e74705SXin Li } __except(1) { 53*67e74705SXin Li } 54*67e74705SXin Li } 55*67e74705SXin Li 56*67e74705SXin Li // Make sure we use __C_specific_handler for SEH. 57*67e74705SXin Li 58*67e74705SXin Li // CHECK-LABEL: define void @use_seh() 59*67e74705SXin Li // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 60*67e74705SXin Li // CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]] 61*67e74705SXin Li // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 62*67e74705SXin Li // 63*67e74705SXin Li // CHECK: [[lpad]] 64*67e74705SXin Li // CHECK-NEXT: %[[switch:.*]] = catchswitch within none [label %[[cpad:.*]]] unwind to caller 65*67e74705SXin Li // 66*67e74705SXin Li // CHECK: [[cpad]] 67*67e74705SXin Li // CHECK-NEXT: catchpad within %[[switch]] 68*67e74705SXin Li // CHECK: catchret {{.*}} label %[[except:[^ ]*]] 69*67e74705SXin Li // 70*67e74705SXin Li // CHECK: [[except]] 71*67e74705SXin Li // CHECK: br label %[[ret:[^ ]*]] 72*67e74705SXin Li // 73*67e74705SXin Li // CHECK: [[ret]] 74*67e74705SXin Li // CHECK: ret void 75*67e74705SXin Li // 76*67e74705SXin Li // CHECK: [[cont]] 77*67e74705SXin Li // CHECK: br label %[[ret]] 78*67e74705SXin Li use_seh_in_lambda()79*67e74705SXin Livoid use_seh_in_lambda() { 80*67e74705SXin Li ([]() { 81*67e74705SXin Li __try { 82*67e74705SXin Li might_throw(); 83*67e74705SXin Li } __except(1) { 84*67e74705SXin Li } 85*67e74705SXin Li })(); 86*67e74705SXin Li HasCleanup x; 87*67e74705SXin Li might_throw(); 88*67e74705SXin Li } 89*67e74705SXin Li 90*67e74705SXin Li // CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"() 91*67e74705SXin Li // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 92*67e74705SXin Li // CXXEH: cleanuppad 93*67e74705SXin Li 94*67e74705SXin Li // NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"() 95*67e74705SXin Li // NOCXX-NOT: invoke 96*67e74705SXin Li // NOCXX: ret void 97*67e74705SXin Li 98*67e74705SXin Li // CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this) 99*67e74705SXin Li // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 100*67e74705SXin Li // CHECK: invoke void @might_throw() #[[NOINLINE]] 101*67e74705SXin Li // CHECK: catchpad 102*67e74705SXin Li 103*67e74705SXin Li static int my_unique_global; 104*67e74705SXin Li use_seh_in_inline_func()105*67e74705SXin Liextern "C" inline void use_seh_in_inline_func() { 106*67e74705SXin Li __try { 107*67e74705SXin Li might_throw(); 108*67e74705SXin Li } __except(_exception_code() == 424242) { 109*67e74705SXin Li } 110*67e74705SXin Li __try { 111*67e74705SXin Li might_throw(); 112*67e74705SXin Li } __finally { 113*67e74705SXin Li my_unique_global = 1234; 114*67e74705SXin Li } 115*67e74705SXin Li } 116*67e74705SXin Li use_inline()117*67e74705SXin Livoid use_inline() { 118*67e74705SXin Li use_seh_in_inline_func(); 119*67e74705SXin Li } 120*67e74705SXin Li 121*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat 122*67e74705SXin Li // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 123*67e74705SXin Li // CHECK: invoke void @might_throw() 124*67e74705SXin Li // 125*67e74705SXin Li // CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)] 126*67e74705SXin Li // 127*67e74705SXin Li // CHECK: invoke void @might_throw() 128*67e74705SXin Li // 129*67e74705SXin Li // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 130*67e74705SXin Li // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]]) 131*67e74705SXin Li // CHECK: ret void 132*67e74705SXin Li // 133*67e74705SXin Li // CHECK: cleanuppad 134*67e74705SXin Li // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 135*67e74705SXin Li // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) 136*67e74705SXin Li 137*67e74705SXin Li // CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) 138*67e74705SXin Li // CHECK: icmp eq i32 %{{.*}}, 424242 139*67e74705SXin Li // CHECK: zext i1 %{{.*}} to i32 140*67e74705SXin Li // CHECK: ret i32 141*67e74705SXin Li 142*67e74705SXin Li // CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) 143*67e74705SXin Li // CHECK: store i32 1234, i32* @my_unique_global 144*67e74705SXin Li 145*67e74705SXin Li // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } 146