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