static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, StringRef Keyword) { if (!checkCoroutineContext(S, KWLoc, Keyword)) return false; auto *ScopeInfo = S.getCurFunction(); assert(ScopeInfo->CoroutinePromise); // If we have existing coroutine statements then we have already built // the initial and final suspend points. if (!ScopeInfo->NeedsCoroutineSuspends) return true; ScopeInfo->setNeedsCoroutineSuspends(false); auto *Fn = cast<FunctionDecl>(S.CurContext); SourceLocation Loc = Fn->getLocation(); // Build the initial suspend point auto buildSuspends = [&](StringRef Name) mutable -> StmtResult { ExprResult Suspend = buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None); if (Suspend.isInvalid()) return StmtError(); Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get()); if (Suspend.isInvalid()) return StmtError(); Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(), /*IsImplicit*/ true); Suspend = S.ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword; return StmtError(); } return cast<Stmt>(Suspend.get()); }; StmtResult InitSuspend = buildSuspends("initial_suspend"); if (InitSuspend.isInvalid()) return true; StmtResult FinalSuspend = buildSuspends("final_suspend"); if (FinalSuspend.isInvalid()) return true; ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get()); return true; }