llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-coroutines Author: Vlad Serebrennikov (Endilll) <details> <summary>Changes</summary> This patch moves coroutines-specific `Sema` functions into the new `SemaCoroutine` class. This continues previous efforts to split `Sema` up. Additional context can be found in #<!-- -->84184. As usual, in order to help reviewing this, formatting changes are split into a separate commit. --- Patch is 48.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92645.diff 10 Files Affected: - (modified) clang/include/clang/Sema/Sema.h (+7-51) - (added) clang/include/clang/Sema/SemaCoroutine.h (+73) - (modified) clang/lib/Parse/ParseExpr.cpp (+3-1) - (modified) clang/lib/Parse/ParseExprCXX.cpp (+2-1) - (modified) clang/lib/Parse/ParseStmt.cpp (+3-1) - (modified) clang/lib/Sema/Sema.cpp (+4-2) - (modified) clang/lib/Sema/SemaCoroutine.cpp (+153-120) - (modified) clang/lib/Sema/SemaDecl.cpp (+3-13) - (modified) clang/lib/Sema/SemaStmt.cpp (+6-5) - (modified) clang/lib/Sema/TreeTransform.h (+17-14) ``````````diff 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..d4ca6cb0d860a --- /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/Scope.h" +#include "clang/Sema/SemaBase.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..98471ea0ea1a7 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,8 @@ 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..f07bc2690fa35 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,8 @@ 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..df71673548fb9 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -44,6 +44,7 @@ #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaCodeCompletion.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" @@ -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,8 +221,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CodeSegStack(nullptr), StrictGuardStackCheckStack(false), FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr), VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr), - StdCoroutineTraitsCache(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 81334c817b2af..f59e6a7c2b6a8 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,20 +251,21 @@ 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, - UnresolvedLookupExpr *Lookup) { +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, - cast<UnresolvedLookupExpr>(R.get())); + return SemaRef.Coroutine().BuildOperatorCoawaitCall( + Loc, E, cast<UnresolvedLookupExpr>(R.get())); } static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, @@ -475,9 +478,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 +491,20 @@ 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, - 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(); - 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 +513,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()); @@ -532,9 +537,9 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { // frame, use that reference. auto *MoveDecl = cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl()); - RefExpr = - 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()); @@ -550,7 +555,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 +566,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 +601,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 +671,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 +689,14 @@ bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) { return ThrowingDecls.empty(); } -bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, - StringRef Keyword) { +bool SemaCoroutine::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, + StringRef Keyword) { // Ignore previous expr evaluation contexts. EnterExpressionEvaluationContext PotentiallyEvaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - if (!checkCoroutin... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/92645 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits