summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGCall.cpp31
-rw-r--r--clang/lib/CodeGen/CGCleanup.cpp37
-rw-r--r--clang/lib/CodeGen/CGCleanup.h8
-rw-r--r--clang/lib/CodeGen/CGException.cpp74
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h8
-rw-r--r--clang/lib/CodeGen/EHScopeStack.h4
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp4
-rw-r--r--clang/test/CodeGen/exceptions-seh-finally.c49
-rw-r--r--clang/test/CodeGen/exceptions-seh-leave.c28
-rw-r--r--clang/test/CodeGen/exceptions-seh.c61
-rw-r--r--clang/test/CodeGenCXX/exceptions-cxx-new.cpp38
-rw-r--r--clang/test/CodeGenCXX/exceptions-seh.cpp9
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp4
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp48
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp18
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp4
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp4
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-try-throw.cpp4
18 files changed, 168 insertions, 265 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 80f88fb8d15..891f9071bdc 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -15,6 +15,7 @@
#include "CGCall.h"
#include "ABIInfo.h"
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
@@ -3472,11 +3473,21 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
AttributeList);
- llvm::BasicBlock *InvokeDest = nullptr;
- if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind) ||
- currentFunctionUsesSEHTry())
- InvokeDest = getInvokeDest();
+ bool CannotThrow;
+ if (currentFunctionUsesSEHTry()) {
+ // SEH cares about asynchronous exceptions, everything can "throw."
+ CannotThrow = false;
+ } else if (isCleanupPadScope() &&
+ EHPersonality::get(*this).isMSVCXXPersonality()) {
+ // The MSVC++ personality will implicitly terminate the program if an
+ // exception is thrown. An unwind edge cannot be reached.
+ CannotThrow = true;
+ } else {
+ // Otherwise, nowunind callsites will never throw.
+ CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+ }
+ llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
llvm::CallSite CS;
if (!InvokeDest) {
@@ -3495,14 +3506,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::AlwaysInline);
- // Disable inlining inside SEH __try blocks and cleanup funclets. None of the
- // funclet EH personalities that clang supports have tables that are
- // expressive enough to describe catching an exception inside a cleanup.
- // __CxxFrameHandler3, for example, will terminate the program without
- // catching it.
- // FIXME: Move this decision to the LLVM inliner. Before we can do that, the
- // inliner needs to know if a given call site is part of a cleanuppad.
- if (isSEHTryScope() || isCleanupPadScope())
+ // Disable inlining inside SEH __try blocks.
+ if (isSEHTryScope())
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoInline);
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 5b6e497673c..245d6a7e4b0 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -246,13 +246,6 @@ void EHScopeStack::pushTerminate() {
InnermostEHScope = stable_begin();
}
-void EHScopeStack::pushPadEnd(llvm::BasicBlock *PadEndBB) {
- char *Buffer = allocate(EHPadEndScope::getSize());
- auto *CES = new (Buffer) EHPadEndScope(InnermostEHScope);
- CES->setCachedEHDispatchBlock(PadEndBB);
- InnermostEHScope = stable_begin();
-}
-
/// Remove any 'null' fixups on the stack. However, we can't pop more
/// fixups than the fixup depth on the innermost normal cleanup, or
/// else fixups that we try to add to that cleanup will end up in the
@@ -909,24 +902,17 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// throwing cleanups. For funclet EH personalities, the cleanupendpad models
// program termination when cleanups throw.
bool PushedTerminate = false;
- SaveAndRestore<bool> RestoreIsCleanupPadScope(IsCleanupPadScope);
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
llvm::CleanupPadInst *CPI = nullptr;
- llvm::BasicBlock *CleanupEndBB = nullptr;
if (!EHPersonality::get(*this).usesFuncletPads()) {
EHStack.pushTerminate();
PushedTerminate = true;
} else {
- CPI = Builder.CreateCleanupPad({});
-
- // Build a cleanupendpad to unwind through. Our insertion point should be
- // in the cleanuppad block.
- 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;
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad);
}
// We only actually emit the cleanup code if the cleanup is either
@@ -941,17 +927,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
else
Builder.CreateBr(NextAction);
- // Insert the cleanupendpad block here, if it has any uses.
- if (CleanupEndBB) {
- EHStack.popPadEnd();
- if (CleanupEndBB->hasNUsesOrMore(1)) {
- CurFn->getBasicBlockList().insertAfter(
- Builder.GetInsertBlock()->getIterator(), CleanupEndBB);
- } else {
- delete CleanupEndBB;
- }
- }
-
// Leave the terminate scope.
if (PushedTerminate)
EHStack.popTerminate();
diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h
index 5a0145eb0b8..909f00b0592 100644
--- a/clang/lib/CodeGen/CGCleanup.h
+++ b/clang/lib/CodeGen/CGCleanup.h
@@ -587,14 +587,6 @@ inline void EHScopeStack::popTerminate() {
deallocate(EHTerminateScope::getSize());
}
-inline void EHScopeStack::popPadEnd() {
- assert(!empty() && "popping exception stack when not empty");
-
- EHPadEndScope &scope = cast<EHPadEndScope>(*begin());
- InnermostEHScope = scope.getEnclosingEHScope();
- deallocate(EHPadEndScope::getSize());
-}
-
inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
assert(sp.isValid() && "finding invalid savepoint");
assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index eaa76109be1..b5e1dcdc6c9 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -871,58 +871,50 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
return lpad;
}
-static llvm::BasicBlock *emitCatchPadBlock(CodeGenFunction &CGF,
- EHCatchScope &CatchScope) {
+static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) {
llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock();
assert(DispatchBlock);
CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
CGF.EmitBlockAfterUses(DispatchBlock);
- // Figure out the next block.
- llvm::BasicBlock *NextBlock = nullptr;
+ llvm::Value *ParentPad = CGF.CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
+ llvm::BasicBlock *UnwindBB =
+ CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope());
+
+ unsigned NumHandlers = CatchScope.getNumHandlers();
+ llvm::CatchSwitchInst *CatchSwitch =
+ CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers);
// Test against each of the exception types we claim to catch.
- for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) {
+ for (unsigned I = 0; I < NumHandlers; ++I) {
const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
CatchTypeInfo TypeInfo = Handler.Type;
if (!TypeInfo.RTTI)
TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy);
- // If this is the last handler, we're at the end, and the next
- // block is the block for the enclosing EH scope.
- if (I + 1 == E) {
- NextBlock = CGF.createBasicBlock("catchendblock");
- CGBuilderTy(CGF, NextBlock).CreateCatchEndPad(
- CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()));
- } else {
- NextBlock = CGF.createBasicBlock("catch.dispatch");
- }
+ CGF.Builder.SetInsertPoint(Handler.Block);
if (EHPersonality::get(CGF).isMSVCXXPersonality()) {
- CGF.Builder.CreateCatchPad(Handler.Block, NextBlock,
- {TypeInfo.RTTI,
- CGF.Builder.getInt32(TypeInfo.Flags),
- llvm::Constant::getNullValue(CGF.VoidPtrTy)});
+ CGF.Builder.CreateCatchPad(
+ CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags),
+ llvm::Constant::getNullValue(CGF.VoidPtrTy)});
} else {
- CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, {TypeInfo.RTTI});
+ CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI});
}
- // Otherwise we need to emit and continue at that block.
- CGF.EmitBlock(NextBlock);
+ CatchSwitch->addHandler(Handler.Block);
}
CGF.Builder.restoreIP(SavedIP);
-
- return NextBlock;
}
/// Emit the structure of the dispatch block for the given catch scope.
/// It is an invariant that the dispatch block already exists.
-/// If the catchblock instructions are used for EH dispatch, then the basic
-/// block holding the final catchendblock instruction is returned.
-static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
- EHCatchScope &catchScope) {
+static void emitCatchDispatchBlock(CodeGenFunction &CGF,
+ EHCatchScope &catchScope) {
if (EHPersonality::get(CGF).usesFuncletPads())
return emitCatchPadBlock(CGF, catchScope);
@@ -934,7 +926,7 @@ static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
if (catchScope.getNumHandlers() == 1 &&
catchScope.getHandler(0).isCatchAll()) {
assert(dispatchBlock == catchScope.getHandler(0).Block);
- return nullptr;
+ return;
}
CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();
@@ -992,12 +984,11 @@ static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
// If the next handler is a catch-all, we're completely done.
if (nextIsEnd) {
CGF.Builder.restoreIP(savedIP);
- return nullptr;
+ return;
}
// Otherwise we need to emit and continue at that block.
CGF.EmitBlock(nextBlock);
}
- return nullptr;
}
void CodeGenFunction::popCatchScope() {
@@ -1020,7 +1011,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
}
// Emit the structure of the EH dispatch for this catch.
- llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope);
+ emitCatchDispatchBlock(*this, CatchScope);
// Copy the handler blocks off before we pop the EH stack. Emitting
// the handlers might scribble on this memory.
@@ -1043,9 +1034,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
isa<CXXConstructorDecl>(CurCodeDecl);
- if (CatchEndBlockBB)
- EHStack.pushPadEnd(CatchEndBlockBB);
-
// Perversely, we emit the handlers backwards precisely because we
// want them to appear in source order. In all of these cases, the
// catch block will have exactly one predecessor, which will be a
@@ -1065,6 +1053,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
RunCleanupsScope CatchScope(*this);
// Initialize the catch variable and set up the cleanups.
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
CGM.getCXXABI().emitBeginCatch(*this, C);
// Emit the PGO counter increment.
@@ -1098,8 +1088,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
EmitBlock(ContBB);
incrementProfileCounter(&S);
- if (CatchEndBlockBB)
- EHStack.popPadEnd();
}
namespace {
@@ -1338,7 +1326,11 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
TerminateHandler = createBasicBlock("terminate.handler");
Builder.SetInsertPoint(TerminateHandler);
if (EHPersonality::get(*this).usesFuncletPads()) {
- Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn());
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ Builder.CreateTerminatePad(ParentPad, /*UnwindBB=*/nullptr,
+ {CGM.getTerminateFn()});
} else {
llvm::Value *Exn = nullptr;
if (getLangOpts().CPlusPlus)
@@ -1857,18 +1849,16 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
emitCatchDispatchBlock(*this, CatchScope);
// Grab the block before we pop the handler.
- llvm::BasicBlock *ExceptBB = CatchScope.getHandler(0).Block;
+ llvm::BasicBlock *CatchPadBB = CatchScope.getHandler(0).Block;
EHStack.popCatch();
- EmitBlockAfterUses(ExceptBB);
+ EmitBlockAfterUses(CatchPadBB);
// __except blocks don't get outlined into funclets, so immediately do a
// catchret.
- llvm::BasicBlock *CatchPadBB = ExceptBB->getSinglePredecessor();
- assert(CatchPadBB && "only ExceptBB pred should be catchpad");
llvm::CatchPadInst *CPI =
cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
- ExceptBB = createBasicBlock("__except");
+ llvm::BasicBlock *ExceptBB = createBasicBlock("__except");
Builder.CreateCatchRet(CPI, ExceptBB);
EmitBlock(ExceptBB);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 714a641ba39..0302b0e6edd 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -279,8 +279,6 @@ public:
/// finally block or filter expression.
bool IsOutlinedSEHHelper;
- bool IsCleanupPadScope = false;
-
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
@@ -295,6 +293,8 @@ public:
llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack;
llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack;
+ llvm::Instruction *CurrentFuncletPad = nullptr;
+
/// Header for data within LifetimeExtendedCleanupStack.
struct LifetimeExtendedCleanupHeader {
/// The size of the following cleanup object.
@@ -375,7 +375,9 @@ public:
bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
/// Returns true while emitting a cleanuppad.
- bool isCleanupPadScope() const { return IsCleanupPadScope; }
+ bool isCleanupPadScope() const {
+ return CurrentFuncletPad && isa<llvm::CleanupPadInst>(CurrentFuncletPad);
+ }
/// pushFullExprCleanup - Push a cleanup to be run at the end of the
/// current full-expression. Safe against the possibility that
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index 9840afe6bc5..85cd1543e5b 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -334,10 +334,6 @@ public:
/// Pops a terminate handler off the stack.
void popTerminate();
- void pushPadEnd(llvm::BasicBlock *PadEndBB);
-
- void popPadEnd();
-
// Returns true iff the current scope is either empty or contains only
// lifetime markers, i.e. no real cleanup code
bool containsOnlyLifetimeMarkers(stable_iterator Old) const;
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 711b08e6a29..f22c5b8b60d 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -893,10 +893,10 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
// In the MS ABI, the runtime handles the copy, and the catch handler is
// responsible for destruction.
VarDecl *CatchParam = S->getExceptionDecl();
- llvm::BasicBlock *CatchPadBB =
- CGF.Builder.GetInsertBlock()->getSinglePredecessor();
+ llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock();
llvm::CatchPadInst *CPI =
cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
+ CGF.CurrentFuncletPad = CPI;
// If this is a catch-all or the catch parameter is unnamed, we don't need to
// emit an alloca to the object.
diff --git a/clang/test/CodeGen/exceptions-seh-finally.c b/clang/test/CodeGen/exceptions-seh-finally.c
index 03c04e6fe0e..f0ed2230640 100644
--- a/clang/test/CodeGen/exceptions-seh-finally.c
+++ b/clang/test/CodeGen/exceptions-seh-finally.c
@@ -25,12 +25,8 @@ void basic_finally(void) {
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
// CHECK: call void @cleanup()
@@ -95,12 +91,8 @@ void use_abnormal_termination(void) {
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
@@ -141,12 +133,8 @@ void noreturn_finally() {
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK: call void @abort()
@@ -189,12 +177,8 @@ int nested___finally___finally() {
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK: ret void
@@ -231,24 +215,15 @@ int nested___finally___finally_with_eh_edge() {
// CHECK: [[lpad1]]
// CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
-// CHECK-NEXT: to label %[[innercleanupretbb:[^ ]*]] unwind label %[[innerend:[^ ]*]]
+// CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
//
// CHECK: [[innercleanupretbb]]
-// CHECK-NEXT: cleanupret %[[innerpad]] unwind label %[[lpad2]]
-//
-// CHECK: [[innerend]]
-// CHECK-NEXT: cleanupendpad %[[innerpad]] unwind label %[[lpad2:[^ ]*]]
+// CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
//
// CHECK: [[lpad2]]
// CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
-// CHECK-NEXT: to label %[[outercleanupretbb:[^ ]*]] unwind label %[[outerend:[^ ]*]]
-//
-// CHECK: [[outercleanupretbb]]
-// CHECK-NEXT: cleanupret %[[outerpad]] unwind to caller
-//
-// CHECK: [[outerend]]
-// CHECK-NEXT: cleanupendpad %[[outerpad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK: ret void
diff --git a/clang/test/CodeGen/exceptions-seh-leave.c b/clang/test/CodeGen/exceptions-seh-leave.c
index 2895edbdfef..a0b1956d142 100644
--- a/clang/test/CodeGen/exceptions-seh-leave.c
+++ b/clang/test/CodeGen/exceptions-seh-leave.c
@@ -160,20 +160,17 @@ int nested___except___finally() {
// CHECK-NEXT: cleanuppad
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
-// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[cleanupend:[^ ]*]]
+// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]]
// CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]]
// CHECK: [[g2_lpad]]
-// CHECK: catchpad [i8* null]
+// CHECK: catchpad {{.*}} [i8* null]
// CHECK: catchret
// CHECK: br label %[[trycont]]
// CHECK: [[trycont]]
// CHECK-NEXT: ret i32 1
-// CHECK: [[cleanupend]]
-// CHECK-NEXT: cleanupendpad {{.*}} unwind label %[[g2_lpad]]
-
// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: call void @g()
// CHECK: unreachable
@@ -203,14 +200,14 @@ int nested___except___except() {
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
// CHECK: [[g1_lpad]]
-// CHECK: catchpad [i8* null]
+// CHECK: catchpad {{.*}} [i8* null]
// CHECK: catchret {{.*}} to label %[[except:[^ ]*]]
// CHECK: [[except]]
// CHECK: invoke void @g()
// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[g2_lpad]]
-// CHECK: catchpad [i8* null]
+// CHECK: catchpad {{.*}} [i8* null]
// CHECK: catchret
// CHECK: br label %[[trycont4:[^ ]*]]
@@ -280,7 +277,7 @@ int nested___finally___except() {
// CHECK: [[g2_lpad]]
// CHECK: cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
// CHECK: cleanupret {{.*}} unwind to caller
// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
@@ -323,21 +320,18 @@ int nested___finally___finally() {
// CHECK-NEXT: ret i32 1
// CHECK: [[g1_lpad]]
-// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad []
+// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
-// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[endcleanup:[^ ]*]]
+// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]]
// CHECK: [[finally_cont2]]
-// CHECK: cleanupret %[[padtoken]] unwind label %[[g2_lpad]]
-
-// CHECK: [[endcleanup]]
-// CHECK-NEXT: cleanupendpad %[[padtoken]] unwind label %[[g2_lpad]]
+// CHECK: cleanupret from %[[padtoken]] unwind label %[[g2_lpad]]
// CHECK: [[g2_lpad]]
-// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad []
+// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
-// CHECK: cleanupret %[[padtoken]] unwind to caller
+// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
+// CHECK: cleanupret from %[[padtoken]] unwind to caller
// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: ret void
diff --git a/clang/test/CodeGen/exceptions-seh.c b/clang/test/CodeGen/exceptions-seh.c
index 1a50ed0deae..0829117fbe3 100644
--- a/clang/test/CodeGen/exceptions-seh.c
+++ b/clang/test/CodeGen/exceptions-seh.c
@@ -34,12 +34,9 @@ int safe_div(int numerator, int denominator, int *res) {
// CHECK: to label %{{.*}} unwind label %[[catchpad:[^ ]*]]
//
// CHECK: [[catchpad]]
-// X64: %[[padtoken:[^ ]*]] = catchpad [i8* null]
-// X86: %[[padtoken:[^ ]*]] = catchpad [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)]
-// CHECK-NEXT: to label %[[exceptret:[^ ]*]] unwind label
-//
-// CHECK: [[exceptret]]
-// CHECK: catchret %[[padtoken]] to label %[[except:[^ ]*]]
+// X64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null]
+// X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)]
+// CHECK-NEXT: catchret from %[[padtoken]] to label %[[except:[^ ]*]]
//
// CHECK: [[except]]
// CHECK: store i32 -42, i32* %[[success:[^ ]*]]
@@ -85,7 +82,7 @@ int filter_expr_capture(void) {
// CHECK: store i32 42, i32* %[[r]]
// CHECK: invoke void @j() #[[NOINLINE]]
//
-// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)]
+// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)]
// CHECK: store i32 13, i32* %[[r]]
//
// CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]]
@@ -121,37 +118,37 @@ int nested_try(void) {
// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
// CHECK: store i32 42, i32* %[[r:[^ ,]*]]
// CHECK: invoke void @j() #[[NOINLINE]]
-// CHECK: to label %[[cont:[^ ]*]] unwind label %[[cpad_inner:[^ ]*]]
-//
-// CHECK: [[cpad_inner]]
-// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)]
-// CHECK-NEXT: to label %[[exceptret_inner:[^ ]*]] unwind label %[[cpad_outer:[^ ]*]]
+// CHECK: to label %[[cont:[^ ]*]] unwind label %[[cswitch_inner:[^ ]*]]
//
-// CHECK: [[exceptret_inner]]
-// CHECK: catchret {{.*}} to label %[[except_inner:[^ ]*]]
+// CHECK: [[cswitch_inner]]
+// CHECK: %[[cs_inner:[^ ]*]] = catchswitch within none [label %[[cpad_inner:[^ ]*]]] unwind label %[[cswitch_outer:[^ ]*]]
//
-// CHECK: [[except_inner]]
-// CHECK: store i32 123, i32* %[[r]]
-// CHECK: br label %[[inner_try_cont:[^ ]*]]
-//
-// CHECK: [[inner_try_cont]]
-// CHECK: br label %[[outer_try_cont:[^ ]*]]
+// CHECK: [[cswitch_outer]]
+// CHECK: %[[cs_outer:[^ ]*]] = catchswitch within none [label %[[cpad_outer:[^ ]*]]] unwind to caller
//
// CHECK: [[cpad_outer]]
-// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)]
-// CHECK-NEXT: to label %[[exceptret_outer:[^ ]*]] unwind label
-//
-// CHECK: [[exceptret_outer]]
-// CHECK: catchret {{.*}} to label %[[except_outer:[^ ]*]]
+// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)]
+// CHECK-NEXT: catchret {{.*}} to label %[[except_outer:[^ ]*]]
//
// CHECK: [[except_outer]]
// CHECK: store i32 456, i32* %[[r]]
-// CHECK: br label %[[outer_try_cont]]
+// CHECK: br label %[[outer_try_cont:[^ ]*]]
//
// CHECK: [[outer_try_cont]]
// CHECK: %[[r_load:[^ ]*]] = load i32, i32* %[[r]]
// CHECK: ret i32 %[[r_load]]
//
+// CHECK: [[cpad_inner]]
+// CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)]
+// CHECK-NEXT: catchret {{.*}} to label %[[except_inner:[^ ]*]]
+//
+// CHECK: [[except_inner]]
+// CHECK: store i32 123, i32* %[[r]]
+// CHECK: br label %[[inner_try_cont:[^ ]*]]
+//
+// CHECK: [[inner_try_cont]]
+// CHECK: br label %[[outer_try_cont]]
+//
// CHECK: [[cont]]
// CHECK: store i32 0, i32* %[[r]]
// CHECK: br label %[[inner_try_cont]]
@@ -193,14 +190,10 @@ int basic_finally(int g) {
// CHECK: ret i32
//
// CHECK: [[cleanuppad]]
-// CHECK: %[[padtoken:[^ ]*]] = cleanuppad []
+// CHECK: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
-// CHECK: to label %[[cleanupcont:[^ ]*]] unwind label %[[cleanupend:[^ ]*]]
-// CHECK: [[cleanupcont]]
-// CHECK: cleanupret %[[padtoken]] unwind to caller
-// CHECK: [[cleanupend]]
-// CHECK: cleanupendpad %[[padtoken]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: cleanupret from %[[padtoken]] unwind to caller
// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
// CHECK: call i8* @llvm.localrecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0)
@@ -278,7 +271,7 @@ int exception_code_in_except(void) {
// CHECK: %[[code_slot:[^ ]*]] = alloca i32
// CHECK: invoke void @try_body(i32 0, i32 0, i32* null)
// CHECK: %[[pad:[^ ]*]] = catchpad
-// CHECK: catchret %[[pad]]
+// CHECK: catchret from %[[pad]]
// X64: %[[code:[^ ]*]] = call i32 @llvm.eh.exceptioncode(token %[[pad]])
// X64: store i32 %[[code]], i32* %[[code_slot]]
// CHECK: %[[ret1:[^ ]*]] = load i32, i32* %[[code_slot]]
diff --git a/clang/test/CodeGenCXX/exceptions-cxx-new.cpp b/clang/test/CodeGenCXX/exceptions-cxx-new.cpp
index 182bda1f545..42b26c9dc8f 100644
--- a/clang/test/CodeGenCXX/exceptions-cxx-new.cpp
+++ b/clang/test/CodeGenCXX/exceptions-cxx-new.cpp
@@ -14,18 +14,15 @@ void test_catch() {
// CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"(
// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1)
-// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCH_INT:.*]]
+// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCHSWITCH:.*]]
-// CHECK: [[CATCH_INT]]
-// CHECK: %[[CATCHPAD_INT:.*]] = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// CHECK: to label %[[CATCH_INT_HANDLER:.*]] unwind label %[[CATCH_DOUBLE:.*]]
-
-// CHECK: [[CATCH_INT_HANDLER]]
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 2)
-// CHECK: to label %[[CATCH_INT_DONE:.*]] unwind label %[[CATCHENDPAD:.*]]
+// CHECK: [[CATCHSWITCH]]
+// CHECK: %[[CATCHSWITCHPAD:.*]] = catchswitch within none [label %[[CATCH_INT:.*]], label %[[CATCH_DOUBLE:.*]]] unwind to caller
-// CHECK: [[CATCH_INT_DONE]]
-// CHECK: catchret %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]
+// CHECK: [[CATCH_INT]]
+// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 2)
+// CHECK: catchret from %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]
// CHECK: [[LEAVE_INT_CATCH]]
// CHECK: br label %[[LEAVE_FUNC:.*]]
@@ -34,22 +31,13 @@ void test_catch() {
// CHECK: ret void
// CHECK: [[CATCH_DOUBLE]]
-// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null]
-// CHECK: to label %[[CATCH_DOUBLE_HANDLER:.*]] unwind label %[[CATCHENDPAD]]
-
-// CHECK: [[CATCH_DOUBLE_HANDLER]]
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 3)
-// CHECK: to label %[[CATCH_DOUBLE_DONE:.*]] unwind label %[[CATCHENDPAD]]
-
-// CHECK: [[CATCH_DOUBLE_DONE]]
-// CHECK: catchret %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]
+// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null]
+// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 3)
+// CHECK: catchret from %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]
// CHECK: [[LEAVE_DOUBLE_CATCH]]
// CHECK: br label %[[LEAVE_FUNC]]
-// CHECK: [[CATCHENDPAD]]
-// CHECK: catchendpad unwind to caller
-
// CHECK: [[NORMAL]]
// CHECK: br label %[[LEAVE_FUNC]]
@@ -71,9 +59,9 @@ void test_cleanup() {
// CHECK: ret void
// CHECK: [[CLEANUP]]
-// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad []
+// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
-// CHECK: cleanupret %[[CLEANUPPAD]] unwind to caller
+// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller
// CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"(
@@ -84,5 +72,5 @@ void test_cleanup() {
// CHECK: ret void
// CHECK: [[TERMINATE]]
-// CHECK: terminatepad [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
+// CHECK: terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
diff --git a/clang/test/CodeGenCXX/exceptions-seh.cpp b/clang/test/CodeGenCXX/exceptions-seh.cpp
index c6120b8172f..abbe95be340 100644
--- a/clang/test/CodeGenCXX/exceptions-seh.cpp
+++ b/clang/test/CodeGenCXX/exceptions-seh.cpp
@@ -61,7 +61,10 @@ extern "C" void use_seh() {
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[lpad]]
-// CHECK-NEXT: catchpad
+// CHECK-NEXT: %[[switch:.*]] = catchswitch within none [label %[[cpad:.*]]] unwind to caller
+//
+// CHECK: [[cpad]]
+// CHECK-NEXT: catchpad within %[[switch]]
// CHECK: catchret {{.*}} label %[[except:[^ ]*]]
//
// CHECK: [[except]]
@@ -119,7 +122,7 @@ void use_inline() {
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
//
-// CHECK: catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
+// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
//
// CHECK: invoke void @might_throw()
//
@@ -129,7 +132,7 @@ void use_inline() {
//
// CHECK: cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
// CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
// CHECK: icmp eq i32 %{{.*}}, 424242
diff --git a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
index e13ed5a8b64..68c141f1620 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -52,7 +52,7 @@ void call_foo() {
// X86: ret void
//
// lpad2:
-// X86: cleanuppad []
+// X86: cleanuppad within none []
// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]])
// X86: cleanupret
//
@@ -68,7 +68,7 @@ void call_foo() {
// X64: ret void
//
// lpad2:
-// X64: cleanuppad []
+// X64: cleanuppad within none []
// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
// X64: cleanupret
//
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
index e742f8b1c4a..69ec3475481 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
@@ -19,15 +19,15 @@ extern "C" void catch_all() {
// WIN64-LABEL: define void @catch_all()
// WIN64: invoke void @might_throw()
-// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[catchswitch_lpad:[^ ]*]]
//
-// WIN64: [[lpad]]
-// WIN64: catchpad [i8* null, i32 64, i8* null]
-// WIN64: to label %[[catchit:[^ ]*]] unwind label %{{.*}}
+// WIN64: [[catchswitch_lpad]]
+// WIN64: %[[catchswitch:[^ ]*]] = catchswitch within none [label %[[catchpad_lpad:[^ ]*]]] unwind to caller
//
-// WIN64: [[catchit]]
+// WIN64: [[catchpad_lpad]]
+// WIN64: catchpad within %[[catchswitch]] [i8* null, i32 64, i8* null]
// WIN64: call void @recover()
-// WIN64: catchret %{{.*}} to label %[[catchret:[^ ]*]]
+// WIN64: catchret from %{{.*}} to label %[[catchret:[^ ]*]]
//
// WIN64: [[catchret]]
// WIN64-NEXT: br label %[[ret:[^ ]*]]
@@ -47,7 +47,7 @@ extern "C" void catch_int() {
}
// WIN64-LABEL: define void @catch_int()
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
//
// The catchpad instruction starts the lifetime of 'e'. Unfortunately, that
// leaves us with nowhere to put lifetime.start, so we don't emit lifetime
@@ -69,7 +69,7 @@ extern "C" void catch_int_unnamed() {
}
// WIN64-LABEL: define void @catch_int_unnamed()
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
// WIN64: catchret
struct A {
@@ -96,7 +96,7 @@ extern "C" void catch_a_byval() {
// WIN64-LABEL: define void @catch_a_byval()
// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
-// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
// WIN64: call void @handle_exception(i8* %[[e_i8]])
// WIN64: catchret
@@ -111,7 +111,7 @@ extern "C" void catch_a_ref() {
// WIN64-LABEL: define void @catch_a_ref()
// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
-// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
// WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
// WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
// WIN64: call void @handle_exception(i8* %[[eptr_i8]])
@@ -139,25 +139,22 @@ extern "C" void catch_nested() {
// WIN64-LABEL: define void @catch_nested()
// WIN64: invoke void @might_throw()
-// WIN64-NEXT: to label %{{.*}} unwind label %[[lp1:[^ ]*]]
+// WIN64-NEXT: to label %{{.*}} unwind label %[[catchswitch_outer:[^ ]*]]
//
-// WIN64: [[lp1]]
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// WIN64: to label %[[catchit:[^ ]*]] unwind label %{{.*}}
+// WIN64: [[catchswitch_outer]]
+// WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch within none [label %[[catch_int_outer:[^ ]*]]] unwind to caller
//
-// WIN64: [[catchit]]
+// WIN64: [[catch_int_outer]]
+// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
// WIN64: invoke void @might_throw()
-// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[lp2:[^ ]*]]
+// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]]
//
-// WIN64: [[lp2]]
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// WIN64: to label %[[catchit2:[^ ]*]] unwind label %[[endcatch2:[^ ]*]]
+// WIN64: [[catchswitch_inner]]
+// WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch within %[[catchpad]] [label %[[catch_int_inner:[^ ]*]]] unwind to caller
//
-// WIN64: [[catchit2]]
-// WIN64-NEXT: invoke void @might_throw()
-// WIN64-NEXT: to label %[[catchret1:[^ ]*]] unwind label %[[endcatch2]]
-//
-// WIN64: [[catchret1]]
+// WIN64: [[catch_int_inner]]
+// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64-NEXT: call void @might_throw()
// WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]]
//
// WIN64: [[catchret2]]
@@ -165,6 +162,3 @@ extern "C" void catch_nested() {
//
// WIN64: [[mainret]]
// WIN64: ret void
-//
-// WIN64: [[endcatch2]]
-// WIN64: catchendpad unwind label %{{.*}}
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index c4a0d1ce649..bf05c693ec0 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -27,7 +27,7 @@ void HasEHCleanup() {
//
// There should be one dtor call for unwinding from the second getA.
// WIN32: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline:[0-9]+]]
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
// WIN32-NOT: @"\01??1A@@QAE@XZ"
// WIN32: }
@@ -62,7 +62,7 @@ int HasDeactivatedCleanups() {
// Conditionally destroy arg1.
// WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]]
// WIN32: br i1 %[[cond]]
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) #[[noinline]]
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
// WIN32: }
// Test putting the cleanups inside a conditional.
@@ -85,7 +85,7 @@ int HasConditionalCleanup(bool cond) {
// WIN32: call i32 @"\01?CouldThrow@@YAHXZ"()
//
// Only one dtor in the invoke for arg1
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]]
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
// WIN32: }
@@ -126,7 +126,7 @@ int HasConditionalDeactivatedCleanups(bool cond) {
// Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
// WIN32: br i1 %[[isactive]]
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]]
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
// WIN32: }
namespace crash_on_partial_destroy {
@@ -164,7 +164,7 @@ C::C() { foo(); }
// WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// WIN32-NOT: load
// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
-// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) #[[noinline]]
+// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
// WIN32: }
}
@@ -187,7 +187,7 @@ void f() {
//
// WIN32: [[lpad]]
// WIN32-NEXT: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) #[[noinline]]
+// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
}
namespace noexcept_false_dtor {
@@ -204,9 +204,5 @@ void f() {
// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanuppad
-// WIN32: invoke x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) #[[invoke_noinline:[0-9]+]]
+// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanupret
-// WIN32: cleanupendpad
-
-// WIN32: attributes #[[noinline]] = { noinline nounwind }
-// WIN32: attributes #[[invoke_noinline]] = { noinline }
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
index 6d462bf7b01..7eb9f08524e 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
@@ -9,6 +9,6 @@ void never_throws() noexcept(true) {
// CHECK-LABEL: define void @"\01?never_throws@@YAXXZ"()
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
-// MSVC2013: terminatepad [void ()* @"\01?terminate@@YAXXZ"]
-// MSVC2015: terminatepad [void ()* @__std_terminate]
+// MSVC2013: terminatepad within none [void ()* @"\01?terminate@@YAXXZ"]
+// MSVC2015: terminatepad within none [void ()* @__std_terminate]
// CHECK-NEXT: unreachable
diff --git a/clang/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/clang/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
index dadc656a15c..29b434eaf2c 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
@@ -39,7 +39,7 @@ extern inline S &f() {
// CHECK-NEXT: ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"
// CHECK: [[lpad:.*]]:
-// CHECK-NEXT: cleanuppad []
+// CHECK-NEXT: cleanuppad within none []
// CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], -2
// CHECK-NEXT: store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
@@ -75,7 +75,7 @@ extern inline S &g() {
// CHECK-NEXT: ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
//
// CHECK: [[lpad]]:
-// CHECK-NEXT: cleanuppad []
+// CHECK-NEXT: cleanuppad within none []
// CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT: cleanupret {{.*}} unwind to caller
return s;
diff --git a/clang/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/clang/test/CodeGenCXX/microsoft-abi-try-throw.cpp
index b87d9e1ad48..88e1802d200 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-try-throw.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-try-throw.cpp
@@ -19,7 +19,7 @@ int main() {
external(); // TRY: invoke void @"\01?external@@YAXXZ"
} catch (int) {
rv = 1;
- // TRY: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ // TRY: catchpad within %0 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
// TRY: catchret
}
#endif
@@ -39,7 +39,7 @@ void qual_catch() {
external();
} catch (const int *) {
}
- // TRY: catchpad [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null]
+ // TRY: catchpad within %0 [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null]
// TRY: catchret
}
#endif
OpenPOWER on IntegriCloud