[WinEH] Mark calls inside cleanups as noinline
This works around PR25162. The MSVC tables make it very difficult to
correctly inline a C++ destructor that contains try / catch. We've
attempted to address PR25162 in LLVM's backend, but it feels pretty
infeasible. MSVC and ICC both appear to avoid inlining such complex
destructors.
Long term, we want to fix this by making the inliner smart enough to
know when it is inlining into a cleanup, so it can inline simple
destructors (~unique_ptr and ~vector) while avoiding destructors
containing try / catch.
llvm-svn: 251576
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 5217e24..f1f6a8b 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -19,6 +19,7 @@
#include "CGCleanup.h"
#include "CodeGenFunction.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -902,19 +903,19 @@
EmitBlock(EHEntry);
- // Push terminate scopes around the potentially throwing destructor calls.
- // We don't emit these when using funclets, because the runtime does it for
- // us as part of unwinding out of a cleanuppad.
+ llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent);
+
+ // Push a terminate scope or cleanupendpad scope around the potentially
+ // throwing cleanups. For funclet EH personalities, the cleanupendpad models
+ // program termination when cleanups throw.
bool PushedTerminate = false;
+ SaveAndRestore<bool> RestoreIsCleanupPadScope(IsCleanupPadScope);
+ llvm::CleanupPadInst *CPI = nullptr;
+ llvm::BasicBlock *CleanupEndBB = nullptr;
if (!EHPersonality::get(*this).usesFuncletPads()) {
EHStack.pushTerminate();
PushedTerminate = true;
- }
-
- llvm::CleanupPadInst *CPI = nullptr;
- llvm::BasicBlock *CleanupEndBB = nullptr;
- llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent);
- if (EHPersonality::get(*this).usesFuncletPads()) {
+ } else {
CPI = Builder.CreateCleanupPad({});
// Build a cleanupendpad to unwind through. Our insertion point should be
@@ -922,6 +923,10 @@
CleanupEndBB = createBasicBlock("ehcleanup.end");
CGBuilderTy(*this, CleanupEndBB).CreateCleanupEndPad(CPI, NextAction);
EHStack.pushPadEnd(CleanupEndBB);
+
+ // Mark that we're inside a cleanuppad to block inlining.
+ // FIXME: Remove this once the inliner knows when it's safe to do so.
+ IsCleanupPadScope = true;
}
// We only actually emit the cleanup code if the cleanup is either