llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Yuxuan Chen (yuxuanchen1997) <details> <summary>Changes</summary> Previously we were not properly skipping the generation of the `try { }` block around the `init_suspend.await_resume()` if the `await_resume` is not returning void. The reason being that the resume expression was wrapped in a `CXXBindTemporaryExpr` and the first dyn_cast failed, silently ignoring the noexcept. This only mattered for `init_suspend` because it had its own try block. This patch changes that to extract the sub expression when we see a `CXXBindTemporaryExpr`. Another version of this patch also wanted to assert by `cast<CXXMemberCallExpr>` and as far as I understand it should be a valid assumption. I can change to that if upstream prefers. --- Full diff: https://github.com/llvm/llvm-project/pull/73160.diff 2 Files Affected: - (modified) clang/lib/CodeGen/CGCoroutine.cpp (+11-3) - (modified) clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp (+47-3) ``````````diff diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index aaf122c0f83bc47..724d471cc9d78b6 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -12,9 +12,10 @@ #include "CGCleanup.h" #include "CodeGenFunction.h" -#include "llvm/ADT/ScopeExit.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtVisitor.h" +#include "llvm/ADT/ScopeExit.h" using namespace clang; using namespace CodeGen; @@ -129,7 +130,14 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { return Prefix; } -static bool memberCallExpressionCanThrow(const Expr *E) { +static bool ResumeExprCanThrow(const CoroutineSuspendExpr &S) { + const Expr *E = S.getResumeExpr(); + + // If the return type of await_resume is not void, get the CXXMemberCallExpr + // from its subexpr. + if (const auto *BindTempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) { + E = BindTempExpr->getSubExpr(); + } if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E)) if (const auto *Proto = CE->getMethodDecl()->getType()->getAs<FunctionProtoType>()) @@ -233,7 +241,7 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co // is marked as 'noexcept', we avoid generating this additional IR. CXXTryStmt *TryStmt = nullptr; if (Coro.ExceptionHandler && Kind == AwaitKind::Init && - memberCallExpressionCanThrow(S.getResumeExpr())) { + ResumeExprCanThrow(S)) { Coro.ResumeEHVar = CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh")); Builder.CreateFlagStore(true, Coro.ResumeEHVar); diff --git a/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp b/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp index c4b8da327f5c140..0e50a616d6ef7c2 100644 --- a/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp +++ b/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp @@ -3,6 +3,7 @@ #include "Inputs/coroutine.h" +namespace can_throw { struct NontrivialType { ~NontrivialType() {} }; @@ -38,9 +39,52 @@ Task coro_create() { co_return; } -// CHECK-LABEL: define{{.*}} ptr @_Z11coro_createv( +// CHECK-LABEL: define{{.*}} ptr @_ZN9can_throw11coro_createEv( // CHECK: init.ready: // CHECK-NEXT: store i1 true, ptr {{.*}} -// CHECK-NEXT: call void @_ZN4Task23initial_suspend_awaiter12await_resumeEv( -// CHECK-NEXT: call void @_ZN14NontrivialTypeD1Ev( +// CHECK-NEXT: call void @_ZN9can_throw4Task23initial_suspend_awaiter12await_resumeEv( +// CHECK-NEXT: call void @_ZN9can_throw14NontrivialTypeD1Ev( // CHECK-NEXT: store i1 false, ptr {{.*}} +} + +namespace no_throw { +struct NontrivialType { + ~NontrivialType() {} +}; + +struct Task { + struct promise_type; + using handle_type = std::coroutine_handle<promise_type>; + + struct initial_suspend_awaiter { + bool await_ready() { + return false; + } + + void await_suspend(handle_type h) {} + + NontrivialType await_resume() noexcept { return {}; } + }; + + struct promise_type { + void return_void() {} + void unhandled_exception() {} + initial_suspend_awaiter initial_suspend() { return {}; } + std::suspend_never final_suspend() noexcept { return {}; } + Task get_return_object() { + return Task{handle_type::from_promise(*this)}; + } + }; + + handle_type handler; +}; + +Task coro_create() { + co_return; +} + +// CHECK-LABEL: define{{.*}} ptr @_ZN8no_throw11coro_createEv( +// CHECK: init.ready: +// CHECK-NEXT: call void @_ZN8no_throw4Task23initial_suspend_awaiter12await_resumeEv( +// CHECK-NEXT: call void @_ZN8no_throw14NontrivialTypeD1Ev( +} `````````` </details> https://github.com/llvm/llvm-project/pull/73160 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits