diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -4413,44 +4413,23 @@ } namespace { - /// A cleanup to call __cxa_end_catch. In many cases, the caught - /// exception type lets us state definitively that the thrown exception - /// type does not have a destructor. In particular: - /// - Catch-alls tell us nothing, so we have to conservatively - /// assume that the thrown exception might have a destructor. - /// - Catches by reference behave according to their base types. - /// - Catches of non-record types will only trigger for exceptions - /// of non-record types, which never have destructors. - /// - Catches of record types can trigger for arbitrary subclasses - /// of the caught type, so we have to assume the actual thrown - /// exception type might have a throwing destructor, even if the - /// caught type's destructor is trivial or nothrow. + // A cleanup to call __cxa_end_catch. Assume that the call is nounwind, i.e. + // the destructor of the thrown exception cannot throw. struct CallEndCatch final : EHScopeStack::Cleanup { - CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} - bool MightThrow; - void Emit(CodeGenFunction &CGF, Flags flags) override { - if (!MightThrow) { - CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM)); - return; - } - - CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM)); + CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM)); } }; } /// Emits a call to __cxa_begin_catch and enters a cleanup to call /// __cxa_end_catch. -/// -/// \param EndMightThrow - true if __cxa_end_catch might throw static llvm::Value *CallBeginCatch(CodeGenFunction &CGF, - llvm::Value *Exn, - bool EndMightThrow) { + llvm::Value *Exn) { llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn); - CGF.EHStack.pushCleanup(NormalAndEHCleanup, EndMightThrow); + CGF.EHStack.pushCleanup(NormalAndEHCleanup); return call; } @@ -4472,10 +4451,9 @@ // pointer to the appropriate pointer. if (isa(CatchType)) { QualType CaughtType = cast(CatchType)->getPointeeType(); - bool EndCatchMightThrow = CaughtType->isRecordType(); // __cxa_begin_catch returns the adjusted object pointer. - llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); + llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn); // We have no way to tell the personality function that we're // catching by reference, so if we're catching a pointer, @@ -4533,7 +4511,7 @@ // Scalars and complexes. TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType); if (TEK != TEK_Aggregate) { - llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); + llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn); // If the catch type is a pointer type, __cxa_begin_catch returns // the pointer by value. @@ -4592,7 +4570,7 @@ // that means a trivial copy is okay. const Expr *copyExpr = CatchParam.getInit(); if (!copyExpr) { - llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); + llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn); Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), caughtExnAlignment); LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType); @@ -4634,7 +4612,7 @@ opaque.pop(); // Finally we can call __cxa_begin_catch. - CallBeginCatch(CGF, Exn, true); + CallBeginCatch(CGF, Exn); } /// Begins a catch statement by initializing the catch variable and @@ -4667,7 +4645,7 @@ VarDecl *CatchParam = S->getExceptionDecl(); if (!CatchParam) { llvm::Value *Exn = CGF.getExceptionFromSlot(); - CallBeginCatch(CGF, Exn, true); + CallBeginCatch(CGF, Exn); return; } diff --git a/clang/test/CodeGenCXX/eh.cpp b/clang/test/CodeGenCXX/eh.cpp --- a/clang/test/CodeGenCXX/eh.cpp +++ b/clang/test/CodeGenCXX/eh.cpp @@ -228,18 +228,18 @@ // CHECK-NEXT: store i32 // CHECK-NEXT: call void @__cxa_end_catch() [[NUW:#[0-9]+]] } catch (B a) { + // CHECK: call void @_ZN6test101AD1Ev( + // CHECK-NEXT: ret void // CHECK: call i8* @__cxa_begin_catch // CHECK-NEXT: bitcast // CHECK-NEXT: bitcast // CHECK-NEXT: bitcast // CHECK-NEXT: call void @llvm.memcpy - // CHECK-NEXT: invoke void @__cxa_end_catch() + // CHECK-NEXT: call void @__cxa_end_catch() } catch (...) { // CHECK: call i8* @__cxa_begin_catch - // CHECK-NEXT: invoke void @__cxa_end_catch() } - // CHECK: call void @_ZN6test101AD1Ev( } } diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp --- a/clang/test/CodeGenCXX/exceptions.cpp +++ b/clang/test/CodeGenCXX/exceptions.cpp @@ -494,8 +494,8 @@ // CHECK98: call void @__cxa_end_catch() // CHECK98-NEXT: br label - // CHECK11: invoke void @__cxa_end_catch() - // CHECK11-NEXT: to label + // CHECK11: call void @__cxa_end_catch() + // CHECK11-NEXT: br label // CHECK: invoke void @__cxa_rethrow() // CHECK: unreachable diff --git a/clang/test/CodeGenCXX/stack-reuse-exceptions.cpp b/clang/test/CodeGenCXX/stack-reuse-exceptions.cpp --- a/clang/test/CodeGenCXX/stack-reuse-exceptions.cpp +++ b/clang/test/CodeGenCXX/stack-reuse-exceptions.cpp @@ -86,8 +86,8 @@ // // CHECK: [[CATCH]]: // CHECK-NOT: call void @llvm.lifetime -// CHECK: invoke void -// CHECK-NEXT: to label %[[TRY_CONT]] unwind label %[[OUTER_LPAD:.+]] +// CHECK: call void @__cxa_end_catch +// CHECK-NEXT: br label %[[TRY_CONT]] // // CHECK: [[TRY_CONT]]: // CHECK: %[[T_OUTER:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8* @@ -100,15 +100,7 @@ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]]) // CHECK: ret void // -// CHECK: [[OUTER_LPAD]]: -// CHECK-NOT: call void @llvm.lifetime -// CHECK: br label %[[EHCLEANUP:.+]] -// -// CHECK: [[OUTER_LPAD2]]: -// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]]) -// CHECK: br label %[[EHCLEANUP]] -// -// CHECK: [[EHCLEANUP]]: +// CHECK: lpad[[#]]: // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]]) NontrivialDtor clean; diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp --- a/clang/test/CodeGenCXX/wasm-eh.cpp +++ b/clang/test/CodeGenCXX/wasm-eh.cpp @@ -175,22 +175,14 @@ // CHECK-NEXT: to label %[[INVOKE_CONT_BB0:.*]] unwind label %[[EHCLEANUP_BB:.*]] // CHECK: [[INVOKE_CONT_BB0]]: -// CHECK-NEXT: call void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: call void @__cxa_end_catch() #[[#]] [ "funclet"(token %[[CATCHPAD]]) ] // CHECK-NEXT: catchret from %[[CATCHPAD]] to label // CHECK: [[EHCLEANUP_BB]]: // CHECK-NEXT: %[[CLEANUPPAD0:.*]] = cleanuppad within %[[CATCHPAD]] [] -// CHECK-NEXT: invoke void @__cxa_end_catch() [ "funclet"(token %[[CLEANUPPAD0]]) ] -// CHECK-NEXT: to label %[[INVOKE_CONT_BB1:.*]] unwind label %[[TERMINATE_BB:.*]] - -// CHECK: [[INVOKE_CONT_BB1]]: +// CHECK-NEXT: call void @__cxa_end_catch() #[[#]] [ "funclet"(token %[[CLEANUPPAD0]]) ] // CHECK-NEXT: cleanupret from %[[CLEANUPPAD0]] unwind to caller -// CHECK: [[TERMINATE_BB]]: -// CHECK-NEXT: %[[CLEANUPPAD1:.*]] = cleanuppad within %[[CLEANUPPAD0]] [] -// CHECK-NEXT: call void @_ZSt9terminatev() {{.*}} [ "funclet"(token %[[CLEANUPPAD1]]) ] -// CHECK-NEXT: unreachable - // Try-catch with cleanups void test6() { Cleanup c1; @@ -312,12 +304,12 @@ // CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ] -// CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD1]]) ] +// CHECK: call void @__cxa_end_catch() #[[#]] [ "funclet"(token %[[CATCHPAD1]]) ] // CHECK: catchret from %[[CATCHPAD1]] to label // CHECK: %[[CLEANUPPAD4:.*]] = cleanuppad within %[[CATCHPAD1]] [] -// CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CLEANUPPAD4]]) ] +// CHECK: call void @__cxa_end_catch() #[[#]] [ "funclet"(token %[[CLEANUPPAD4]]) ] // CHECK: cleanupret from %[[CLEANUPPAD4]] unwind label @@ -329,8 +321,6 @@ // CHECK: unreachable -// CHECK: %[[CLEANUPPAD7:.*]] = cleanuppad within %[[CLEANUPPAD4]] [] -// CHECK: call void @_ZSt9terminatev() {{.*}} [ "funclet"(token %[[CLEANUPPAD7]]) ] // CHECK: unreachable // Nested try-catches within a catch diff --git a/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp b/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp --- a/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp +++ b/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp @@ -53,9 +53,7 @@ // CHECK: invoke void @_ZN13throwing_task12promise_type19unhandled_exceptionEv // CHECK-NEXT: to label %[[RESUMEENDCATCH:.+]] unwind label // CHECK: [[RESUMEENDCATCH]]: - // CHECK-NEXT: invoke void @__cxa_end_catch() - // CHECK-NEXT: to label %[[RESUMEENDCATCHCONT:.+]] unwind label - // CHECK: [[RESUMEENDCATCHCONT]]: + // CHECK-NEXT: call void @__cxa_end_catch() // CHECK-NEXT: br label %[[RESUMETRYCONT]] // CHECK: [[RESUMETRYCONT]]: // CHECK-NEXT: br label %[[CLEANUP:.+]] diff --git a/clang/test/CodeGenCoroutines/coro-cleanup.cpp b/clang/test/CodeGenCoroutines/coro-cleanup.cpp --- a/clang/test/CodeGenCoroutines/coro-cleanup.cpp +++ b/clang/test/CodeGenCoroutines/coro-cleanup.cpp @@ -49,7 +49,8 @@ // CHECK: [[DeallocPad]]: // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup - // CHECK: br label %[[Dealloc:.+]] + // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( + // CHECK: br i1 %[[#]], label %[[Dealloc:.+]], label Cleanup cleanup; may_throw(); @@ -68,12 +69,10 @@ // CHECK: [[Catch]]: // CHECK: call i8* @__cxa_begin_catch( // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type19unhandled_exceptionEv( - // CHECK: invoke void @__cxa_end_catch() - // CHECK-NEXT: to label %[[Cont:.+]] unwind + // CHECK: call void @__cxa_end_catch() + // CHECK-NEXT: br label %[[Cont:.+]] // CHECK: [[Cont]]: - // CHECK-NEXT: br label %[[Cont2:.+]] - // CHECK: [[Cont2]]: // CHECK-NEXT: br label %[[Cleanup:.+]] // CHECK: [[Cleanup]]: @@ -82,7 +81,6 @@ // CHECK: call void @_ZdlPv(i8* %[[Mem0]] // CHECK: [[Dealloc]]: - // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( // CHECK: call void @_ZdlPv(i8* %[[Mem]]) co_return; diff --git a/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp b/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp --- a/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp +++ b/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp @@ -72,15 +72,7 @@ // CHECK-LPAD: call void @_ZN7CleanupD1Ev( // CHECK-LPAD: call i8* @__cxa_begin_catch // CHECK-LPAD: call void @_ZN6coro_t12promise_type19unhandled_exceptionEv -// CHECK-LPAD: invoke void @__cxa_end_catch() -// CHECK-LPAD: to label %{{.+}} unwind label %[[UNWINDBB:.+]] +// CHECK-LPAD: call void @__cxa_end_catch() -// CHECK-LPAD: [[UNWINDBB]]: -// CHECK-LPAD: %[[I1RESUME:.+]] = call i1 @llvm.coro.end(i8* null, i1 true) -// CHECK-LPAD: br i1 %[[I1RESUME]], label %[[EHRESUME:.+]], label -// CHECK-LPAD: [[EHRESUME]]: -// CHECK-LPAD-NEXT: %[[exn:.+]] = load i8*, i8** %exn.slot, align 8 -// CHECK-LPAD-NEXT: %[[sel:.+]] = load i32, i32* %ehselector.slot, align 4 -// CHECK-LPAD-NEXT: %[[val1:.+]] = insertvalue { i8*, i32 } undef, i8* %[[exn]], 0 -// CHECK-LPAD-NEXT: %[[val2:.+]] = insertvalue { i8*, i32 } %[[val1]], i32 %[[sel]], 1 -// CHECK-LPAD-NEXT: resume { i8*, i32 } %[[val2]] +// CHECK-LPAD: %{{.+}} = call i1 @llvm.coro.end(i8* null, i1 false) +// CHECK-LPAD: ret void diff --git a/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp b/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp --- a/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp +++ b/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp @@ -64,9 +64,7 @@ // CHECK-LPAD: [[CATCH]]: // CHECK-LPAD: call i8* @__cxa_begin_catch // CHECK-LPAD: call void @_ZN6coro_t12promise_type19unhandled_exceptionEv(%"struct.coro_t::promise_type"* {{[^,]*}} %__promise) #2 -// CHECK-LPAD: invoke void @__cxa_end_catch() -// CHECK-LPAD-NEXT: to label %[[CATCHRETDEST:.+]] unwind label -// CHECK-LPAD: [[CATCHRETDEST]]: +// CHECK-LPAD: call void @__cxa_end_catch() // CHECK-LPAD-NEXT: br label %[[TRYCONT:.+]] // CHECK-LPAD: [[TRYCONT]]: // CHECK-LPAD: br label %[[COROFIN:.+]]