summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/exceptions-seh.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-02-03 22:52:35 +0000
committerReid Kleckner <reid@kleckner.net>2015-02-03 22:52:35 +0000
commit41c5887917db2aba647714cfad1e675d6d93cd1e (patch)
tree0f9f73a1a7354c6b77b19d397c37c6d75d0443b5 /test/CodeGenCXX/exceptions-seh.cpp
parent1f6936185b95a45fedeff6267457b68aeeea1578 (diff)
SEH: Track users of __try so we can pick a per-func EH personality
There are four major kinds of declarations that cause code generation: - FunctionDecl (includes CXXMethodDecl etc) - ObjCMethodDecl - BlockDecl - CapturedDecl This patch tracks __try usage on FunctionDecls and diagnoses __try usage in other decls. If someone wants to use __try from ObjC, they can use it from a free function, since the ObjC code will need an ObjC-style EH personality. Eventually we will want to look through CapturedDecls and track SEH usage on the parent FunctionDecl, if present. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@228058 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/exceptions-seh.cpp')
-rw-r--r--test/CodeGenCXX/exceptions-seh.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp
new file mode 100644
index 0000000000..74b43a94f6
--- /dev/null
+++ b/test/CodeGenCXX/exceptions-seh.cpp
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm -o - -fcxx-exceptions -fexceptions -mconstructor-aliases | FileCheck %s
+
+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.
+
+// CHECK-LABEL: define void @use_cxx()
+// CHECK: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CHECK: invoke void @might_throw()
+// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+//
+// CHECK: [[cont]]
+// CHECK: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CHECK: ret void
+//
+// CHECK: [[lpad]]
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-NEXT: cleanup
+// CHECK: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CHECK: br label %[[resume:[^ ]*]]
+//
+// CHECK: [[resume]]
+// CHECK: resume
+
+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()
+// 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();
+}
+
+// CHECK-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+
+// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this)
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)