From: Reid Kleckner Date: Wed, 8 Apr 2015 22:48:50 +0000 (+0000) Subject: [WinEH] Don't wrap cleanups in terminate actions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dbad6778509e98d21c6107067282baa078c37a6e;p=clang [WinEH] Don't wrap cleanups in terminate actions _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 --- diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index de716cf66d..299969a464 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -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, diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 642d8e23fa..68f1430ace 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -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"({{.*}}) +}