https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/92645

>From 4fe09a3411e54561857d2f9d8c1808cb2728e299 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com>
Date: Sat, 18 May 2024 13:33:04 +0300
Subject: [PATCH 1/3] [clang] Introduce `SemaCoroutine`

---
 clang/include/clang/Sema/Sema.h          |  58 +-----
 clang/include/clang/Sema/SemaCoroutine.h |  73 ++++++++
 clang/lib/Parse/ParseExpr.cpp            |   3 +-
 clang/lib/Parse/ParseExprCXX.cpp         |   3 +-
 clang/lib/Parse/ParseStmt.cpp            |   3 +-
 clang/lib/Sema/Sema.cpp                  |   4 +-
 clang/lib/Sema/SemaCoroutine.cpp         | 218 ++++++++++++-----------
 clang/lib/Sema/SemaDecl.cpp              |  16 +-
 clang/lib/Sema/SemaStmt.cpp              |   9 +-
 clang/lib/Sema/TreeTransform.h           |  25 +--
 10 files changed, 227 insertions(+), 185 deletions(-)
 create mode 100644 clang/include/clang/Sema/SemaCoroutine.h

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d4d4a82525a02..1d0fbeacfe061 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -168,6 +168,7 @@ class PseudoDestructorTypeStorage;
 class PseudoObjectExpr;
 class QualType;
 class SemaCodeCompletion;
+class SemaCoroutine;
 class SemaCUDA;
 class SemaHLSL;
 class SemaObjC;
@@ -989,6 +990,11 @@ class Sema final : public SemaBase {
     return *CodeCompletionPtr;
   }
 
+  SemaCoroutine &Coroutine() {
+    assert(CoroutinePtr);
+    return *CoroutinePtr;
+  }
+
   SemaCUDA &CUDA() {
     assert(CUDAPtr);
     return *CUDAPtr;
@@ -1050,6 +1056,7 @@ class Sema final : public SemaBase {
   mutable IdentifierInfo *Ident_super;
 
   std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
+  std::unique_ptr<SemaCoroutine> CoroutinePtr;
   std::unique_ptr<SemaCUDA> CUDAPtr;
   std::unique_ptr<SemaHLSL> HLSLPtr;
   std::unique_ptr<SemaObjC> ObjCPtr;
@@ -2267,57 +2274,6 @@ class Sema final : public SemaBase {
   //
   //
 
-  /// \name C++ Coroutines
-  /// Implementations are in SemaCoroutine.cpp
-  ///@{
-
-public:
-  /// The C++ "std::coroutine_traits" template, which is defined in
-  /// \<coroutine_traits>
-  ClassTemplateDecl *StdCoroutineTraitsCache;
-
-  bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc,
-                               StringRef Keyword);
-  ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E);
-  ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E);
-  StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E);
-
-  ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc);
-  ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
-                                      UnresolvedLookupExpr *Lookup);
-  ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
-                                      Expr *Awaiter, bool IsImplicit = false);
-  ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
-                                        UnresolvedLookupExpr *Lookup);
-  ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E);
-  StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E,
-                               bool IsImplicit = false);
-  StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs);
-  bool buildCoroutineParameterMoves(SourceLocation Loc);
-  VarDecl *buildCoroutinePromise(SourceLocation Loc);
-  void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
-
-  // As a clang extension, enforces that a non-coroutine function must be 
marked
-  // with [[clang::coro_wrapper]] if it returns a type marked with
-  // [[clang::coro_return_type]].
-  // Expects that FD is not a coroutine.
-  void CheckCoroutineWrapper(FunctionDecl *FD);
-  /// Lookup 'coroutine_traits' in std namespace and std::experimental
-  /// namespace. The namespace found is recorded in Namespace.
-  ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
-                                           SourceLocation FuncLoc);
-  /// Check that the expression co_await promise.final_suspend() shall not be
-  /// potentially-throwing.
-  bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
-
-  ///@}
-
-  //
-  //
-  // -------------------------------------------------------------------------
-  //
-  //
-
   /// \name C++ Scope Specifiers
   /// Implementations are in SemaCXXScopeSpec.cpp
   ///@{
diff --git a/clang/include/clang/Sema/SemaCoroutine.h 
b/clang/include/clang/Sema/SemaCoroutine.h
new file mode 100644
index 0000000000000..20f1fffc970f8
--- /dev/null
+++ b/clang/include/clang/Sema/SemaCoroutine.h
@@ -0,0 +1,73 @@
+//===----- SemaCUDA.h ----- Semantic Analysis for C++20 coroutines 
--------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis for C++20 coroutines.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMACOROUTINE_H
+#define LLVM_CLANG_SEMA_SEMACOROUTINE_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/SemaBase.h"
+#include "clang/Sema/Scope.h"
+
+namespace clang {
+class SemaCoroutine : public SemaBase {
+public:
+  SemaCoroutine(Sema &S);
+
+  /// The C++ "std::coroutine_traits" template, which is defined in
+  /// \<coroutine_traits>
+  ClassTemplateDecl *StdCoroutineTraitsCache;
+
+  bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc,
+                               StringRef Keyword);
+  ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+  ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+  StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E);
+
+  ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc);
+  ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
+                                      UnresolvedLookupExpr *Lookup);
+  ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
+                                      Expr *Awaiter, bool IsImplicit = false);
+  ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
+                                        UnresolvedLookupExpr *Lookup);
+  ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E);
+  StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E,
+                               bool IsImplicit = false);
+  StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs);
+  bool buildCoroutineParameterMoves(SourceLocation Loc);
+  VarDecl *buildCoroutinePromise(SourceLocation Loc);
+  void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
+
+  // As a clang extension, enforces that a non-coroutine function must be 
marked
+  // with [[clang::coro_wrapper]] if it returns a type marked with
+  // [[clang::coro_return_type]].
+  // Expects that FD is not a coroutine.
+  void CheckCoroutineWrapper(FunctionDecl *FD);
+  /// Lookup 'coroutine_traits' in std namespace and std::experimental
+  /// namespace. The namespace found is recorded in Namespace.
+  ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
+                                           SourceLocation FuncLoc);
+  /// Check that the expression co_await promise.final_suspend() shall not be
+  /// potentially-throwing.
+  bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMACOROUTINE_H
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e4..e8b0e42466aab 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -32,6 +32,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenACC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -1465,7 +1466,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
     SourceLocation CoawaitLoc = ConsumeToken();
     Res = ParseCastExpression(AnyCastExpr);
     if (!Res.isInvalid())
-      Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get());
+      Res = Actions.Coroutine().ActOnCoawaitExpr(getCurScope(), CoawaitLoc, 
Res.get());
     return Res;
   }
 
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index e149b1a0fb5ef..78db3a7deeaac 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -24,6 +24,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <numeric>
@@ -1977,7 +1978,7 @@ ExprResult Parser::ParseCoyieldExpression() {
   ExprResult Expr = Tok.is(tok::l_brace) ? ParseBraceInitializer()
                                          : ParseAssignmentExpression();
   if (!Expr.isInvalid())
-    Expr = Actions.ActOnCoyieldExpr(getCurScope(), Loc, Expr.get());
+    Expr = Actions.Coroutine().ActOnCoyieldExpr(getCurScope(), Loc, 
Expr.get());
   return Expr;
 }
 
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index b0af04451166c..8ebce6bc726d3 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -23,6 +23,7 @@
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
 #include "clang/Sema/TypoCorrection.h"
@@ -2456,7 +2457,7 @@ StmtResult Parser::ParseReturnStatement() {
     }
   }
   if (IsCoreturn)
-    return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get());
+    return Actions.Coroutine().ActOnCoreturnStmt(getCurScope(), ReturnLoc, 
R.get());
   return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
 }
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f847c49920cf3..f218d3e39eb70 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -43,6 +43,7 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaConsumer.h"
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
@@ -205,6 +206,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer 
&consumer,
       CurScope(nullptr), Ident_super(nullptr),
       CodeCompletionPtr(
           std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
+      CoroutinePtr(std::make_unique<SemaCoroutine>(*this)),
       CUDAPtr(std::make_unique<SemaCUDA>(*this)),
       HLSLPtr(std::make_unique<SemaHLSL>(*this)),
       ObjCPtr(std::make_unique<SemaObjC>(*this)),
@@ -219,7 +221,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer 
&consumer,
       CodeSegStack(nullptr), StrictGuardStackCheckStack(false),
       FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr),
       VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
-      StdCoroutineTraitsCache(nullptr), IdResolver(pp),
+      IdResolver(pp),
       OriginalLexicalContext(nullptr), StdInitializerList(nullptr),
       FullyCheckedComparisonCategories(
           static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 81334c817b2af..efca77c78428b 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -13,6 +13,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "clang/Sema/SemaCoroutine.h"
 #include "CoroutineStmtBuilder.h"
 #include "clang/AST/ASTLambda.h"
 #include "clang/AST/Decl.h"
@@ -25,6 +26,7 @@
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Overload.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaInternal.h"
 #include "llvm/ADT/SmallSet.h"
 
@@ -57,7 +59,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl 
*FD,
   const SourceLocation FuncLoc = FD->getLocation();
 
   ClassTemplateDecl *CoroTraits =
-      S.lookupCoroutineTraits(KwLoc, FuncLoc);
+      S.Coroutine().lookupCoroutineTraits(KwLoc, FuncLoc);
   if (!CoroTraits)
     return QualType();
 
@@ -249,19 +251,19 @@ static bool isValidCoroutineContext(Sema &S, 
SourceLocation Loc,
 
 /// Build a call to 'operator co_await' if there is a suitable operator for
 /// the given expression.
-ExprResult Sema::BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
+ExprResult SemaCoroutine::BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
                                           UnresolvedLookupExpr *Lookup) {
   UnresolvedSet<16> Functions;
   Functions.append(Lookup->decls_begin(), Lookup->decls_end());
-  return CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
+  return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
 }
 
 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
                                            SourceLocation Loc, Expr *E) {
-  ExprResult R = SemaRef.BuildOperatorCoawaitLookupExpr(S, Loc);
+  ExprResult R = SemaRef.Coroutine().BuildOperatorCoawaitLookupExpr(S, Loc);
   if (R.isInvalid())
     return ExprError();
-  return SemaRef.BuildOperatorCoawaitCall(Loc, E,
+  return SemaRef.Coroutine().BuildOperatorCoawaitCall(Loc, E,
                                           cast<UnresolvedLookupExpr>(R.get()));
 }
 
@@ -475,9 +477,10 @@ static ExprResult buildPromiseCall(Sema &S, VarDecl 
*Promise,
   return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
 }
 
-VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
-  assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
-  auto *FD = cast<FunctionDecl>(CurContext);
+VarDecl *SemaCoroutine::buildCoroutinePromise(SourceLocation Loc) {
+  assert(isa<FunctionDecl>(SemaRef.CurContext) && "not in a function scope");
+  ASTContext &Context = getASTContext();
+  auto *FD = cast<FunctionDecl>(SemaRef.CurContext);
   bool IsThisDependentType = [&] {
     if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD))
       return MD->isImplicitObjectMemberFunction() &&
@@ -487,19 +490,19 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
 
   QualType T = FD->getType()->isDependentType() || IsThisDependentType
                    ? Context.DependentTy
-                   : lookupPromiseType(*this, FD, Loc);
+                   : lookupPromiseType(SemaRef, FD, Loc);
   if (T.isNull())
     return nullptr;
 
   auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
-                             &PP.getIdentifierTable().get("__promise"), T,
+                             
&SemaRef.PP.getIdentifierTable().get("__promise"), T,
                              Context.getTrivialTypeSourceInfo(T, Loc), 
SC_None);
   VD->setImplicit();
-  CheckVariableDeclarationType(VD);
+  SemaRef.CheckVariableDeclarationType(VD);
   if (VD->isInvalidDecl())
     return nullptr;
 
-  auto *ScopeInfo = getCurFunction();
+  auto *ScopeInfo = SemaRef.getCurFunction();
 
   // Build a list of arguments, based on the coroutine function's arguments,
   // that if present will be passed to the promise type's constructor.
@@ -508,10 +511,10 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
   // Add implicit object parameter.
   if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
     if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
-      ExprResult ThisExpr = ActOnCXXThis(Loc);
+      ExprResult ThisExpr = SemaRef.ActOnCXXThis(Loc);
       if (ThisExpr.isInvalid())
         return nullptr;
-      ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+      ThisExpr = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
       if (ThisExpr.isInvalid())
         return nullptr;
       CtorArgExprs.push_back(ThisExpr.get());
@@ -533,7 +536,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
     auto *MoveDecl =
         cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
     RefExpr =
-        BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
+        SemaRef.BuildDeclRefExpr(MoveDecl, 
MoveDecl->getType().getNonReferenceType(),
                          ExprValueKind::VK_LValue, FD->getLocation());
     if (RefExpr.isInvalid())
       return nullptr;
@@ -550,7 +553,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
     InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
     InitializationKind Kind = InitializationKind::CreateForInit(
         VD->getLocation(), /*DirectInit=*/true, PLE);
-    InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
+    InitializationSequence InitSeq(SemaRef, Entity, Kind, CtorArgExprs,
                                    /*TopLevelOfInitList=*/false,
                                    /*TreatUnavailableAsInvalid=*/false);
 
@@ -561,18 +564,18 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
     // found ([over.match.viable]), then promise-constructor-arguments is ( q_1
     // , ...,  q_n ), otherwise promise-constructor-arguments is empty.
     if (InitSeq) {
-      ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
+      ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, CtorArgExprs);
       if (Result.isInvalid()) {
         VD->setInvalidDecl();
       } else if (Result.get()) {
-        VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
+        VD->setInit(SemaRef.MaybeCreateExprWithCleanups(Result.get()));
         VD->setInitStyle(VarDecl::CallInit);
-        CheckCompleteVariableDeclaration(VD);
+        SemaRef.CheckCompleteVariableDeclaration(VD);
       }
     } else
-      ActOnUninitializedDecl(VD);
+      SemaRef.ActOnUninitializedDecl(VD);
   } else
-    ActOnUninitializedDecl(VD);
+    SemaRef.ActOnUninitializedDecl(VD);
 
   FD->addDecl(VD);
   return VD;
@@ -596,10 +599,10 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, 
SourceLocation Loc,
   if (ScopeInfo->CoroutinePromise)
     return ScopeInfo;
 
-  if (!S.buildCoroutineParameterMoves(Loc))
+  if (!S.Coroutine().buildCoroutineParameterMoves(Loc))
     return nullptr;
 
-  ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
+  ScopeInfo->CoroutinePromise = S.Coroutine().buildCoroutinePromise(Loc);
   if (!ScopeInfo->CoroutinePromise)
     return nullptr;
 
@@ -666,13 +669,13 @@ static void checkNoThrow(Sema &S, const Stmt *E,
     }
 }
 
-bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
+bool SemaCoroutine::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
   llvm::SmallPtrSet<const Decl *, 4> ThrowingDecls;
   // We first collect all declarations that should not throw but not declared
   // with noexcept. We then sort them based on the location before printing.
   // This is to avoid emitting the same note multiple times on the same
   // declaration, and also provide a deterministic order for the messages.
-  checkNoThrow(*this, FinalSuspend, ThrowingDecls);
+  checkNoThrow(SemaRef, FinalSuspend, ThrowingDecls);
   auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(),
                                                         ThrowingDecls.end()};
   sort(SortedDecls, [](const Decl *A, const Decl *B) {
@@ -684,14 +687,14 @@ bool Sema::checkFinalSuspendNoThrow(const Stmt 
*FinalSuspend) {
   return ThrowingDecls.empty();
 }
 
-bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
+bool SemaCoroutine::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
                                    StringRef Keyword) {
   // Ignore previous expr evaluation contexts.
   EnterExpressionEvaluationContext PotentiallyEvaluated(
-      *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
-  if (!checkCoroutineContext(*this, KWLoc, Keyword))
+      SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+  if (!checkCoroutineContext(SemaRef, KWLoc, Keyword))
     return false;
-  auto *ScopeInfo = getCurFunction();
+  auto *ScopeInfo = SemaRef.getCurFunction();
   assert(ScopeInfo->CoroutinePromise);
 
   // If we have existing coroutine statements then we have already built
@@ -701,21 +704,21 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, 
SourceLocation KWLoc,
 
   ScopeInfo->setNeedsCoroutineSuspends(false);
 
-  auto *Fn = cast<FunctionDecl>(CurContext);
+  auto *Fn = cast<FunctionDecl>(SemaRef.CurContext);
   SourceLocation Loc = Fn->getLocation();
   // Build the initial suspend point
   auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
-    ExprResult Operand = buildPromiseCall(*this, ScopeInfo->CoroutinePromise,
+    ExprResult Operand = buildPromiseCall(SemaRef, ScopeInfo->CoroutinePromise,
                                           Loc, Name, std::nullopt);
     if (Operand.isInvalid())
       return StmtError();
     ExprResult Suspend =
-        buildOperatorCoawaitCall(*this, SC, Loc, Operand.get());
+        buildOperatorCoawaitCall(SemaRef, SC, Loc, Operand.get());
     if (Suspend.isInvalid())
       return StmtError();
     Suspend = BuildResolvedCoawaitExpr(Loc, Operand.get(), Suspend.get(),
                                        /*IsImplicit*/ true);
-    Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
+    Suspend = SemaRef.ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ 
false);
     if (Suspend.isInvalid()) {
       Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
           << ((Name == "initial_suspend") ? 0 : 1);
@@ -787,17 +790,17 @@ static bool checkSuspensionContext(Sema &S, 
SourceLocation Loc,
   return true;
 }
 
-ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
-  if (!checkSuspensionContext(*this, Loc, "co_await"))
+ExprResult SemaCoroutine::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr 
*E) {
+  if (!checkSuspensionContext(SemaRef, Loc, "co_await"))
     return ExprError();
 
   if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
-    CorrectDelayedTyposInExpr(E);
+    SemaRef.CorrectDelayedTyposInExpr(E);
     return ExprError();
   }
 
   if (E->hasPlaceholderType()) {
-    ExprResult R = CheckPlaceholderExpr(E);
+    ExprResult R = SemaRef.CheckPlaceholderExpr(E);
     if (R.isInvalid()) return ExprError();
     E = R.get();
   }
@@ -808,17 +811,17 @@ ExprResult Sema::ActOnCoawaitExpr(Scope *S, 
SourceLocation Loc, Expr *E) {
                                    cast<UnresolvedLookupExpr>(Lookup.get()));
 }
 
-ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) {
+ExprResult SemaCoroutine::BuildOperatorCoawaitLookupExpr(Scope *S, 
SourceLocation Loc) {
   DeclarationName OpName =
-      Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
-  LookupResult Operators(*this, OpName, SourceLocation(),
+      SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
+  LookupResult Operators(SemaRef, OpName, SourceLocation(),
                          Sema::LookupOperatorName);
-  LookupName(Operators, S);
+  SemaRef.LookupName(Operators, S);
 
   assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
   const auto &Functions = Operators.asUnresolvedSet();
   Expr *CoawaitOp = UnresolvedLookupExpr::Create(
-      Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
+      SemaRef.Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
       DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, 
Functions.begin(),
       Functions.end(), /*KnownDependent=*/false);
   assert(CoawaitOp);
@@ -827,14 +830,14 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, 
SourceLocation Loc) {
 
 // Attempts to resolve and build a CoawaitExpr from "raw" inputs, bailing out 
to
 // DependentCoawaitExpr if needed.
-ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *Operand,
+ExprResult SemaCoroutine::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr 
*Operand,
                                             UnresolvedLookupExpr *Lookup) {
-  auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
+  auto *FSI = checkCoroutineContext(SemaRef, Loc, "co_await");
   if (!FSI)
     return ExprError();
 
   if (Operand->hasPlaceholderType()) {
-    ExprResult R = CheckPlaceholderExpr(Operand);
+    ExprResult R = SemaRef.CheckPlaceholderExpr(Operand);
     if (R.isInvalid())
       return ExprError();
     Operand = R.get();
@@ -842,16 +845,16 @@ ExprResult 
Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *Operand,
 
   auto *Promise = FSI->CoroutinePromise;
   if (Promise->getType()->isDependentType()) {
-    Expr *Res = new (Context)
-        DependentCoawaitExpr(Loc, Context.DependentTy, Operand, Lookup);
+    Expr *Res = new (SemaRef.Context)
+        DependentCoawaitExpr(Loc, SemaRef.Context.DependentTy, Operand, 
Lookup);
     return Res;
   }
 
   auto *RD = Promise->getType()->getAsCXXRecordDecl();
   auto *Transformed = Operand;
-  if (lookupMember(*this, "await_transform", RD, Loc)) {
+  if (lookupMember(SemaRef, "await_transform", RD, Loc)) {
     ExprResult R =
-        buildPromiseCall(*this, Promise, Loc, "await_transform", Operand);
+        buildPromiseCall(SemaRef, Promise, Loc, "await_transform", Operand);
     if (R.isInvalid()) {
       Diag(Loc,
            diag::note_coroutine_promise_implicit_await_transform_required_here)
@@ -867,28 +870,28 @@ ExprResult 
Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *Operand,
   return BuildResolvedCoawaitExpr(Loc, Operand, Awaiter.get());
 }
 
-ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *Operand,
+ExprResult SemaCoroutine::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr 
*Operand,
                                           Expr *Awaiter, bool IsImplicit) {
-  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
+  auto *Coroutine = checkCoroutineContext(SemaRef, Loc, "co_await", 
IsImplicit);
   if (!Coroutine)
     return ExprError();
 
   if (Awaiter->hasPlaceholderType()) {
-    ExprResult R = CheckPlaceholderExpr(Awaiter);
+    ExprResult R = SemaRef.CheckPlaceholderExpr(Awaiter);
     if (R.isInvalid()) return ExprError();
     Awaiter = R.get();
   }
 
   if (Awaiter->getType()->isDependentType()) {
-    Expr *Res = new (Context)
-        CoawaitExpr(Loc, Context.DependentTy, Operand, Awaiter, IsImplicit);
+    Expr *Res = new (SemaRef.Context)
+        CoawaitExpr(Loc, SemaRef.Context.DependentTy, Operand, Awaiter, 
IsImplicit);
     return Res;
   }
 
   // If the expression is a temporary, materialize it as an lvalue so that we
   // can use it multiple times.
   if (Awaiter->isPRValue())
-    Awaiter = CreateMaterializeTemporaryExpr(Awaiter->getType(), Awaiter, 
true);
+    Awaiter = SemaRef.CreateMaterializeTemporaryExpr(Awaiter->getType(), 
Awaiter, true);
 
   // The location of the `co_await` token cannot be used when constructing
   // the member call expressions since it's before the location of `Expr`, 
which
@@ -897,46 +900,46 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation 
Loc, Expr *Operand,
 
   // Build the await_ready, await_suspend, await_resume calls.
   ReadySuspendResumeResult RSS =
-      buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, Awaiter);
+      buildCoawaitCalls(SemaRef, Coroutine->CoroutinePromise, CallLoc, 
Awaiter);
   if (RSS.IsInvalid)
     return ExprError();
 
-  Expr *Res = new (Context)
+  Expr *Res = new (SemaRef.Context)
       CoawaitExpr(Loc, Operand, Awaiter, RSS.Results[0], RSS.Results[1],
                   RSS.Results[2], RSS.OpaqueValue, IsImplicit);
 
   return Res;
 }
 
-ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
-  if (!checkSuspensionContext(*this, Loc, "co_yield"))
+ExprResult SemaCoroutine::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr 
*E) {
+  if (!checkSuspensionContext(SemaRef, Loc, "co_yield"))
     return ExprError();
 
   if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
-    CorrectDelayedTyposInExpr(E);
+    SemaRef.CorrectDelayedTyposInExpr(E);
     return ExprError();
   }
 
   // Build yield_value call.
   ExprResult Awaitable = buildPromiseCall(
-      *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
+      SemaRef, SemaRef.getCurFunction()->CoroutinePromise, Loc, "yield_value", 
E);
   if (Awaitable.isInvalid())
     return ExprError();
 
   // Build 'operator co_await' call.
-  Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
+  Awaitable = buildOperatorCoawaitCall(SemaRef, S, Loc, Awaitable.get());
   if (Awaitable.isInvalid())
     return ExprError();
 
   return BuildCoyieldExpr(Loc, Awaitable.get());
 }
-ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
-  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
+ExprResult SemaCoroutine::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
+  auto *Coroutine = checkCoroutineContext(SemaRef, Loc, "co_yield");
   if (!Coroutine)
     return ExprError();
 
   if (E->hasPlaceholderType()) {
-    ExprResult R = CheckPlaceholderExpr(E);
+    ExprResult R = SemaRef.CheckPlaceholderExpr(E);
     if (R.isInvalid()) return ExprError();
     E = R.get();
   }
@@ -944,45 +947,45 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, 
Expr *E) {
   Expr *Operand = E;
 
   if (E->getType()->isDependentType()) {
-    Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, Operand, 
E);
+    Expr *Res = new (SemaRef.Context) CoyieldExpr(Loc, 
SemaRef.Context.DependentTy, Operand, E);
     return Res;
   }
 
   // If the expression is a temporary, materialize it as an lvalue so that we
   // can use it multiple times.
   if (E->isPRValue())
-    E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
+    E = SemaRef.CreateMaterializeTemporaryExpr(E->getType(), E, true);
 
   // Build the await_ready, await_suspend, await_resume calls.
   ReadySuspendResumeResult RSS = buildCoawaitCalls(
-      *this, Coroutine->CoroutinePromise, Loc, E);
+      SemaRef, Coroutine->CoroutinePromise, Loc, E);
   if (RSS.IsInvalid)
     return ExprError();
 
   Expr *Res =
-      new (Context) CoyieldExpr(Loc, Operand, E, RSS.Results[0], 
RSS.Results[1],
+      new (SemaRef.Context) CoyieldExpr(Loc, Operand, E, RSS.Results[0], 
RSS.Results[1],
                                 RSS.Results[2], RSS.OpaqueValue);
 
   return Res;
 }
 
-StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
+StmtResult SemaCoroutine::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr 
*E) {
   if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
-    CorrectDelayedTyposInExpr(E);
+    SemaRef.CorrectDelayedTyposInExpr(E);
     return StmtError();
   }
   return BuildCoreturnStmt(Loc, E);
 }
 
-StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
+StmtResult SemaCoroutine::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
                                    bool IsImplicit) {
-  auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
+  auto *FSI = checkCoroutineContext(SemaRef, Loc, "co_return", IsImplicit);
   if (!FSI)
     return StmtError();
 
   if (E && E->hasPlaceholderType() &&
       !E->hasPlaceholderType(BuiltinType::Overload)) {
-    ExprResult R = CheckPlaceholderExpr(E);
+    ExprResult R = SemaRef.CheckPlaceholderExpr(E);
     if (R.isInvalid()) return StmtError();
     E = R.get();
   }
@@ -990,18 +993,18 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, 
Expr *E,
   VarDecl *Promise = FSI->CoroutinePromise;
   ExprResult PC;
   if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
-    getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn);
-    PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
+    SemaRef.getNamedReturnInfo(E, Sema::SimplerImplicitMoveMode::ForceOn);
+    PC = buildPromiseCall(SemaRef, Promise, Loc, "return_value", E);
   } else {
-    E = MakeFullDiscardedValueExpr(E).get();
-    PC = buildPromiseCall(*this, Promise, Loc, "return_void", std::nullopt);
+    E = SemaRef.MakeFullDiscardedValueExpr(E).get();
+    PC = buildPromiseCall(SemaRef, Promise, Loc, "return_void", std::nullopt);
   }
   if (PC.isInvalid())
     return StmtError();
 
-  Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
+  Expr *PCE = SemaRef.ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ 
false).get();
 
-  Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
+  Stmt *Res = new (SemaRef.Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
   return Res;
 }
 
@@ -1087,8 +1090,8 @@ static bool findDeleteForPromise(Sema &S, SourceLocation 
Loc, QualType PromiseTy
 }
 
 
