aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/exceptions-seh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/exceptions-seh.cpp')
-rw-r--r--test/CodeGenCXX/exceptions-seh.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp
new file mode 100644
index 000000000000..3e77f12fb5dc
--- /dev/null
+++ b/test/CodeGenCXX/exceptions-seh.cpp
@@ -0,0 +1,142 @@
+// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
+// RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH
+// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
+// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
+
+extern "C" unsigned long _exception_code();
+extern "C" void might_throw();
+
+struct HasCleanup {
+ HasCleanup();
+ ~HasCleanup();
+ int padding;
+};
+
+extern "C" void use_cxx() {
+ HasCleanup x;
+ might_throw();
+}
+
+// Make sure we use __CxxFrameHandler3 for C++ EH.
+
+// CXXEH-LABEL: define void @use_cxx()
+// CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: invoke void @might_throw()
+// CXXEH: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+//
+// CXXEH: [[cont]]
+// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: ret void
+//
+// CXXEH: [[lpad]]
+// CXXEH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CXXEH-NEXT: cleanup
+// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: br label %[[resume:[^ ]*]]
+//
+// CXXEH: [[resume]]
+// CXXEH: resume
+
+// NOCXX-LABEL: define void @use_cxx()
+// NOCXX-NOT: invoke
+// NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// NOCXX-NOT: invoke
+// NOCXX: call void @might_throw()
+// NOCXX-NOT: invoke
+// NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// NOCXX-NOT: invoke
+// NOCXX: ret void
+
+extern "C" void use_seh() {
+ __try {
+ might_throw();
+ } __except(1) {
+ }
+}
+
+// Make sure we use __C_specific_handler for SEH.
+
+// CHECK-LABEL: define void @use_seh()
+// CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]]
+// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+//
+// CHECK: [[cont]]
+// CHECK: br label %[[ret:[^ ]*]]
+//
+// CHECK: [[lpad]]
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK-NEXT: catch i8*
+//
+// CHECK: br label %[[ret]]
+//
+// CHECK: [[ret]]
+// CHECK: ret void
+
+void use_seh_in_lambda() {
+ ([]() {
+ __try {
+ might_throw();
+ } __except(1) {
+ }
+ })();
+ HasCleanup x;
+ might_throw();
+}
+
+// CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
+// CXXEH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+
+// NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
+// NOCXX-NOT: invoke
+// NOCXX: ret void
+
+// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this)
+// CHECK: invoke void @might_throw() #[[NOINLINE]]
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+static int my_unique_global;
+
+extern "C" inline void use_seh_in_inline_func() {
+ __try {
+ might_throw();
+ } __except(_exception_code() == 424242) {
+ }
+ __try {
+ might_throw();
+ } __finally {
+ my_unique_global = 1234;
+ }
+}
+
+void use_inline() {
+ use_seh_in_inline_func();
+}
+
+// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat {
+// CHECK: invoke void @might_throw()
+//
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)
+//
+// CHECK: invoke void @might_throw()
+//
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
+// CHECK: ret void
+//
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK-NEXT: cleanup
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
+
+// 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)
+// CHECK: icmp eq i32 %{{.*}}, 424242
+// CHECK: zext i1 %{{.*}} to i32
+// CHECK: ret i32
+
+// 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)
+// CHECK: store i32 1234, i32* @my_unique_global
+
+// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }