[SEH] Use the SEH personality on frontend-outlined funclets
authorReid Kleckner <rnk@google.com>
Fri, 13 Oct 2017 16:55:14 +0000 (16:55 +0000)
committerReid Kleckner <rnk@google.com>
Fri, 13 Oct 2017 16:55:14 +0000 (16:55 +0000)
This allows __try inside __finally to work.

Fixes PR34939

llvm-svn: 315707

clang/lib/CodeGen/CGException.cpp
clang/test/CodeGenCXX/exceptions-seh.cpp

index 709ed002643a60dacb4bb73bb9242adeca860cea..1bff6490b8ca8118f9ae386308540fc54e36b211 100644 (file)
@@ -225,7 +225,12 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
 }
 
 const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
-  return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(CGF.CurCodeDecl));
+  const auto *FD = CGF.CurCodeDecl;
+  // For outlined finallys and filters, use the SEH personality in case they
+  // contain more SEH. This mostly only affects finallys. Filters could
+  // hypothetically use gnu statement expressions to sneak in nested SEH.
+  FD = FD ? FD : CGF.CurSEHParent;
+  return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(FD));
 }
 
 static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
index 4f7eacd6672087c90fc95a25f68458e2db01e17e..fa2d834c1e38e9695ba8e2534ced7a28c46f4939 100644 (file)
@@ -76,6 +76,27 @@ extern "C" void use_seh() {
 // CHECK: [[cont]]
 // CHECK: br label %[[ret]]
 
+extern "C" void nested_finally() {
+  __try {
+    might_throw();
+  } __finally {
+    __try {
+      might_throw();
+    } __finally {
+    }
+  }
+}
+
+// CHECK-LABEL: define void @nested_finally() #{{[0-9]+}}
+// CHECK-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK: invoke void @might_throw()
+// CHECK: call void @"\01?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}})
+
+// CHECK-LABEL: define internal void @"\01?fin$0@0@nested_finally@@"
+// CHECK-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK: invoke void @might_throw()
+// CHECK: call void @"\01?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}})
+
 void use_seh_in_lambda() {
   ([]() {
     __try {