-void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
-  FunctionScopeInfo *Fn = getCurFunction();
+void SemaCoroutine::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) 
{
+  FunctionScopeInfo *Fn = SemaRef.getCurFunction();
   assert(Fn && Fn->isCoroutine() && "not a coroutine");
   if (!Body) {
     assert(FD->isInvalidDecl() &&
@@ -1133,12 +1136,12 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl 
*FD, Stmt *&Body) {
   for (AddrLabelExpr *ALE : Fn->AddrLabels)
     Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
 
-  CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
+  CoroutineStmtBuilder Builder(SemaRef, *FD, *Fn, Body);
   if (Builder.isInvalid() || !Builder.buildStatements())
     return FD->setInvalidDecl();
 
   // Build body for the coroutine wrapper statement.
-  Body = CoroutineBodyStmt::Create(Context, Builder);
+  Body = CoroutineBodyStmt::Create(SemaRef.Context, Builder);
 }
 
 static CompoundStmt *buildCoroutineBody(Stmt *Body, ASTContext &Context) {
@@ -1656,7 +1659,7 @@ bool CoroutineStmtBuilder::makeOnFallthrough() {
     if (Fallthrough.isInvalid())
       return false;
   } else if (HasRVoid) {
-    Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
+    Fallthrough = S.Coroutine().BuildCoreturnStmt(FD.getLocation(), nullptr,
                                       /*IsImplicit=*/true);
     Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
     if (Fallthrough.isInvalid())
@@ -1861,11 +1864,11 @@ static VarDecl *buildVarDecl(Sema &S, SourceLocation 
Loc, QualType Type,
 
 // Build statements that move coroutine function parameters to the coroutine
 // frame, and store them on the function scope info.
-bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
-  assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
-  auto *FD = cast<FunctionDecl>(CurContext);
+bool SemaCoroutine::buildCoroutineParameterMoves(SourceLocation Loc) {
+  assert(isa<FunctionDecl>(SemaRef.CurContext) && "not in a function scope");
+  auto *FD = cast<FunctionDecl>(SemaRef.CurContext);
 
-  auto *ScopeInfo = getCurFunction();
+  auto *ScopeInfo = SemaRef.getCurFunction();
   if (!ScopeInfo->CoroutineParameterMoves.empty())
     return false;
 
@@ -1883,7 +1886,7 @@ bool Sema::buildCoroutineParameterMoves(SourceLocation 
Loc) {
     bool DeclReferenced = PD->isReferenced();
 
     ExprResult PDRefExpr =
-        BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
+        SemaRef.BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
                          ExprValueKind::VK_LValue, Loc); // FIXME: scope?
 
     PD->setReferenced(DeclReferenced);
@@ -1894,17 +1897,17 @@ bool Sema::buildCoroutineParameterMoves(SourceLocation 
Loc) {
     Expr *CExpr = nullptr;
     if (PD->getType()->getAsCXXRecordDecl() ||
         PD->getType()->isRValueReferenceType())
-      CExpr = castForMoving(*this, PDRefExpr.get());
+      CExpr = castForMoving(SemaRef, PDRefExpr.get());
     else
       CExpr = PDRefExpr.get();
     // [dcl.fct.def.coroutine]p13
     //   The initialization and destruction of each parameter copy occurs in 
the
     //   context of the called coroutine.
-    auto *D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
-    AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
+    auto *D = buildVarDecl(SemaRef, Loc, PD->getType(), PD->getIdentifier());
+    SemaRef.AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
 
     // Convert decl to a statement.
-    StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc, Loc);
+    StmtResult Stmt = SemaRef.ActOnDeclStmt(SemaRef.ConvertDeclToDeclGroup(D), 
Loc, Loc);
     if (Stmt.isInvalid())
       return false;
 
@@ -1913,24 +1916,24 @@ bool Sema::buildCoroutineParameterMoves(SourceLocation 
Loc) {
   return true;
 }
 
-StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
-  CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args);
+StmtResult SemaCoroutine::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs 
Args) {
+  CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(SemaRef.Context, Args);
   if (!Res)
     return StmtError();
   return Res;
 }
 
-ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
+ClassTemplateDecl *SemaCoroutine::lookupCoroutineTraits(SourceLocation KwLoc,
                                                SourceLocation FuncLoc) {
   if (StdCoroutineTraitsCache)
     return StdCoroutineTraitsCache;
 
   IdentifierInfo const &TraitIdent =
-      PP.getIdentifierTable().get("coroutine_traits");
+      SemaRef.PP.getIdentifierTable().get("coroutine_traits");
 
-  NamespaceDecl *StdSpace = getStdNamespace();
-  LookupResult Result(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
-  bool Found = StdSpace && LookupQualifiedName(Result, StdSpace);
+  NamespaceDecl *StdSpace = SemaRef.getStdNamespace();
+  LookupResult Result(SemaRef, &TraitIdent, FuncLoc, Sema::LookupOrdinaryName);
+  bool Found = StdSpace && SemaRef.LookupQualifiedName(Result, StdSpace);
 
   if (!Found) {
     // The goggles, we found nothing!
@@ -1950,3 +1953,16 @@ ClassTemplateDecl 
*Sema::lookupCoroutineTraits(SourceLocation KwLoc,
 
   return StdCoroutineTraitsCache;
 }
+
+void SemaCoroutine::CheckCoroutineWrapper(FunctionDecl *FD) {
+  RecordDecl *RD = FD->getReturnType()->getAsRecordDecl();
+  if (!RD || !RD->getUnderlyingDecl()->hasAttr<CoroReturnTypeAttr>())
+    return;
+  // Allow some_promise_type::get_return_object().
+  if (SemaRef.CanBeGetReturnObject(FD) || 
SemaRef.CanBeGetReturnTypeOnAllocFailure(FD))
+    return;
+  if (!FD->hasAttr<CoroWrapperAttr>())
+    Diag(FD->getLocation(), diag::err_coroutine_return_type) << RD;
+}
+
+SemaCoroutine::SemaCoroutine(Sema &S) : SemaBase(S), 
StdCoroutineTraitsCache(nullptr) {}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f2b9202255cd4..993ecd95ea67c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -46,6 +46,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
@@ -15989,17 +15990,6 @@ bool Sema::CanBeGetReturnTypeOnAllocFailure(const 
FunctionDecl *FD) {
          methodHasName(FD, "get_return_object_on_allocation_failure");
 }
 
-void Sema::CheckCoroutineWrapper(FunctionDecl *FD) {
-  RecordDecl *RD = FD->getReturnType()->getAsRecordDecl();
-  if (!RD || !RD->getUnderlyingDecl()->hasAttr<CoroReturnTypeAttr>())
-    return;
-  // Allow some_promise_type::get_return_object().
-  if (CanBeGetReturnObject(FD) || CanBeGetReturnTypeOnAllocFailure(FD))
-    return;
-  if (!FD->hasAttr<CoroWrapperAttr>())
-    Diag(FD->getLocation(), diag::err_coroutine_return_type) << RD;
-}
-
 Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
                                     bool IsInstantiation) {
   FunctionScopeInfo *FSI = getCurFunction();
@@ -16014,9 +16004,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt 
*Body,
   // If we skip function body, we can't tell if a function is a coroutine.
   if (getLangOpts().Coroutines && FD && !FD->hasSkippedBody()) {
     if (FSI->isCoroutine())
-      CheckCompletedCoroutineBody(FD, Body);
+      Coroutine().CheckCompletedCoroutineBody(FD, Body);
     else
-      CheckCoroutineWrapper(FD);
+      Coroutine().CheckCoroutineWrapper(FD);
   }
 
   {
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 57465d4a77ac2..c973c316f6c3b 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -2391,7 +2392,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(
   // Build the coroutine state immediately and not later during template
   // instantiation
   if (!CoawaitLoc.isInvalid()) {
-    if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await")) {
+    if (!Coroutine().ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await")) {
       ActOnInitializerError(LoopVar);
       return StmtError();
     }
@@ -2473,7 +2474,7 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, 
Expr *EndRange,
       // FIXME: getCurScope() should not be used during template instantiation.
       // We should pick up the set of unqualified lookup results for operator
       // co_await during the initial parse.
-      *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,
+      *BeginExpr = SemaRef.Coroutine().ActOnCoawaitExpr(SemaRef.getCurScope(), 
ColonLoc,
                                             BeginExpr->get());
       if (BeginExpr->isInvalid())
         return Sema::FRS_DiagnosticIssued;
@@ -2705,7 +2706,7 @@ StmtResult Sema::BuildCXXForRangeStmt(
       // begin-expr is __range.
       BeginExpr = BeginRangeRef;
       if (!CoawaitLoc.isInvalid()) {
-        BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get());
+        BeginExpr = Coroutine().ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get());
         if (BeginExpr.isInvalid())
           return StmtError();
       }
@@ -2898,7 +2899,7 @@ StmtResult Sema::BuildCXXForRangeStmt(
       // FIXME: getCurScope() should not be used during template instantiation.
       // We should pick up the set of unqualified lookup results for operator
       // co_await during the initial parse.
-      IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
+      IncrExpr = Coroutine().ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
     if (!IncrExpr.isInvalid())
       IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false);
     if (IncrExpr.isInvalid()) {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 29444f0edc2ae..504c5d6c62ebe 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -37,6 +37,7 @@
 #include "clang/Sema/Ownership.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
@@ -1549,7 +1550,7 @@ class TreeTransform {
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result,
                                  bool IsImplicit) {
-    return getSema().BuildCoreturnStmt(CoreturnLoc, Result, IsImplicit);
+    return getSema().Coroutine().BuildCoreturnStmt(CoreturnLoc, Result, 
IsImplicit);
   }
 
   /// Build a new co_await expression.
@@ -1566,17 +1567,17 @@ class TreeTransform {
     // For an implicit coawait-expr, we need to rebuild the "operator
     // coawait" but not await_transform(), so use BuildResolvedCoawaitExpr().
     // This mirrors how the implicit CoawaitExpr is originally created
-    // in Sema::ActOnCoroutineBodyStart().
+    // in SemaCoroutine::ActOnCoroutineBodyStart().
     if (IsImplicit) {
-      ExprResult Suspend = getSema().BuildOperatorCoawaitCall(
+      ExprResult Suspend = getSema().Coroutine().BuildOperatorCoawaitCall(
           CoawaitLoc, Operand, OpCoawaitLookup);
       if (Suspend.isInvalid())
         return ExprError();
-      return getSema().BuildResolvedCoawaitExpr(CoawaitLoc, Operand,
+      return getSema().Coroutine().BuildResolvedCoawaitExpr(CoawaitLoc, 
Operand,
                                                 Suspend.get(), true);
     }
 
-    return getSema().BuildUnresolvedCoawaitExpr(CoawaitLoc, Operand,
+    return getSema().Coroutine().BuildUnresolvedCoawaitExpr(CoawaitLoc, 
Operand,
                                                 OpCoawaitLookup);
   }
 
@@ -1587,7 +1588,7 @@ class TreeTransform {
   ExprResult RebuildDependentCoawaitExpr(SourceLocation CoawaitLoc,
                                          Expr *Result,
                                          UnresolvedLookupExpr *Lookup) {
-    return getSema().BuildUnresolvedCoawaitExpr(CoawaitLoc, Result, Lookup);
+    return getSema().Coroutine().BuildUnresolvedCoawaitExpr(CoawaitLoc, 
Result, Lookup);
   }
 
   /// Build a new co_yield expression.
@@ -1595,11 +1596,11 @@ class TreeTransform {
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildCoyieldExpr(SourceLocation CoyieldLoc, Expr *Result) {
-    return getSema().BuildCoyieldExpr(CoyieldLoc, Result);
+    return getSema().Coroutine().BuildCoyieldExpr(CoyieldLoc, Result);
   }
 
   StmtResult RebuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
-    return getSema().BuildCoroutineBodyStmt(Args);
+    return getSema().Coroutine().BuildCoroutineBodyStmt(Args);
   }
 
   /// Build a new Objective-C \@try statement.
@@ -8349,9 +8350,9 @@ 
TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
   // before attempting to transform the other parts of the coroutine body
   // statement, such as the implicit suspend statements (because those
   // statements reference the FunctionScopeInfo::CoroutinePromise).
-  if (!SemaRef.buildCoroutineParameterMoves(FD->getLocation()))
+  if (!SemaRef.Coroutine().buildCoroutineParameterMoves(FD->getLocation()))
     return StmtError();
-  auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation());
+  auto *Promise = SemaRef.Coroutine().buildCoroutinePromise(FD->getLocation());
   if (!Promise)
     return StmtError();
   getDerived().transformedLocalDecl(S->getPromiseDecl(), {Promise});
@@ -8366,7 +8367,7 @@ 
TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
   StmtResult FinalSuspend =
       getDerived().TransformStmt(S->getFinalSuspendStmt());
   if (FinalSuspend.isInvalid() ||
-      !SemaRef.checkFinalSuspendNoThrow(FinalSuspend.get()))
+      !SemaRef.Coroutine().checkFinalSuspendNoThrow(FinalSuspend.get()))
     return StmtError();
   ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
   assert(isa<Expr>(InitSuspend.get()) && isa<Expr>(FinalSuspend.get()));
@@ -8480,7 +8481,7 @@ ExprResult 
TreeTransform<Derived>::TransformCoawaitExpr(CoawaitExpr *E) {
   // FIXME: getCurScope() should not be used during template instantiation.
   // We should pick up the set of unqualified lookup results for operator
   // co_await during the initial parse.
-  ExprResult Lookup = getSema().BuildOperatorCoawaitLookupExpr(
+  ExprResult Lookup = getSema().Coroutine().BuildOperatorCoawaitLookupExpr(
       getSema().getCurScope(), E->getKeywordLoc());
 
   // Always rebuild; we don't know if this needs to be injected into a new

>From 18d933dd059e4908f1aa08d96af76664ddc753da Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com>
Date: Sat, 18 May 2024 13:33:51 +0300
Subject: [PATCH 2/3] Run clang-format

---
 clang/include/clang/Sema/SemaCoroutine.h |   2 +-
 clang/lib/Parse/ParseExpr.cpp            |   3 +-
 clang/lib/Parse/ParseStmt.cpp            |   3 +-
 clang/lib/Sema/Sema.cpp                  |   6 +-
 clang/lib/Sema/SemaCoroutine.cpp         | 105 +++++++++++++----------
 clang/lib/Sema/SemaStmt.cpp              |   4 +-
 clang/lib/Sema/TreeTransform.h           |  12 +--
 7 files changed, 78 insertions(+), 57 deletions(-)

diff --git a/clang/include/clang/Sema/SemaCoroutine.h 
b/clang/include/clang/Sema/SemaCoroutine.h
index 20f1fffc970f8..d4ca6cb0d860a 100644
--- a/clang/include/clang/Sema/SemaCoroutine.h
+++ b/clang/include/clang/Sema/SemaCoroutine.h
@@ -22,8 +22,8 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Sema/Ownership.h"
-#include "clang/Sema/SemaBase.h"
 #include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaBase.h"
 
 namespace clang {
 class SemaCoroutine : public SemaBase {
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index e8b0e42466aab..98471ea0ea1a7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1466,7 +1466,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
     SourceLocation CoawaitLoc = ConsumeToken();
     Res = ParseCastExpression(AnyCastExpr);
     if (!Res.isInvalid())
-      Res = Actions.Coroutine().ActOnCoawaitExpr(getCurScope(), CoawaitLoc, 
Res.get());
+      Res = Actions.Coroutine().ActOnCoawaitExpr(getCurScope(), CoawaitLoc,
+                                                 Res.get());
     return Res;
   }
 
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 8ebce6bc726d3..f07bc2690fa35 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2457,7 +2457,8 @@ StmtResult Parser::ParseReturnStatement() {
     }
   }
   if (IsCoreturn)
-    return Actions.Coroutine().ActOnCoreturnStmt(getCurScope(), ReturnLoc, 
R.get());
+    return Actions.Coroutine().ActOnCoreturnStmt(getCurScope(), ReturnLoc,
+                                                 R.get());
   return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
 }
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f218d3e39eb70..df71673548fb9 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -43,8 +43,8 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaCodeCompletion.h"
-#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaConsumer.h"
+#include "clang/Sema/SemaCoroutine.h"
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
@@ -221,8 +221,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer 
&consumer,
       CodeSegStack(nullptr), StrictGuardStackCheckStack(false),
       FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr),
       VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
-      IdResolver(pp),
-      OriginalLexicalContext(nullptr), StdInitializerList(nullptr),
+      IdResolver(pp), OriginalLexicalContext(nullptr),
+      StdInitializerList(nullptr),
       FullyCheckedComparisonCategories(
           static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
       StdSourceLocationImplDecl(nullptr), CXXTypeInfoDecl(nullptr),
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index efca77c78428b..f59e6a7c2b6a8 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -251,8 +251,9 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation 
Loc,
 
 /// Build a call to 'operator co_await' if there is a suitable operator for
 /// the given expression.
-ExprResult SemaCoroutine::BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
-                                          UnresolvedLookupExpr *Lookup) {
+ExprResult
+SemaCoroutine::BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
+                                        UnresolvedLookupExpr *Lookup) {
   UnresolvedSet<16> Functions;
   Functions.append(Lookup->decls_begin(), Lookup->decls_end());
   return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
@@ -263,8 +264,8 @@ static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, 
Scope *S,
   ExprResult R = SemaRef.Coroutine().BuildOperatorCoawaitLookupExpr(S, Loc);
   if (R.isInvalid())
     return ExprError();
-  return SemaRef.Coroutine().BuildOperatorCoawaitCall(Loc, E,
-                                          cast<UnresolvedLookupExpr>(R.get()));
+  return SemaRef.Coroutine().BuildOperatorCoawaitCall(
+      Loc, E, cast<UnresolvedLookupExpr>(R.get()));
 }
 
 static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
@@ -494,9 +495,10 @@ VarDecl 
*SemaCoroutine::buildCoroutinePromise(SourceLocation Loc) {
   if (T.isNull())
     return nullptr;
 
-  auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
-                             
&SemaRef.PP.getIdentifierTable().get("__promise"), T,
-                             Context.getTrivialTypeSourceInfo(T, Loc), 
SC_None);
+  auto *VD =
+      VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
+                      &SemaRef.PP.getIdentifierTable().get("__promise"), T,
+                      Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
   VD->setImplicit();
   SemaRef.CheckVariableDeclarationType(VD);
   if (VD->isInvalidDecl())
@@ -535,9 +537,9 @@ VarDecl 
*SemaCoroutine::buildCoroutinePromise(SourceLocation Loc) {
     // frame, use that reference.
     auto *MoveDecl =
         cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
-    RefExpr =
-        SemaRef.BuildDeclRefExpr(MoveDecl, 
MoveDecl->getType().getNonReferenceType(),
-                         ExprValueKind::VK_LValue, FD->getLocation());
+    RefExpr = SemaRef.BuildDeclRefExpr(
+        MoveDecl, MoveDecl->getType().getNonReferenceType(),
+        ExprValueKind::VK_LValue, FD->getLocation());
     if (RefExpr.isInvalid())
       return nullptr;
     CtorArgExprs.push_back(RefExpr.get());
@@ -688,7 +690,7 @@ bool SemaCoroutine::checkFinalSuspendNoThrow(const Stmt 
*FinalSuspend) {
 }
 
 bool SemaCoroutine::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
-                                   StringRef Keyword) {
+                                            StringRef Keyword) {
   // Ignore previous expr evaluation contexts.
   EnterExpressionEvaluationContext PotentiallyEvaluated(
       SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
@@ -718,7 +720,8 @@ bool SemaCoroutine::ActOnCoroutineBodyStart(Scope *SC, 
SourceLocation KWLoc,
       return StmtError();
     Suspend = BuildResolvedCoawaitExpr(Loc, Operand.get(), Suspend.get(),
                                        /*IsImplicit*/ true);
-    Suspend = SemaRef.ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ 
false);
+    Suspend =
+        SemaRef.ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
     if (Suspend.isInvalid()) {
       Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
           << ((Name == "initial_suspend") ? 0 : 1);
@@ -790,7 +793,8 @@ static bool checkSuspensionContext(Sema &S, SourceLocation 
Loc,
   return true;
 }
 
-ExprResult SemaCoroutine::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr 
*E) {
+ExprResult SemaCoroutine::ActOnCoawaitExpr(Scope *S, SourceLocation Loc,
+                                           Expr *E) {
   if (!checkSuspensionContext(SemaRef, Loc, "co_await"))
     return ExprError();
 
@@ -811,7 +815,8 @@ ExprResult SemaCoroutine::ActOnCoawaitExpr(Scope *S, 
SourceLocation Loc, Expr *E
                                    cast<UnresolvedLookupExpr>(Lookup.get()));
 }
 
-ExprResult SemaCoroutine::BuildOperatorCoawaitLookupExpr(Scope *S, 
SourceLocation Loc) {
+ExprResult SemaCoroutine::BuildOperatorCoawaitLookupExpr(Scope *S,
+                                                         SourceLocation Loc) {
   DeclarationName OpName =
       SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
   LookupResult Operators(SemaRef, OpName, SourceLocation(),
@@ -830,8 +835,9 @@ ExprResult 
SemaCoroutine::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocatio
 
 // Attempts to resolve and build a CoawaitExpr from "raw" inputs, bailing out 
to
 // DependentCoawaitExpr if needed.
-ExprResult SemaCoroutine::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr 
*Operand,
-                                            UnresolvedLookupExpr *Lookup) {
+ExprResult
+SemaCoroutine::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *Operand,
+                                          UnresolvedLookupExpr *Lookup) {
   auto *FSI = checkCoroutineContext(SemaRef, Loc, "co_await");
   if (!FSI)
     return ExprError();
@@ -870,8 +876,9 @@ ExprResult 
SemaCoroutine::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *O
   return BuildResolvedCoawaitExpr(Loc, Operand, Awaiter.get());
 }
 
-ExprResult SemaCoroutine::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr 
*Operand,
-                                          Expr *Awaiter, bool IsImplicit) {
+ExprResult SemaCoroutine::BuildResolvedCoawaitExpr(SourceLocation Loc,
+                                                   Expr *Operand, Expr 
*Awaiter,
+                                                   bool IsImplicit) {
   auto *Coroutine = checkCoroutineContext(SemaRef, Loc, "co_await", 
IsImplicit);
   if (!Coroutine)
     return ExprError();
@@ -883,15 +890,16 @@ ExprResult 
SemaCoroutine::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *Ope
   }
 
   if (Awaiter->getType()->isDependentType()) {
-    Expr *Res = new (SemaRef.Context)
-        CoawaitExpr(Loc, SemaRef.Context.DependentTy, Operand, Awaiter, 
IsImplicit);
+    Expr *Res = new (SemaRef.Context) CoawaitExpr(
+        Loc, SemaRef.Context.DependentTy, Operand, Awaiter, IsImplicit);
     return Res;
   }
 
   // If the expression is a temporary, materialize it as an lvalue so that we
   // can use it multiple times.
   if (Awaiter->isPRValue())
-    Awaiter = SemaRef.CreateMaterializeTemporaryExpr(Awaiter->getType(), 
Awaiter, true);
+    Awaiter = SemaRef.CreateMaterializeTemporaryExpr(Awaiter->getType(),
+                                                     Awaiter, true);
 
   // The location of the `co_await` token cannot be used when constructing
   // the member call expressions since it's before the location of `Expr`, 
which
@@ -911,7 +919,8 @@ ExprResult 
SemaCoroutine::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *Ope
   return Res;
 }
 
-ExprResult SemaCoroutine::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr 
*E) {
+ExprResult SemaCoroutine::ActOnCoyieldExpr(Scope *S, SourceLocation Loc,
+                                           Expr *E) {
   if (!checkSuspensionContext(SemaRef, Loc, "co_yield"))
     return ExprError();
 
@@ -921,8 +930,9 @@ ExprResult SemaCoroutine::ActOnCoyieldExpr(Scope *S, 
SourceLocation Loc, Expr *E
   }
 
   // Build yield_value call.
-  ExprResult Awaitable = buildPromiseCall(
-      SemaRef, SemaRef.getCurFunction()->CoroutinePromise, Loc, "yield_value", 
E);
+  ExprResult Awaitable =
+      buildPromiseCall(SemaRef, SemaRef.getCurFunction()->CoroutinePromise, 
Loc,
+                       "yield_value", E);
   if (Awaitable.isInvalid())
     return ExprError();
 
@@ -947,7 +957,8 @@ ExprResult SemaCoroutine::BuildCoyieldExpr(SourceLocation 
Loc, Expr *E) {
   Expr *Operand = E;
 
   if (E->getType()->isDependentType()) {
-    Expr *Res = new (SemaRef.Context) CoyieldExpr(Loc, 
SemaRef.Context.DependentTy, Operand, E);
+    Expr *Res = new (SemaRef.Context)
+        CoyieldExpr(Loc, SemaRef.Context.DependentTy, Operand, E);
     return Res;
   }
 
@@ -957,19 +968,20 @@ ExprResult SemaCoroutine::BuildCoyieldExpr(SourceLocation 
Loc, Expr *E) {
     E = SemaRef.CreateMaterializeTemporaryExpr(E->getType(), E, true);
 
   // Build the await_ready, await_suspend, await_resume calls.
-  ReadySuspendResumeResult RSS = buildCoawaitCalls(
-      SemaRef, Coroutine->CoroutinePromise, Loc, E);
+  ReadySuspendResumeResult RSS =
+      buildCoawaitCalls(SemaRef, Coroutine->CoroutinePromise, Loc, E);
   if (RSS.IsInvalid)
     return ExprError();
 
-  Expr *Res =
-      new (SemaRef.Context) CoyieldExpr(Loc, Operand, E, RSS.Results[0], 
RSS.Results[1],
-                                RSS.Results[2], RSS.OpaqueValue);
+  Expr *Res = new (SemaRef.Context)
+      CoyieldExpr(Loc, Operand, E, RSS.Results[0], RSS.Results[1],
+                  RSS.Results[2], RSS.OpaqueValue);
 
   return Res;
 }
 
-StmtResult SemaCoroutine::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr 
*E) {
+StmtResult SemaCoroutine::ActOnCoreturnStmt(Scope *S, SourceLocation Loc,
+                                            Expr *E) {
   if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
     SemaRef.CorrectDelayedTyposInExpr(E);
     return StmtError();
@@ -978,7 +990,7 @@ StmtResult SemaCoroutine::ActOnCoreturnStmt(Scope *S, 
SourceLocation Loc, Expr *
 }
 
 StmtResult SemaCoroutine::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
-                                   bool IsImplicit) {
+                                            bool IsImplicit) {
   auto *FSI = checkCoroutineContext(SemaRef, Loc, "co_return", IsImplicit);
   if (!FSI)
     return StmtError();
@@ -1002,7 +1014,8 @@ StmtResult 
SemaCoroutine::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
   if (PC.isInvalid())
     return StmtError();
 
-  Expr *PCE = SemaRef.ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ 
false).get();
+  Expr *PCE =
+      SemaRef.ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
 
   Stmt *Res = new (SemaRef.Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
   return Res;
@@ -1089,7 +1102,6 @@ static bool findDeleteForPromise(Sema &S, SourceLocation 
Loc, QualType PromiseTy
   return true;
 }
 
-
 void SemaCoroutine::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) 
{
   FunctionScopeInfo *Fn = SemaRef.getCurFunction();
   assert(Fn && Fn->isCoroutine() && "not a coroutine");
@@ -1660,7 +1672,7 @@ bool CoroutineStmtBuilder::makeOnFallthrough() {
       return false;
   } else if (HasRVoid) {
     Fallthrough = S.Coroutine().BuildCoreturnStmt(FD.getLocation(), nullptr,
-                                      /*IsImplicit=*/true);
+                                                  /*IsImplicit=*/true);
     Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
     if (Fallthrough.isInvalid())
       return false;
@@ -1885,9 +1897,9 @@ bool 
SemaCoroutine::buildCoroutineParameterMoves(SourceLocation Loc) {
     // Preserve the referenced state for unused parameter diagnostics.
     bool DeclReferenced = PD->isReferenced();
 
-    ExprResult PDRefExpr =
-        SemaRef.BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
-                         ExprValueKind::VK_LValue, Loc); // FIXME: scope?
+    ExprResult PDRefExpr = SemaRef.BuildDeclRefExpr(
+        PD, PD->getType().getNonReferenceType(), ExprValueKind::VK_LValue,
+        Loc); // FIXME: scope?
 
     PD->setReferenced(DeclReferenced);
 
@@ -1907,7 +1919,8 @@ bool 
SemaCoroutine::buildCoroutineParameterMoves(SourceLocation Loc) {
     SemaRef.AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
 
     // Convert decl to a statement.
-    StmtResult Stmt = SemaRef.ActOnDeclStmt(SemaRef.ConvertDeclToDeclGroup(D), 
Loc, Loc);
+    StmtResult Stmt =
+        SemaRef.ActOnDeclStmt(SemaRef.ConvertDeclToDeclGroup(D), Loc, Loc);
     if (Stmt.isInvalid())
       return false;
 
@@ -1916,15 +1929,17 @@ bool 
SemaCoroutine::buildCoroutineParameterMoves(SourceLocation Loc) {
   return true;
 }
 
-StmtResult SemaCoroutine::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs 
Args) {
+StmtResult
+SemaCoroutine::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
   CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(SemaRef.Context, Args);
   if (!Res)
     return StmtError();
   return Res;
 }
 
-ClassTemplateDecl *SemaCoroutine::lookupCoroutineTraits(SourceLocation KwLoc,
-                                               SourceLocation FuncLoc) {
+ClassTemplateDecl *
+SemaCoroutine::lookupCoroutineTraits(SourceLocation KwLoc,
+                                     SourceLocation FuncLoc) {
   if (StdCoroutineTraitsCache)
     return StdCoroutineTraitsCache;
 
@@ -1959,10 +1974,12 @@ void SemaCoroutine::CheckCoroutineWrapper(FunctionDecl 
*FD) {
   if (!RD || !RD->getUnderlyingDecl()->hasAttr<CoroReturnTypeAttr>())
     return;
   // Allow some_promise_type::get_return_object().
-  if (SemaRef.CanBeGetReturnObject(FD) || 
SemaRef.CanBeGetReturnTypeOnAllocFailure(FD))
+  if (SemaRef.CanBeGetReturnObject(FD) ||
+      SemaRef.CanBeGetReturnTypeOnAllocFailure(FD))
     return;
   if (!FD->hasAttr<CoroWrapperAttr>())
     Diag(FD->getLocation(), diag::err_coroutine_return_type) << RD;
 }
 
-SemaCoroutine::SemaCoroutine(Sema &S) : SemaBase(S), 
StdCoroutineTraitsCache(nullptr) {}
+SemaCoroutine::SemaCoroutine(Sema &S)
+    : SemaBase(S), StdCoroutineTraitsCache(nullptr) {}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index c973c316f6c3b..3e835f86d233a 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2474,8 +2474,8 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, 
Expr *EndRange,
       // FIXME: getCurScope() should not be used during template instantiation.
       // We should pick up the set of unqualified lookup results for operator
       // co_await during the initial parse.
-      *BeginExpr = SemaRef.Coroutine().ActOnCoawaitExpr(SemaRef.getCurScope(), 
ColonLoc,
-                                            BeginExpr->get());
+      *BeginExpr = SemaRef.Coroutine().ActOnCoawaitExpr(
+          SemaRef.getCurScope(), ColonLoc, BeginExpr->get());
       if (BeginExpr->isInvalid())
         return Sema::FRS_DiagnosticIssued;
     }
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 504c5d6c62ebe..fc60532a20a1b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1550,7 +1550,8 @@ class TreeTransform {
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result,
                                  bool IsImplicit) {
-    return getSema().Coroutine().BuildCoreturnStmt(CoreturnLoc, Result, 
IsImplicit);
+    return getSema().Coroutine().BuildCoreturnStmt(CoreturnLoc, Result,
+                                                   IsImplicit);
   }
 
   /// Build a new co_await expression.
@@ -1573,12 +1574,12 @@ class TreeTransform {
           CoawaitLoc, Operand, OpCoawaitLookup);
       if (Suspend.isInvalid())
         return ExprError();
-      return getSema().Coroutine().BuildResolvedCoawaitExpr(CoawaitLoc, 
Operand,
-                                                Suspend.get(), true);
+      return getSema().Coroutine().BuildResolvedCoawaitExpr(
+          CoawaitLoc, Operand, Suspend.get(), true);
     }
 
     return getSema().Coroutine().BuildUnresolvedCoawaitExpr(CoawaitLoc, 
Operand,
-                                                OpCoawaitLookup);
+                                                            OpCoawaitLookup);
   }
 
   /// Build a new co_await expression.
@@ -1588,7 +1589,8 @@ class TreeTransform {
   ExprResult RebuildDependentCoawaitExpr(SourceLocation CoawaitLoc,
                                          Expr *Result,
                                          UnresolvedLookupExpr *Lookup) {
-    return getSema().Coroutine().BuildUnresolvedCoawaitExpr(CoawaitLoc, 
Result, Lookup);
+    return getSema().Coroutine().BuildUnresolvedCoawaitExpr(CoawaitLoc, Result,
+                                                            Lookup);
   }
 
   /// Build a new co_yield expression.

>From f832ccd89a348c490a8475241c996fb6240d109b Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com>
Date: Sat, 18 May 2024 13:44:13 +0300
Subject: [PATCH 3/3] Fix table of contents in `Sema`

---
 clang/include/clang/Sema/Sema.h | 53 ++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 27 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1d0fbeacfe061..20d1dcd0aab97 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -457,34 +457,33 @@ class Sema final : public SemaBase {
   // 4. Availability Attribute Handling (SemaAvailability.cpp)
   // 5. Casts (SemaCast.cpp)
   // 6. Extra Semantic Checking (SemaChecking.cpp)
-  // 7. C++ Coroutines (SemaCoroutine.cpp)
-  // 8. C++ Scope Specifiers (SemaCXXScopeSpec.cpp)
-  // 9. Declarations (SemaDecl.cpp)
-  // 10. Declaration Attribute Handling (SemaDeclAttr.cpp)
-  // 11. C++ Declarations (SemaDeclCXX.cpp)
-  // 12. C++ Exception Specifications (SemaExceptionSpec.cpp)
-  // 13. Expressions (SemaExpr.cpp)
-  // 14. C++ Expressions (SemaExprCXX.cpp)
-  // 15. Member Access Expressions (SemaExprMember.cpp)
-  // 16. Initializers (SemaInit.cpp)
-  // 17. C++ Lambda Expressions (SemaLambda.cpp)
-  // 18. Name Lookup (SemaLookup.cpp)
-  // 19. Modules (SemaModule.cpp)
-  // 20. C++ Overloading (SemaOverload.cpp)
-  // 21. Pseudo-Object (SemaPseudoObject.cpp)
-  // 22. Statements (SemaStmt.cpp)
-  // 23. `inline asm` Statement (SemaStmtAsm.cpp)
-  // 24. Statement Attribute Handling (SemaStmtAttr.cpp)
-  // 25. C++ Templates (SemaTemplate.cpp)
-  // 26. C++ Template Argument Deduction (SemaTemplateDeduction.cpp)
-  // 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp)
-  // 28. C++ Template Declaration Instantiation
+  // 7. C++ Scope Specifiers (SemaCXXScopeSpec.cpp)
+  // 8. Declarations (SemaDecl.cpp)
+  // 9. Declaration Attribute Handling (SemaDeclAttr.cpp)
+  // 10. C++ Declarations (SemaDeclCXX.cpp)
+  // 11. C++ Exception Specifications (SemaExceptionSpec.cpp)
+  // 12. Expressions (SemaExpr.cpp)
+  // 13. C++ Expressions (SemaExprCXX.cpp)
+  // 14. Member Access Expressions (SemaExprMember.cpp)
+  // 15. Initializers (SemaInit.cpp)
+  // 16. C++ Lambda Expressions (SemaLambda.cpp)
+  // 17. Name Lookup (SemaLookup.cpp)
+  // 18. Modules (SemaModule.cpp)
+  // 19. C++ Overloading (SemaOverload.cpp)
+  // 20. Pseudo-Object (SemaPseudoObject.cpp)
+  // 21. Statements (SemaStmt.cpp)
+  // 22. `inline asm` Statement (SemaStmtAsm.cpp)
+  // 23. Statement Attribute Handling (SemaStmtAttr.cpp)
+  // 24. C++ Templates (SemaTemplate.cpp)
+  // 25. C++ Template Argument Deduction (SemaTemplateDeduction.cpp)
+  // 26. C++ Template Instantiation (SemaTemplateInstantiate.cpp)
+  // 27. C++ Template Declaration Instantiation
   //     (SemaTemplateInstantiateDecl.cpp)
-  // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp)
-  // 30. Constraints and Concepts (SemaConcept.cpp)
-  // 31. Types (SemaType.cpp)
-  // 32. FixIt Helpers (SemaFixItUtils.cpp)
-  // 33. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp)
+  // 28. C++ Variadic Templates (SemaTemplateVariadic.cpp)
+  // 29. Constraints and Concepts (SemaConcept.cpp)
+  // 30. Types (SemaType.cpp)
+  // 31. FixIt Helpers (SemaFixItUtils.cpp)
+  // 32. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp)
 
   /// \name Semantic Analysis
   /// Implementations are in Sema.cpp

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to