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 8 extern "C" unsigned long _exception_code(); 9 extern "C" void might_throw(); 10 11 struct HasCleanup { 12 HasCleanup(); 13 ~HasCleanup(); 14 int padding; 15 }; 16 17 extern "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: landingpad { i8*, i32 } 36 // CXXEH-NEXT: cleanup 37 // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 38 // CXXEH: br label %[[resume:[^ ]*]] 39 // 40 // CXXEH: [[resume]] 41 // CXXEH: resume 42 43 // NOCXX-LABEL: define void @use_cxx() 44 // NOCXX-NOT: invoke 45 // NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 46 // NOCXX-NOT: invoke 47 // NOCXX: call void @might_throw() 48 // NOCXX-NOT: invoke 49 // NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) 50 // NOCXX-NOT: invoke 51 // NOCXX: ret void 52 53 extern "C" void use_seh() { 54 __try { 55 might_throw(); 56 } __except(1) { 57 } 58 } 59 60 // Make sure we use __C_specific_handler for SEH. 61 62 // CHECK-LABEL: define void @use_seh() 63 // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 64 // CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]] 65 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 66 // 67 // CHECK: [[cont]] 68 // CHECK: br label %[[ret:[^ ]*]] 69 // 70 // CHECK: [[lpad]] 71 // CHECK: landingpad { i8*, i32 } 72 // CHECK-NEXT: catch i8* 73 // 74 // CHECK: br label %[[ret]] 75 // 76 // CHECK: [[ret]] 77 // CHECK: ret void 78 79 void 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: landingpad { i8*, i32 } 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>@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this) 99 // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 100 // CHECK: invoke void @might_throw() #[[NOINLINE]] 101 // CHECK: landingpad { i8*, i32 } 102 103 static int my_unique_global; 104 105 extern "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 117 void 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: landingpad { i8*, i32 } 126 // CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*) 127 // 128 // CHECK: invoke void @might_throw() 129 // 130 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 131 // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]]) 132 // CHECK: ret void 133 // 134 // CHECK: landingpad { i8*, i32 } 135 // CHECK-NEXT: cleanup 136 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 137 // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) 138 139 // 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) 140 // CHECK: icmp eq i32 %{{.*}}, 424242 141 // CHECK: zext i1 %{{.*}} to i32 142 // CHECK: ret i32 143 144 // 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) 145 // CHECK: store i32 1234, i32* @my_unique_global 146 147 // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } 148