1 // RUN: %clang_cc1 -no-opaque-pointers -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 -no-opaque-pointers -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \ 5 // RUN: -o - -mconstructor-aliases -O1 -disable-llvm-passes | \ 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 dso_local void @use_cxx() 25 // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 26 // CXXEH: call noundef %struct.HasCleanup* @"??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 @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* {{[^,]*}} %{{.*}}) 32 // CXXEH: ret void 33 // 34 // CXXEH: [[lpad]] 35 // CXXEH: cleanuppad 36 // CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* {{[^,]*}} %{{.*}}) 37 // CXXEH: cleanupret 38 39 // NOCXX-LABEL: define dso_local void @use_cxx() 40 // NOCXX-NOT: invoke 41 // NOCXX: call noundef %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* {{[^,]*}} %{{.*}}) 42 // NOCXX-NOT: invoke 43 // NOCXX: call void @might_throw() 44 // NOCXX-NOT: invoke 45 // NOCXX: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* {{[^,]*}} %{{.*}}) 46 // NOCXX-NOT: invoke 47 // NOCXX: ret void 48 49 extern "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 dso_local 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 79 extern "C" void nested_finally() { 80 __try { 81 might_throw(); 82 } __finally { 83 __try { 84 might_throw(); 85 } __finally { 86 } 87 } 88 } 89 90 // CHECK-LABEL: define dso_local void @nested_finally() #{{[0-9]+}} 91 // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 92 // CHECK: invoke void @might_throw() 93 // CHECK: call void @"?fin$0@0@nested_finally@@"(i8 noundef 1, i8* {{.*}}) 94 95 // CHECK-LABEL: define internal void @"?fin$0@0@nested_finally@@" 96 // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 97 // CHECK: invoke void @might_throw() 98 // CHECK: call void @"?fin$1@0@nested_finally@@"(i8 noundef 1, i8* {{.*}}) 99 100 void use_seh_in_lambda() { 101 ([]() { 102 __try { 103 might_throw(); 104 } __except(1) { 105 } 106 })(); 107 HasCleanup x; 108 might_throw(); 109 } 110 111 // CXXEH-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"() 112 // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 113 // CXXEH: cleanuppad 114 115 // NOCXX-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"() 116 // NOCXX-NOT: invoke 117 // NOCXX: ret void 118 119 // CHECK-LABEL: define internal void @"??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* {{[^,]*}} %this) 120 // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 121 // CHECK: invoke void @might_throw() #[[NOINLINE]] 122 // CHECK: catchpad 123 124 static int my_unique_global; 125 126 extern "C" inline void use_seh_in_inline_func() { 127 __try { 128 might_throw(); 129 } __except(_exception_code() == 424242) { 130 } 131 __try { 132 might_throw(); 133 } __finally { 134 my_unique_global = 1234; 135 } 136 } 137 138 void use_inline() { 139 use_seh_in_inline_func(); 140 } 141 142 // CHECK-LABEL: define linkonce_odr dso_local void @use_seh_in_inline_func() #{{[0-9]+}} 143 // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 144 // CHECK: invoke void @might_throw() 145 // 146 // CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"?filt$0@0@use_seh_in_inline_func@@" to i8*)] 147 // 148 // CHECK: invoke void @might_throw() 149 // 150 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 151 // CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 noundef 0, i8* noundef %[[fp]]) 152 // CHECK: ret void 153 // 154 // CHECK: cleanuppad 155 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 156 // CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 noundef 1, i8* noundef %[[fp]]) 157 158 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@use_seh_in_inline_func@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer) #{{[0-9]+}} 159 // CHECK: icmp eq i32 %{{.*}}, 424242 160 // CHECK: zext i1 %{{.*}} to i32 161 // CHECK: ret i32 162 163 // CHECK-LABEL: define internal void @"?fin$0@0@use_seh_in_inline_func@@"(i8 noundef %abnormal_termination, i8* noundef %frame_pointer) #{{[0-9]+}} 164 // CHECK: store i32 1234, i32* @my_unique_global 165 166 // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } 167 168 void seh_in_noexcept() noexcept { __try {} __finally {} } 169