================ @@ -401,36 +432,85 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, return Calls; } Expr *CoroHandle = CoroHandleRes.get(); + Calls.UseAwaitSuspendDestroy = false; CallExpr *AwaitSuspend = cast_or_null<CallExpr>( BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle)); if (!AwaitSuspend) return Calls; + + // When this `await_suspend()` overload is annotated with + // `[[clang::coro_await_suspend_destroy]]`, do NOT call `await_suspend()` -- + // instead call `await_suspend_destroy(Promise&)`. This assumes that the + // `await_suspend()` is just a compatibility stub consisting of: + // await_suspend_destroy(handle.promise()); + // handle.destroy(); + // Users of the attribute must follow this contract. Then, diagnostics from + // both `await_suspend` and `await_suspend_destroy` will get exposed. + CallExpr *PlainAwaitSuspend = nullptr; + if (FunctionDecl *AwaitSuspendCallee = AwaitSuspend->getDirectCallee()) { + if (AwaitSuspendCallee->hasAttr<CoroAwaitSuspendDestroyAttr>()) { + Calls.UseAwaitSuspendDestroy = true; + ExprResult PromiseRefRes = + buildPromiseRef(S, CoroPromise->getType(), Loc); + if (PromiseRefRes.isInvalid()) { + Calls.IsInvalid = true; + return Calls; + } + Expr *PromiseRef = PromiseRefRes.get(); + PlainAwaitSuspend = AwaitSuspend; + AwaitSuspend = cast_or_null<CallExpr>( + BuildSubExpr(ACT::ACT_Suspend, "await_suspend_destroy", PromiseRef)); + if (!AwaitSuspend) + return Calls; + } + } ---------------- ChuanqiXu9 wrote:
I don't have a good method now. And I am confused why do you have to do overload resolution? Is it bad to lookup `await_suspend_destroy ` directly? https://github.com/llvm/llvm-project/pull/152623 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits