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