]> granicus.if.org Git - clang/commitdiff
[WinEH] Don't wrap cleanups in terminate actions
authorReid Kleckner <reid@kleckner.net>
Wed, 8 Apr 2015 22:48:50 +0000 (22:48 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 8 Apr 2015 22:48:50 +0000 (22:48 +0000)
_CxxFrameHandler3 calls terminate if a cleanup action throws, regardless
of what bits you put in the xdata tables. There's no need to model this
in the IR, since we just have to take it out later.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@234448 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCleanup.cpp
test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp

index de716cf66db1bbc58b49b877a3f43aa609dedf4f..299969a464988c22ec27b7440c2c8c6501bd618c 100644 (file)
@@ -471,8 +471,14 @@ static void EmitCleanup(CodeGenFunction &CGF,
                         EHScopeStack::Cleanup *Fn,
                         EHScopeStack::Cleanup::Flags flags,
                         llvm::Value *ActiveFlag) {
-  // EH cleanups always occur within a terminate scope.
-  if (flags.isForEHCleanup()) CGF.EHStack.pushTerminate();
+  // Itanium EH cleanups occur within a terminate scope. Microsoft SEH doesn't
+  // have this behavior, and the Microsoft C++ runtime will call terminate for
+  // us if the cleanup throws.
+  bool PushedTerminate = false;
+  if (flags.isForEHCleanup() && !CGF.getTarget().getCXXABI().isMicrosoft()) {
+    CGF.EHStack.pushTerminate();
+    PushedTerminate = true;
+  }
 
   // If there's an active flag, load it and skip the cleanup if it's
   // false.
@@ -495,7 +501,8 @@ static void EmitCleanup(CodeGenFunction &CGF,
     CGF.EmitBlock(ContBB);
 
   // Leave the terminate scope.
-  if (flags.isForEHCleanup()) CGF.EHStack.popTerminate();
+  if (PushedTerminate)
+    CGF.EHStack.popTerminate();
 }
 
 static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
index 642d8e23fa95bf174054416ce721480ef98b1d42..68f1430ace5729425275553e1f7e89e324d88650 100644 (file)
@@ -165,6 +165,29 @@ C::C() { foo(); }
 // WIN32:      getelementptr inbounds i8, i8* %{{.*}}, i64 4
 // WIN32-NOT:  load
 // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
-// WIN32:      invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"
+// WIN32:      call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"
 // WIN32: }
 }
+
+namespace dont_call_terminate {
+struct C {
+  ~C();
+};
+void g();
+void f() {
+  C c;
+  g();
+}
+
+// WIN32-LABEL: define void @"\01?f@dont_call_terminate@@YAXXZ"()
+// WIN32: invoke void @"\01?g@dont_call_terminate@@YAXXZ"()
+// WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+//
+// WIN32: [[cont]]
+// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+//
+// WIN32: [[lpad]]
+// WIN32-NEXT: landingpad
+// WIN32-NEXT: cleanup
+// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+}