Go to the documentation of this file.
27 #include "llvm/ADT/SmallSet.h"
29 using namespace clang;
74 if (
auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
75 if (MD->isInstance()) {
99 diag::err_coroutine_type_missing_specialization))
103 assert(RD &&
"specialization of class template is not a class?");
112 diag::err_implied_std_coroutine_traits_promise_type_not_found)
119 auto buildElaboratedType = [&]() {
128 diag::err_implied_std_coroutine_traits_promise_type_not_class)
129 << buildElaboratedType();
133 diag::err_coroutine_promise_type_incomplete))
146 assert(CoroNamespace &&
"Should already be diagnosed");
151 S.
Diag(Loc, diag::err_implied_coroutine_type_not_found)
152 <<
"std::coroutine_handle";
158 Result.suppressDiagnostics();
161 S.
Diag(Found->
getLocation(), diag::err_malformed_std_coroutine_handle);
174 if (CoroHandleType.
isNull())
177 diag::err_coroutine_type_missing_specialization))
180 return CoroHandleType;
191 auto *FD = dyn_cast<FunctionDecl>(S.
CurContext);
194 ? diag::err_coroutine_objc_method
195 : diag::err_coroutine_outside_function) << Keyword;
201 enum InvalidFuncDiag {
210 bool Diagnosed =
false;
211 auto DiagInvalid = [&](InvalidFuncDiag
ID) {
212 S.
Diag(Loc, diag::err_coroutine_invalid_func_context) <<
ID << Keyword;
219 auto *MD = dyn_cast<CXXMethodDecl>(FD);
221 if (MD && isa<CXXConstructorDecl>(MD))
222 return DiagInvalid(DiagCtor);
224 else if (MD && isa<CXXDestructorDecl>(MD))
225 return DiagInvalid(DiagDtor);
227 else if (FD->isMain())
228 return DiagInvalid(DiagMain);
234 if (FD->isConstexpr())
235 DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);
238 if (FD->getReturnType()->isUndeducedType())
239 DiagInvalid(DiagAutoRet);
243 if (FD->isVariadic())
244 DiagInvalid(DiagVarargs);
255 return CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
264 cast<UnresolvedLookupExpr>(R.
get()));
270 if (CoroHandleType.
isNull())
277 S.
Diag(Loc, diag::err_coroutine_handle_missing_member)
308 Base,
Base->getType(), Loc,
false, SS,
311 if (Result.isInvalid())
315 if (
auto *TE = dyn_cast<TypoExpr>(Result.get())) {
317 S.
Diag(Loc, diag::err_no_member)
318 << NameInfo.
getName() <<
Base->getType()->getAsCXXRecordDecl()
319 <<
Base->getSourceRange();
323 return S.
BuildCallExpr(
nullptr, Result.get(), Loc, Args, Loc,
nullptr);
346 Expr *JustAddress = AddressExpr.
get();
350 S.
Diag(cast<CallExpr>(JustAddress)->getCalleeDecl()->getLocation(),
351 diag::warn_coroutine_handle_address_invalid_return_type)
387 auto BuildSubExpr = [&](ACT CallType, StringRef Func,
390 if (Result.isInvalid()) {
394 Calls.
Results[CallType] = Result.get();
399 cast_or_null<CallExpr>(BuildSubExpr(ACT::ACT_Ready,
"await_ready", None));
409 diag::note_await_ready_no_bool_conversion);
410 S.
Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
423 Expr *CoroHandle = CoroHandleRes.
get();
424 CallExpr *AwaitSuspend = cast_or_null<CallExpr>(
425 BuildSubExpr(ACT::ACT_Suspend,
"await_suspend", CoroHandle));
436 if (
Expr *TailCallSuspend =
443 Calls.
Results[ACT::ACT_Suspend] = TailCallSuspend;
449 diag::err_await_suspend_invalid_return_type)
451 S.
Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
455 Calls.
Results[ACT::ACT_Suspend] =
460 BuildSubExpr(ACT::ACT_Resume,
"await_resume", None);
482 assert(isa<FunctionDecl>(CurContext) &&
"not in a function scope");
483 auto *FD = cast<FunctionDecl>(CurContext);
484 bool IsThisDependentType = [&] {
485 if (
auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD))
486 return MD->isInstance() && MD->getThisType()->isDependentType();
497 auto *VD =
VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
498 &PP.getIdentifierTable().get(
"__promise"), T,
501 CheckVariableDeclarationType(VD);
502 if (VD->isInvalidDecl())
505 auto *ScopeInfo = getCurFunction();
512 if (
auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
517 ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.
get());
520 CtorArgExprs.push_back(ThisExpr.
get());
525 auto &Moves = ScopeInfo->CoroutineParameterMoves;
526 for (
auto *PD : FD->parameters()) {
527 if (PD->getType()->isDependentType())
531 auto Move = Moves.find(PD);
532 assert(
Move != Moves.end() &&
533 "Coroutine function parameter not inserted into move map");
537 cast<VarDecl>(cast<DeclStmt>(
Move->second)->getSingleDecl());
539 BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
541 if (RefExpr.isInvalid())
543 CtorArgExprs.push_back(RefExpr.get());
548 if (!CtorArgExprs.empty()) {
552 CtorArgExprs, FD->getLocation());
555 VD->getLocation(),
true, PLE);
568 if (Result.isInvalid()) {
569 VD->setInvalidDecl();
570 }
else if (Result.get()) {
571 VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
573 CheckCompleteVariableDeclaration(VD);
576 ActOnUninitializedDecl(VD);
578 ActOnUninitializedDecl(VD);
587 bool IsImplicit =
false) {
591 assert(isa<FunctionDecl>(S.
CurContext) &&
"not in a function scope");
594 assert(ScopeInfo &&
"missing function scope for function");
596 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
597 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
599 if (ScopeInfo->CoroutinePromise)
606 if (!ScopeInfo->CoroutinePromise)
616 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {
617 auto checkDeclNoexcept = [&](
const Decl *D,
bool IsDtor =
false) {
621 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
629 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)
632 if (ThrowingDecls.empty()) {
639 diag::err_coroutine_promise_final_suspend_requires_nothrow);
641 ThrowingDecls.insert(D);
645 if (
auto *CE = dyn_cast<CXXConstructExpr>(E)) {
647 checkDeclNoexcept(Ctor);
650 }
else if (
auto *CE = dyn_cast<CallExpr>(E)) {
651 if (CE->isTypeDependent())
654 checkDeclNoexcept(CE->getCalleeDecl());
658 QualType::DestructionKind::DK_cxx_destructor) {
661 checkDeclNoexcept(cast<CXXRecordDecl>(T->getDecl())->getDestructor(),
665 for (
const auto *Child : E->
children()) {
680 ThrowingDecls.end()};
681 sort(SortedDecls, [](
const Decl *A,
const Decl *B) {
684 for (
const auto *D : SortedDecls) {
685 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
687 return ThrowingDecls.empty();
694 auto *ScopeInfo = getCurFunction();
695 assert(ScopeInfo->CoroutinePromise);
699 if (!ScopeInfo->NeedsCoroutineSuspends)
702 ScopeInfo->setNeedsCoroutineSuspends(
false);
704 auto *Fn = cast<FunctionDecl>(CurContext);
707 auto buildSuspends = [&](StringRef Name)
mutable ->
StmtResult {
710 if (Operand.isInvalid())
716 Suspend = BuildResolvedCoawaitExpr(Loc, Operand.get(), Suspend.
get(),
718 Suspend = ActOnFinishFullExpr(Suspend.
get(),
false);
720 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
721 << ((Name ==
"initial_suspend") ? 0 : 1);
722 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
725 return cast<Stmt>(Suspend.
get());
728 StmtResult InitSuspend = buildSuspends(
"initial_suspend");
732 StmtResult FinalSuspend = buildSuspends(
"final_suspend");
733 if (FinalSuspend.
isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.
get()))
736 ScopeInfo->setCoroutineSuspends(InitSuspend.
get(), FinalSuspend.
get());
758 while (S && !S->isFunctionScope()) {
759 if (S->isCatchScope())
777 S.
Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
781 S.
Diag(Loc, diag::err_coroutine_within_handler) << Keyword;
785 if (!ActOnCoroutineBodyStart(S, Loc,
"co_await")) {
786 CorrectDelayedTyposInExpr(E);
797 ExprResult Lookup = BuildOperatorCoawaitLookupExpr(S, Loc);
800 return BuildUnresolvedCoawaitExpr(Loc, E,
801 cast<UnresolvedLookupExpr>(Lookup.
get()));
809 LookupName(Operators, S);
811 assert(!Operators.
isAmbiguous() &&
"Operator lookup cannot be ambiguous");
814 Functions.size() > 1 ||
815 (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
819 Functions.begin(), Functions.end());
832 if (Operand->hasPlaceholderType()) {
839 auto *Promise = FSI->CoroutinePromise;
840 if (Promise->getType()->isDependentType()) {
841 Expr *Res =
new (Context)
847 auto *Transformed = Operand;
853 diag::note_coroutine_promise_implicit_await_transform_required_here)
854 << Operand->getSourceRange();
857 Transformed = R.
get();
859 ExprResult Awaiter = BuildOperatorCoawaitCall(Loc, Transformed, Lookup);
863 return BuildResolvedCoawaitExpr(Loc, Operand, Awaiter.
get());
867 Expr *Awaiter,
bool IsImplicit) {
879 Expr *Res =
new (Context)
887 Awaiter = CreateMaterializeTemporaryExpr(Awaiter->
getType(), Awaiter,
true);
900 Expr *Res =
new (Context)
908 if (!ActOnCoroutineBodyStart(S, Loc,
"co_yield")) {
909 CorrectDelayedTyposInExpr(E);
917 *
this, getCurFunction()->CoroutinePromise, Loc,
"yield_value", E);
926 return BuildCoyieldExpr(Loc, Awaitable.
get());
949 E = CreateMaterializeTemporaryExpr(E->
getType(), E,
true);
953 *
this, Coroutine->CoroutinePromise, Loc, E);
965 if (!ActOnCoroutineBodyStart(S, Loc,
"co_return")) {
966 CorrectDelayedTyposInExpr(E);
969 return BuildCoreturnStmt(Loc, E);
985 VarDecl *Promise = FSI->CoroutinePromise;
988 getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn);
991 E = MakeFullDiscardedValueExpr(E).get();
997 Expr *PCE = ActOnFinishFullExpr(PC.
get(),
false).get();
1006 assert(
Std &&
"Should already be diagnosed");
1013 S.
Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
1017 auto *VD = Result.getAsSingle<
VarDecl>();
1019 Result.suppressDiagnostics();
1042 assert(PointeeRD &&
"PromiseType must be a CxxRecordDecl type");
1059 if (!OperatorDelete) {
1062 const bool Overaligned =
false;
1064 Overaligned, DeleteName);
1067 return OperatorDelete;
1073 assert(Fn && Fn->
isCoroutine() &&
"not a coroutine");
1076 "a null body is only allowed for invalid declarations");
1084 if (isa<CoroutineBodyStmt>(Body)) {
1094 if (FD->
hasAttr<AlwaysInlineAttr>())
1101 "first coroutine location not set");
1107 if (Builder.isInvalid() || !Builder.buildStatements())
1117 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1118 IsPromiseDependentType(
1119 !Fn.CoroutinePromise ||
1120 Fn.CoroutinePromise->getType()->isDependentType()) {
1124 this->ParamMovesVector.push_back(KV.second);
1127 if (!IsPromiseDependentType) {
1129 assert(PromiseRecordDecl &&
"Type should have already been checked");
1131 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1135 assert(this->IsValid &&
"coroutine already invalid");
1136 this->IsValid = makeReturnObject();
1137 if (this->IsValid && !IsPromiseDependentType)
1139 return this->IsValid;
1143 assert(this->IsValid &&
"coroutine already invalid");
1144 assert(!this->IsPromiseDependentType &&
1145 "coroutine cannot have a dependent promise type");
1146 this->IsValid = makeOnException() && makeOnFallthrough() &&
1147 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1148 makeNewAndDeleteExpr();
1149 return this->IsValid;
1152 bool CoroutineStmtBuilder::makePromiseStmt() {
1164 bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1176 if (
auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1177 auto *
Decl = DeclRef->getDecl();
1179 if (Method->isStatic())
1188 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1189 << PromiseRecordDecl;
1195 bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1196 assert(!IsPromiseDependentType &&
1197 "cannot make statement while the promise type is dependent");
1225 if (ReturnObjectOnAllocationFailure.
isInvalid())
1231 S.
Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1242 bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1244 assert(!IsPromiseDependentType &&
1245 "cannot make statement while the promise type is dependent");
1262 bool PassAlignment =
false;
1291 if (
auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1299 PlacementArgs.push_back(ThisExpr.
get());
1303 if (PD->getType()->isDependentType())
1307 auto PDLoc = PD->getLocation();
1314 PlacementArgs.push_back(PDRefExpr.
get());
1317 bool PromiseContainNew = [
this, &PromiseType]() ->
bool {
1325 return !R.empty() && !R.isAmbiguous();
1328 auto LookupAllocationFunction = [&]() {
1338 false, PassAlignment, PlacementArgs,
1339 OperatorNew, UnusedResult,
false);
1342 LookupAllocationFunction();
1348 if (!OperatorNew && !PlacementArgs.empty()) {
1349 PlacementArgs.clear();
1350 LookupAllocationFunction();
1353 bool IsGlobalOverload =
1354 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->
getDeclContext());
1358 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
1362 PlacementArgs = {StdNoThrow};
1363 OperatorNew =
nullptr;
1366 false, PassAlignment, PlacementArgs,
1367 OperatorNew, UnusedResult);
1371 if (PromiseContainNew)
1372 S.
Diag(Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD;
1377 if (RequiresNoThrowAlloc) {
1379 if (!FT->isNothrow(
false)) {
1381 diag::err_coroutine_promise_new_requires_nothrow)
1383 S.
Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1410 llvm::append_range(NewArgs, PlacementArgs);
1437 const auto *OpDeleteType =
1439 if (OpDeleteType->getNumParams() > 1)
1440 DeleteArgs.push_back(FrameSize);
1455 bool CoroutineStmtBuilder::makeOnFallthrough() {
1456 assert(!IsPromiseDependentType &&
1457 "cannot make statement while the promise type is dependent");
1466 bool HasRVoid, HasRValue;
1468 lookupMember(S,
"return_void", PromiseRecordDecl, Loc, HasRVoid);
1470 lookupMember(S,
"return_value", PromiseRecordDecl, Loc, HasRValue);
1473 if (HasRVoid && HasRValue) {
1476 diag::err_coroutine_promise_incompatible_return_functions)
1477 << PromiseRecordDecl;
1479 diag::note_member_first_declared_here)
1482 diag::note_member_first_declared_here)
1485 }
else if (!HasRVoid && !HasRValue) {
1497 if (Fallthrough.isInvalid())
1499 }
else if (HasRVoid) {
1503 if (Fallthrough.isInvalid())
1511 bool CoroutineStmtBuilder::makeOnException() {
1513 assert(!IsPromiseDependentType &&
1514 "cannot make statement while the promise type is dependent");
1516 const bool RequireUnhandledException = S.
getLangOpts().CXXExceptions;
1518 if (!
lookupMember(S,
"unhandled_exception", PromiseRecordDecl, Loc)) {
1520 RequireUnhandledException
1521 ? diag::err_coroutine_promise_unhandled_exception_required
1523 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1524 S.
Diag(Loc, DiagID) << PromiseRecordDecl;
1526 << PromiseRecordDecl;
1527 return !RequireUnhandledException;
1535 "unhandled_exception", None);
1554 bool CoroutineStmtBuilder::makeReturnObject() {
1568 if (
auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1569 auto *MethodDecl = MbrRef->getMethodDecl();
1570 S.
Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1577 bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1578 assert(!IsPromiseDependentType &&
1579 "cannot make statement while the promise type is dependent");
1580 assert(this->
ReturnValue &&
"ReturnValue must be already formed");
1584 "get_return_object type must no longer be dependent");
1588 "get_return_object type must no longer be dependent");
1647 assert(isa<FunctionDecl>(
CurContext) &&
"not in a function scope");
1651 if (!ScopeInfo->CoroutineParameterMoves.empty())
1660 for (
auto *PD : FD->parameters()) {
1661 if (PD->getType()->isDependentType())
1670 Expr *CExpr =
nullptr;
1671 if (PD->getType()->getAsCXXRecordDecl() ||
1672 PD->getType()->isRValueReferenceType())
1675 CExpr = PDRefExpr.
get();
1679 auto D =
buildVarDecl(*
this, Loc, PD->getType(), PD->getIdentifier());
1684 if (
Stmt.isInvalid())
1687 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD,
Stmt.get()));
1719 if (!InStd && !InExp) {
1721 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
1722 <<
"std::coroutine_traits";
1727 auto &Result = InStd ? ResStd : ResExp;
1733 Result.suppressDiagnostics();
1741 Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
1742 <<
"coroutine_traits";
1744 auto *Found = *ResExp.
begin();
1745 Diag(Found->getLocation(), diag::note_entity_declared_at) << Found;
1751 diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
1753 diag::note_entity_declared_at)
static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, IdentifierInfo *II)
Builds a specifier combining a prefix and an identifier.
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)
Create the initialization entity for the result of a function.
bool isRecordType() const
bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, AllocationFunctionScope NewScope, AllocationFunctionScope DeleteScope, QualType AllocType, bool IsArray, bool &PassAlignment, MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, FunctionDecl *&OperatorDelete, bool Diagnose=true)
Finds the overloads of operator new and delete that are appropriate for the allocation.
ArrayRef< Stmt * > ParamMoves
bool isLambdaCallOperator(const CXXMethodDecl *MD)
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)
Create an initialization from an initializer (which, for direct initialization from a parenthesized l...
Represents a C++ constructor within a class.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
void setExprNeedsCleanups(bool SideEffects)
StringRef getFirstCoroutineStmtKeyword() const
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
QualType getReturnType() const
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getEndLoc() const LLVM_READONLY
StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs)
ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, Expr *Awaiter, bool IsImplicit=false)
A trivial tuple used to represent a source range.
std::pair< Stmt *, Stmt * > CoroutineSuspends
The initial and final coroutine suspend points.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isVoidPointerType() const
static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, StringRef Name, MultiExprArg Args)
ASTContext & getASTContext() const
sema::FunctionScopeInfo * getCurFunction() const
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, bool IsImplicit=false)
static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, SourceLocation Loc)
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static bool IsOverloaded(const UnresolvedSetImpl &Functions)
Encodes a location in the source.
StmtResult ActOnFinishFullStmt(Stmt *Stmt)
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
This represents a decl that may have a name.
llvm::SmallMapVector< ParmVarDecl *, Stmt *, 4 > CoroutineParameterMoves
A mapping between the coroutine function parameters that were moved to the coroutine frame,...
bool buildDependentStatements()
Build the coroutine body statements that require a non-dependent promise type in order to construct.
FunctionDecl * FindUsualDeallocationFunction(SourceLocation StartLoc, bool CanProvideSize, bool Overaligned, DeclarationName Name)
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
DeclarationNameTable DeclarationNames
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
A (possibly-)qualified type.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
static void checkNoThrow(Sema &S, const Stmt *E, llvm::SmallPtrSetImpl< const Decl * > &ThrowingDecls)
Recursively check E and all its children to see if any call target (including constructor call) is de...
QualType getCanonicalType() const
@ LookupOperatorName
Look up of an operator name (e.g., operator+) for use with operator overloading.
Represents the results of name lookup.
ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs=nullptr)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
bool buildCoroutineParameterMoves(SourceLocation Loc)
@ RQ_RValue
An rvalue ref-qualifier was provided (&&).
SourceLocation FirstSEHTryLoc
First SEH '__try' statement in the current function.
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
Represents a 'co_return' statement in the C++ Coroutines TS.
Represents a C++ nested-name-specifier or a global scope specifier.
NamespaceDecl * getStdNamespace() const
Describes the sequence of initializations required to initialize a given object or reference with a s...
@ AFS_Global
Only look for allocation functions in the global scope.
static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static bool diagReturnOnAllocFailure(Sema &S, Expr *E, CXXRecordDecl *PromiseRecordDecl, FunctionScopeInfo &Fn)
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl *&Operator, bool Diagnose=true)
The name of a declaration.
decls_iterator decls_end() const
static CoroutineBodyStmt * Create(const ASTContext &C, CtorArgs const &Args)
IdentifierTable & getIdentifierTable()
bool isUnevaluatedContext() const
Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
The base class of the type hierarchy.
bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend)
Check that the expression co_await promise.final_suspend() shall not be potentially-throwing.
static ParenListExpr * Create(const ASTContext &Ctx, SourceLocation LParenLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc)
Create a paren list.
const LangOptions & getLangOpts() const
NamespaceDecl * getCachedCoroNamespace()
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
bool isReferenceType() const
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, SourceLocation Loc, Expr *E)
Build calls to await_ready, await_suspend, and await_resume for a co_await expression.
ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, TypeSourceInfo *Ty, Expr *E, SourceRange AngleBrackets, SourceRange Parens)
A reference to a name which we were able to look up during parsing but could not resolve to a specifi...
decls_iterator decls_begin() const
A convenient class for passing around template argument information.
NamespaceDecl * CoroTraitsNamespaceCache
The namespace where coroutine components are defined.
Represents a 'co_await' expression while the type of the promise is dependent.
static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, SourceLocation Loc=SourceLocation())
Determine whether the callee of a particular function call can throw.
void addArgument(const TemplateArgumentLoc &Loc)
ClassTemplateDecl * lookupCoroutineTraits(SourceLocation KwLoc, SourceLocation FuncLoc, NamespaceDecl *&Namespace)
Lookup 'coroutine_traits' in std namespace and std::experimental namespace.
Scope - A scope is a transient data structure that is used while parsing the program.
static FunctionScopeInfo * checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword, bool IsImplicit=false)
Check that this is a context in which a coroutine suspension can appear.
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
bool isInvalidDecl() const
Represents a template argument.
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword)
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End)
Location wrapper for a TemplateArgument.
static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn)
StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro=false)
A set of unresolved declarations.
Represents a variable declaration or definition.
ArrayRef< QualType > getParamTypes() const
bool isStructureType() const
ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E)
static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, SourceLocation KwLoc)
Look up the std::coroutine_traits<...>::promise_type for the given function type.
Represents a declaration of a type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
A C++ nested-name-specifier augmented with source location information.
DeclarationName getLookupName() const
Gets the name to look up.
void setImplicit(bool I=true)
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this function type.
static FunctionDecl * findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType)
StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E)
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, SourceLocation Loc, bool &Res)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
@ ETK_None
No keyword precedes the qualified type name.
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
DeclarationName getName() const
getName - Returns the embedded declaration name.
ClassTemplateDecl * StdCoroutineTraitsCache
The C++ "std::coroutine_traits" template, which is defined in <coroutine_traits>
Retains information about a function, method, or block that is currently being parsed.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const T * castAs() const
Member-template castAs<specific type>.
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Represents a C++ struct/union/class.
bool buildStatements()
Build the coroutine body statements, including the "promise dependent" statements when the promise ty...
DeclContext * computeDeclContext(QualType T)
Compute the DeclContext that is associated with the given type.
SourceLocation FirstCoroutineStmtLoc
First coroutine statement in the current function.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr)
StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, bool AllowRecovery=false)
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
SourceLocation FirstReturnLoc
First 'return' statement in the current function.
ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)
Declaration of a class template.
Represents a C++ template name within the type system.
Represents a 'co_yield' expression.
static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E)
Represents a prototype with parameter type info, e.g.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
OpaqueValueExpr * OpaqueValue
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Decl - This represents one declaration (or definition), e.g.
@ AFS_Class
Only look for allocation functions in the scope of the allocated class.
Sema - This implements semantic analysis and AST building for C.
Represents the body of a coroutine.
Represents a 'co_await' expression.
One of these records is kept for each identifier that is lexed.
NamespaceDecl * lookupStdExperimentalNamespace()
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl=nullptr) const
bool isBooleanType() const
static Expr * buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc)
Look up the std::nothrow object.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
Describes the kind of initialization being performed, along with location information for tokens rela...
CleanupInfo Cleanup
Used to control the generation of ExprWithCleanups.
static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, SourceLocation Loc)
Look up the std::coroutine_handle<PromiseType>.
PointerType - C99 6.7.5.1 - Pointer Declarators.
ActionResult< Stmt * > StmtResult
@ AFS_Both
Look for allocation functions in both the global scope and in the scope of the allocated class.
Scope * getCurScope() const
Retrieve the parser's current scope.
CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn, Stmt *Body)
Construct a CoroutineStmtBuilder and initialize the promise statement and initial/final suspends from...
static void checkSuspensionContext(Sema &S, SourceLocation Loc, StringRef Keyword)
AllocationFunctionScope
The scope in which to find allocation functions.
const UnresolvedSetImpl & asUnresolvedSet() const
Stmt - This represents one statement.
static bool isWithinCatchScope(Scope *S)
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
bool isValid() const
Return true if this is a valid SourceLocation object.
A container of type source information.
QualType getReturnType() const
ExprResult ActOnCXXThis(SourceLocation loc)
SourceLocation getBeginLoc() const LLVM_READONLY
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
DeclClass * getAsSingle() const
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
VarDecl * buildCoroutinePromise(SourceLocation Loc)
bool hasInvalidCoroutineSuspends() const
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, SourceLocation Loc, StringRef Name, MultiExprArg Args)
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body)
Expr * BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs)
BuildBuiltinCallExpr - Create a call to a builtin function specified by Id.
This represents one expression.
ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, UnresolvedLookupExpr *Lookup)
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
static Expr * maybeTailCall(Sema &S, QualType RetType, Expr *E, SourceLocation Loc)
Stmt * ReturnStmtOnAllocFailure
QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity)
Build a reference type.
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static Expr * castForMoving(Sema &S, Expr *E, QualType T=QualType())
ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc)
ArrayRef< ParmVarDecl * > parameters() const
SourceLocation getLocation() const
void append(iterator I, iterator E)
Represent a C++ namespace.
Represents a function declaration or definition.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
@ CallInit
Call-style initialization (C++98)
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a static or instance method of a struct/union/class.
void clearDelayedTypo(TypoExpr *TE)
Clears the state of the given TypoExpr.
DeclContext * getDeclContext()
ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E, UnresolvedLookupExpr *Lookup)
Build a call to 'operator co_await' if there is a suitable operator for the given expression.