Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -1400,6 +1400,7 @@ BUILTIN(__builtin_coro_begin, "v*v*", "n") BUILTIN(__builtin_coro_end, "bv*Ib", "n") BUILTIN(__builtin_coro_suspend, "cIb", "n") +BUILTIN(__builtin_coro_eh_suspend, "bI", "n") BUILTIN(__builtin_coro_param, "bv*v*", "n") // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. // We need the generic prototype, since the packet type could be anything. Index: lib/CodeGen/CGCoroutine.cpp =================================================================== --- lib/CodeGen/CGCoroutine.cpp +++ lib/CodeGen/CGCoroutine.cpp @@ -351,6 +351,31 @@ // We will insert coro.end to cut any of the destructors for objects that // do not need to be destroyed once the coroutine is resumed. // See llvm/docs/Coroutines.rst for more details about coro.end. +struct CallCoroEhSuspend final : public EHScopeStack::Cleanup { + void Emit(CodeGenFunction &CGF, Flags flags) override { + auto &CGM = CGF.CGM; // xxx + auto *None = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + llvm::Function *CoroSuspendEhFn = CGM.getIntrinsic(llvm::Intrinsic::coro_eh_suspend); + // See if we have a funclet bundle to associate coro.end with. (WinEH) + auto Bundles = getBundlesForCoroEnd(CGF); + auto *CoroSuspendEh = + CGF.Builder.CreateCall(CoroSuspendEhFn, {None}, Bundles); + if (Bundles.empty()) { + // Otherwise, (landingpad model), create a conditional branch that leads + // either to a cleanup block or a block with EH resume instruction. + auto *ResumeBB = CGF.getEHResumeBlock(/*cleanup=*/true); + auto *CleanupContBB = CGF.createBasicBlock("eh.suspend.cleanup"); + CGF.Builder.CreateCondBr(CoroSuspendEh, ResumeBB, CleanupContBB); + CGF.EmitBlock(CleanupContBB); + } + } +}; +} // namespace + +namespace { +// We will insert coro.end to cut any of the destructors for objects that +// do not need to be destroyed once the coroutine is resumed. +// See llvm/docs/Coroutines.rst for more details about coro.end. struct CallCoroEnd final : public EHScopeStack::Cleanup { void Emit(CodeGenFunction &CGF, Flags flags) override { auto &CGM = CGF.CGM; @@ -401,7 +426,7 @@ auto *CoroFree = CGF.CurCoro.Data->LastCoroFree; if (!CoroFree) { CGF.CGM.Error(Deallocate->getLocStart(), - "Deallocation expressoin does not refer to coro.free"); + "Deallocation expression does not refer to coro.free"); return; } @@ -556,6 +581,8 @@ GetReturnObjectManager GroManager(*this, S); GroManager.EmitGroAlloca(); + EHStack.pushCleanup(EHCleanup); + CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB); { ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap); @@ -585,7 +612,7 @@ // Now we have the promise, initialize the GRO GroManager.EmitGroInit(); - EHStack.pushCleanup(EHCleanup); + EHStack.pushCleanup(EHCleanup); CurCoro.Data->CurrentAwaitKind = AwaitKind::Init; EmitStmt(S.getInitSuspendStmt()); Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -1282,7 +1282,7 @@ // Try to form 'p.unhandled_exception();' assert(!IsPromiseDependentType && "cannot make statement while the promise type is dependent"); - +#if 0 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions; if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) { @@ -1296,7 +1296,12 @@ << PromiseRecordDecl; return !RequireUnhandledException; } +#else + if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) { + return true; + } +#endif // If exceptions are disabled, don't try to build OnException. if (!S.getLangOpts().CXXExceptions) return true;