clang 23.0.0git
SemaCoroutine.cpp
Go to the documentation of this file.
1//===-- SemaCoroutine.cpp - Semantic Analysis for Coroutines --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for C++ Coroutines.
10//
11// This file contains references to sections of the Coroutines TS, which
12// can be found at http://wg21.link/coroutines.
13//
14//===----------------------------------------------------------------------===//
15
17#include "clang/AST/ASTLambda.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExprCXX.h"
22#include "clang/AST/StmtCXX.h"
28#include "clang/Sema/Overload.h"
30
31using namespace clang;
32using namespace sema;
33
34static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
35 SourceLocation Loc, bool &Res) {
38 // Suppress diagnostics when a private member is selected. The same warnings
39 // will be produced again when building the call.
41 Res = S.LookupQualifiedName(LR, RD);
42 return LR;
43}
44
45static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
46 SourceLocation Loc) {
47 bool Res;
48 lookupMember(S, Name, RD, Loc, Res);
49 return Res;
50}
51
52/// Look up the std::coroutine_traits<...>::promise_type for the given
53/// function type.
55 SourceLocation KwLoc) {
56 const FunctionProtoType *FnType = FD->getType()->castAs<FunctionProtoType>();
57 const SourceLocation FuncLoc = FD->getLocation();
58
59 ClassTemplateDecl *CoroTraits =
60 S.lookupCoroutineTraits(KwLoc, FuncLoc);
61 if (!CoroTraits)
62 return QualType();
63
64 // Form template argument list for coroutine_traits<R, P1, P2, ...> according
65 // to [dcl.fct.def.coroutine]3
66 TemplateArgumentListInfo Args(KwLoc, KwLoc);
67 auto AddArg = [&](QualType T) {
70 };
71 AddArg(FnType->getReturnType());
72 // If the function is a non-static member function, add the type
73 // of the implicit object parameter before the formal parameters.
74 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
75 if (MD->isImplicitObjectMemberFunction()) {
76 // [over.match.funcs]4
77 // For non-static member functions, the type of the implicit object
78 // parameter is
79 // -- "lvalue reference to cv X" for functions declared without a
80 // ref-qualifier or with the & ref-qualifier
81 // -- "rvalue reference to cv X" for functions declared with the &&
82 // ref-qualifier
83 QualType T = MD->getFunctionObjectParameterType();
84 T = FnType->getRefQualifier() == RQ_RValue
86 : S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true);
87 AddArg(T);
88 }
89 }
90 for (QualType T : FnType->getParamTypes())
91 AddArg(T);
92
93 // Build the template-id.
94 QualType CoroTrait = S.CheckTemplateIdType(
95 ElaboratedTypeKeyword::None, TemplateName(CoroTraits), KwLoc, Args,
96 /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false);
97 if (CoroTrait.isNull())
98 return QualType();
99 if (S.RequireCompleteType(KwLoc, CoroTrait,
100 diag::err_coroutine_type_missing_specialization))
101 return QualType();
102
103 auto *RD = CoroTrait->getAsCXXRecordDecl();
104 assert(RD && "specialization of class template is not a class?");
105
106 // Look up the ::promise_type member.
107 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc,
109 S.LookupQualifiedName(R, RD);
110 auto *Promise = R.getAsSingle<TypeDecl>();
111 if (!Promise) {
112 S.Diag(FuncLoc,
113 diag::err_implied_std_coroutine_traits_promise_type_not_found)
114 << RD;
115 return QualType();
116 }
117
118 NestedNameSpecifier Qualifier(CoroTrait.getTypePtr());
120 Qualifier, Promise);
121 // The promise type is required to be a class type.
122 if (!PromiseType->getAsCXXRecordDecl()) {
123 S.Diag(FuncLoc,
124 diag::err_implied_std_coroutine_traits_promise_type_not_class)
125 << PromiseType;
126 return QualType();
127 }
128 if (S.RequireCompleteType(FuncLoc, PromiseType,
129 diag::err_coroutine_promise_type_incomplete))
130 return QualType();
131
132 return PromiseType;
133}
134
135/// Look up the std::coroutine_handle<PromiseType>.
137 SourceLocation Loc) {
138 if (PromiseType.isNull())
139 return QualType();
140
141 NamespaceDecl *CoroNamespace = S.getStdNamespace();
142 assert(CoroNamespace && "Should already be diagnosed");
143
144 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
146 if (!S.LookupQualifiedName(Result, CoroNamespace)) {
147 S.Diag(Loc, diag::err_implied_coroutine_type_not_found)
148 << "std::coroutine_handle";
149 return QualType();
150 }
151
152 ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>();
153 if (!CoroHandle) {
154 Result.suppressDiagnostics();
155 // We found something weird. Complain about the first thing we found.
156 NamedDecl *Found = *Result.begin();
157 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle);
158 return QualType();
159 }
160
161 // Form template argument list for coroutine_handle<Promise>.
162 TemplateArgumentListInfo Args(Loc, Loc);
164 TemplateArgument(PromiseType),
165 S.Context.getTrivialTypeSourceInfo(PromiseType, Loc)));
166
167 // Build the template-id.
168 QualType CoroHandleType = S.CheckTemplateIdType(
169 ElaboratedTypeKeyword::None, TemplateName(CoroHandle), Loc, Args,
170 /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false);
171 if (CoroHandleType.isNull())
172 return QualType();
173 if (S.RequireCompleteType(Loc, CoroHandleType,
174 diag::err_coroutine_type_missing_specialization))
175 return QualType();
176
177 return CoroHandleType;
178}
179
181 StringRef Keyword) {
182 // [expr.await]p2 dictates that 'co_await' and 'co_yield' must be used within
183 // a function body.
184 // FIXME: This also covers [expr.await]p2: "An await-expression shall not
185 // appear in a default argument." But the diagnostic QoI here could be
186 // improved to inform the user that default arguments specifically are not
187 // allowed.
188 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
189 if (!FD) {
191 ? diag::err_coroutine_objc_method
192 : diag::err_coroutine_outside_function) << Keyword;
193 return false;
194 }
195
196 // An enumeration for mapping the diagnostic type to the correct diagnostic
197 // selection index.
198 enum InvalidFuncDiag {
199 DiagCtor = 0,
200 DiagDtor,
201 DiagMain,
202 DiagConstexpr,
203 DiagAutoRet,
204 DiagVarargs,
205 DiagConsteval,
206 };
207 bool Diagnosed = false;
208 auto DiagInvalid = [&](InvalidFuncDiag ID) {
209 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
210 Diagnosed = true;
211 return false;
212 };
213
214 // Diagnose when a constructor, destructor
215 // or the function 'main' are declared as a coroutine.
216 auto *MD = dyn_cast<CXXMethodDecl>(FD);
217 // [class.ctor]p11: "A constructor shall not be a coroutine."
218 if (MD && isa<CXXConstructorDecl>(MD))
219 return DiagInvalid(DiagCtor);
220 // [class.dtor]p17: "A destructor shall not be a coroutine."
221 else if (MD && isa<CXXDestructorDecl>(MD))
222 return DiagInvalid(DiagDtor);
223 // [basic.start.main]p3: "The function main shall not be a coroutine."
224 else if (FD->isMain())
225 return DiagInvalid(DiagMain);
226
227 // Emit a diagnostics for each of the following conditions which is not met.
228 // [expr.const]p2: "An expression e is a core constant expression unless the
229 // evaluation of e [...] would evaluate one of the following expressions:
230 // [...] an await-expression [...] a yield-expression."
231 if (FD->isConstexpr())
232 DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);
233 // [dcl.spec.auto]p15: "A function declared with a return type that uses a
234 // placeholder type shall not be a coroutine."
235 if (FD->getReturnType()->isUndeducedType())
236 DiagInvalid(DiagAutoRet);
237 // [dcl.fct.def.coroutine]p1
238 // The parameter-declaration-clause of the coroutine shall not terminate with
239 // an ellipsis that is not part of a parameter-declaration.
240 if (FD->isVariadic())
241 DiagInvalid(DiagVarargs);
242
243 return !Diagnosed;
244}
245
246/// Build a call to 'operator co_await' if there is a suitable operator for
247/// the given expression.
249 UnresolvedLookupExpr *Lookup) {
250 UnresolvedSet<16> Functions;
251 Functions.append(Lookup->decls_begin(), Lookup->decls_end());
252 return CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
253}
254
256 SourceLocation Loc, Expr *E) {
257 ExprResult R = SemaRef.BuildOperatorCoawaitLookupExpr(S, Loc);
258 if (R.isInvalid())
259 return ExprError();
260 return SemaRef.BuildOperatorCoawaitCall(Loc, E,
262}
263
265 SourceLocation Loc) {
266 QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
267 if (CoroHandleType.isNull())
268 return ExprError();
269
270 DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType);
271 LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc,
273 if (!S.LookupQualifiedName(Found, LookupCtx)) {
274 S.Diag(Loc, diag::err_coroutine_handle_missing_member)
275 << "from_address";
276 return ExprError();
277 }
278
279 Expr *FramePtr =
280 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
281
282 CXXScopeSpec SS;
283 ExprResult FromAddr =
284 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
285 if (FromAddr.isInvalid())
286 return ExprError();
287
288 return S.BuildCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc);
289}
290
297
299 StringRef Name, MultiExprArg Args) {
300 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
301
302 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
303 CXXScopeSpec SS;
305 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
306 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
307 /*Scope=*/nullptr);
308 if (Result.isInvalid())
309 return ExprError();
310
311 auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
312 return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
313}
314
315// See if return type is coroutine-handle and if so, invoke builtin coro-resume
316// on its address. This is to enable the support for coroutine-handle
317// returning await_suspend that results in a guaranteed tail call to the target
318// coroutine.
319static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
320 SourceLocation Loc) {
321 if (RetType->isReferenceType())
322 return nullptr;
323 Type const *T = RetType.getTypePtr();
324 if (!T->isClassType() && !T->isStructureType())
325 return nullptr;
326
327 // FIXME: Add convertability check to coroutine_handle<>. Possibly via
328 // EvaluateBinaryTypeTrait(BTT_IsConvertible, ...) which is at the moment
329 // a private function in SemaExprCXX.cpp
330
331 ExprResult AddressExpr = buildMemberCall(S, E, Loc, "address", {});
332 if (AddressExpr.isInvalid())
333 return nullptr;
334
335 Expr *JustAddress = AddressExpr.get();
336
337 // Check that the type of AddressExpr is void*
338 if (!JustAddress->getType().getTypePtr()->isVoidPointerType())
339 S.Diag(cast<CallExpr>(JustAddress)->getCalleeDecl()->getLocation(),
340 diag::warn_coroutine_handle_address_invalid_return_type)
341 << JustAddress->getType();
342
343 // Clean up temporary objects, because the resulting expression
344 // will become the body of await_suspend wrapper.
345 return S.MaybeCreateExprWithCleanups(JustAddress);
346}
347
348/// Build calls to await_ready, await_suspend, and await_resume for a co_await
349/// expression.
350/// The generated AST tries to clean up temporary objects as early as
351/// possible so that they don't live across suspension points if possible.
352/// Having temporary objects living across suspension points unnecessarily can
353/// lead to large frame size, and also lead to memory corruptions if the
354/// coroutine frame is destroyed after coming back from suspension. This is done
355/// by wrapping both the await_ready call and the await_suspend call with
356/// ExprWithCleanups. In the end of this function, we also need to explicitly
357/// set cleanup state so that the CoawaitExpr is also wrapped with an
358/// ExprWithCleanups to clean up the awaiter associated with the co_await
359/// expression.
361 SourceLocation Loc, Expr *E) {
362 OpaqueValueExpr *Operand = new (S.Context)
363 OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
364
365 // Assume valid until we see otherwise.
366 // Further operations are responsible for setting IsInalid to true.
367 ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/false};
368
370
371 auto BuildSubExpr = [&](ACT CallType, StringRef Func,
372 MultiExprArg Arg) -> Expr * {
373 ExprResult Result = buildMemberCall(S, Operand, Loc, Func, Arg);
374 if (Result.isInvalid()) {
375 Calls.IsInvalid = true;
376 return nullptr;
377 }
378 Calls.Results[CallType] = Result.get();
379 return Result.get();
380 };
381
382 CallExpr *AwaitReady =
383 cast_or_null<CallExpr>(BuildSubExpr(ACT::ACT_Ready, "await_ready", {}));
384 if (!AwaitReady)
385 return Calls;
386 if (!AwaitReady->getType()->isDependentType()) {
387 // [expr.await]p3 [...]
388 // — await-ready is the expression e.await_ready(), contextually converted
389 // to bool.
390 ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady);
391 if (Conv.isInvalid()) {
392 S.Diag(AwaitReady->getDirectCallee()->getBeginLoc(),
393 diag::note_await_ready_no_bool_conversion);
394 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
395 << AwaitReady->getDirectCallee() << E->getSourceRange();
396 Calls.IsInvalid = true;
397 } else
398 Calls.Results[ACT::ACT_Ready] = S.MaybeCreateExprWithCleanups(Conv.get());
399 }
400
401 ExprResult CoroHandleRes =
402 buildCoroutineHandle(S, CoroPromise->getType(), Loc);
403 if (CoroHandleRes.isInvalid()) {
404 Calls.IsInvalid = true;
405 return Calls;
406 }
407 Expr *CoroHandle = CoroHandleRes.get();
408 CallExpr *AwaitSuspend = cast_or_null<CallExpr>(
409 BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
410 if (!AwaitSuspend)
411 return Calls;
412 if (!AwaitSuspend->getType()->isDependentType()) {
413 // [expr.await]p3 [...]
414 // - await-suspend is the expression e.await_suspend(h), which shall be
415 // a prvalue of type void, bool, or std::coroutine_handle<Z> for some
416 // type Z.
417 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
418
419 // Support for coroutine_handle returning await_suspend.
420 if (Expr *TailCallSuspend =
421 maybeTailCall(S, RetType, AwaitSuspend, Loc))
422 // Note that we don't wrap the expression with ExprWithCleanups here
423 // because that might interfere with tailcall contract (e.g. inserting
424 // clean up instructions in-between tailcall and return). Instead
425 // ExprWithCleanups is wrapped within maybeTailCall() prior to the resume
426 // call.
427 Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
428 else {
429 // non-class prvalues always have cv-unqualified types
430 if (RetType->isReferenceType() ||
431 (!RetType->isBooleanType() && !RetType->isVoidType())) {
432 S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
433 diag::err_await_suspend_invalid_return_type)
434 << RetType;
435 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
436 << AwaitSuspend->getDirectCallee();
437 Calls.IsInvalid = true;
438 } else
439 Calls.Results[ACT::ACT_Suspend] =
440 S.MaybeCreateExprWithCleanups(AwaitSuspend);
441 }
442 }
443
444 BuildSubExpr(ACT::ACT_Resume, "await_resume", {});
445
446 // Make sure the awaiter object gets a chance to be cleaned up.
448
449 return Calls;
450}
451
453 SourceLocation Loc, StringRef Name,
454 MultiExprArg Args) {
455
456 // Form a reference to the promise.
457 ExprResult PromiseRef = S.BuildDeclRefExpr(
458 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
459 if (PromiseRef.isInvalid())
460 return ExprError();
461
462 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
463}
464
466 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
467 auto *FD = cast<FunctionDecl>(CurContext);
468 bool IsThisDependentType = [&] {
469 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD))
470 return MD->isImplicitObjectMemberFunction() &&
471 MD->getThisType()->isDependentType();
472 return false;
473 }();
474
475 QualType T = FD->getType()->isDependentType() || IsThisDependentType
476 ? Context.DependentTy
477 : lookupPromiseType(*this, FD, Loc);
478 if (T.isNull())
479 return nullptr;
480
481 auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
482 &PP.getIdentifierTable().get("__promise"), T,
483 Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
484 VD->setImplicit();
486 if (VD->isInvalidDecl())
487 return nullptr;
488
489 auto *ScopeInfo = getCurFunction();
490
491 // Build a list of arguments, based on the coroutine function's arguments,
492 // that if present will be passed to the promise type's constructor.
493 llvm::SmallVector<Expr *, 4> CtorArgExprs;
494
495 // Add implicit object parameter.
496 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
497 if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
498 ExprResult ThisExpr = ActOnCXXThis(Loc);
499 if (ThisExpr.isInvalid())
500 return nullptr;
501 ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
502 if (ThisExpr.isInvalid())
503 return nullptr;
504 CtorArgExprs.push_back(ThisExpr.get());
505 }
506 }
507
508 // Add the coroutine function's parameters.
509 auto &Moves = ScopeInfo->CoroutineParameterMoves;
510 for (auto *PD : FD->parameters()) {
511 if (PD->getType()->isDependentType())
512 continue;
513
514 auto RefExpr = ExprEmpty();
515 auto Move = Moves.find(PD);
516 assert(Move != Moves.end() &&
517 "Coroutine function parameter not inserted into move map");
518 // If a reference to the function parameter exists in the coroutine
519 // frame, use that reference.
520 auto *MoveDecl =
521 cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
522 RefExpr =
523 BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
524 ExprValueKind::VK_LValue, FD->getLocation());
525 if (RefExpr.isInvalid())
526 return nullptr;
527 CtorArgExprs.push_back(RefExpr.get());
528 }
529
530 // If we have a non-zero number of constructor arguments, try to use them.
531 // Otherwise, fall back to the promise type's default constructor.
532 if (!CtorArgExprs.empty()) {
533 // Create an initialization sequence for the promise type using the
534 // constructor arguments, wrapped in a parenthesized list expression.
535 Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(),
536 CtorArgExprs, FD->getLocation());
539 VD->getLocation(), /*DirectInit=*/true, PLE);
540 InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
541 /*TopLevelOfInitList=*/false,
542 /*TreatUnavailableAsInvalid=*/false);
543
544 // [dcl.fct.def.coroutine]5.7
545 // promise-constructor-arguments is determined as follows: overload
546 // resolution is performed on a promise constructor call created by
547 // assembling an argument list q_1 ... q_n . If a viable constructor is
548 // found ([over.match.viable]), then promise-constructor-arguments is ( q_1
549 // , ..., q_n ), otherwise promise-constructor-arguments is empty.
550 if (InitSeq) {
551 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
552 if (Result.isInvalid()) {
553 VD->setInvalidDecl();
554 } else if (Result.get()) {
555 VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
556 VD->setInitStyle(VarDecl::CallInit);
558 }
559 } else
561 } else
563
564 FD->addDecl(VD);
565 return VD;
566}
567
568/// Check that this is a context in which a coroutine suspension can appear.
570 StringRef Keyword,
571 bool IsImplicit = false) {
572 if (!isValidCoroutineContext(S, Loc, Keyword))
573 return nullptr;
574
575 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
576
577 auto *ScopeInfo = S.getCurFunction();
578 assert(ScopeInfo && "missing function scope for function");
579
580 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
581 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
582
583 if (ScopeInfo->CoroutinePromise)
584 return ScopeInfo;
585
587 return nullptr;
588
589 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
590 if (!ScopeInfo->CoroutinePromise)
591 return nullptr;
592
593 return ScopeInfo;
594}
595
596/// Recursively check \p E and all its children to see if any call target
597/// (including constructor call) is declared noexcept. Also any value returned
598/// from the call has a noexcept destructor.
599static void checkNoThrow(Sema &S, const Stmt *E,
600 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {
601 auto checkDeclNoexcept = [&](const Decl *D, bool IsDtor = false) {
602 // In the case of dtor, the call to dtor is implicit and hence we should
603 // pass nullptr to canCalleeThrow.
604 if (Sema::canCalleeThrow(S, IsDtor ? nullptr : cast<Expr>(E), D)) {
605 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
606 // co_await promise.final_suspend() could end up calling
607 // __builtin_coro_resume for symmetric transfer if await_suspend()
608 // returns a handle. In that case, even __builtin_coro_resume is not
609 // declared as noexcept and may throw, it does not throw _into_ the
610 // coroutine that just suspended, but rather throws back out from
611 // whoever called coroutine_handle::resume(), hence we claim that
612 // logically it does not throw.
613 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)
614 return;
615 }
616 if (ThrowingDecls.empty()) {
617 // [dcl.fct.def.coroutine]p15
618 // The expression co_await promise.final_suspend() shall not be
619 // potentially-throwing ([except.spec]).
620 //
621 // First time seeing an error, emit the error message.
622 S.Diag(cast<FunctionDecl>(S.CurContext)->getLocation(),
623 diag::err_coroutine_promise_final_suspend_requires_nothrow);
624 }
625 ThrowingDecls.insert(D);
626 }
627 };
628
629 if (auto *CE = dyn_cast<CXXConstructExpr>(E)) {
630 CXXConstructorDecl *Ctor = CE->getConstructor();
631 checkDeclNoexcept(Ctor);
632 // Check the corresponding destructor of the constructor.
633 checkDeclNoexcept(Ctor->getParent()->getDestructor(), /*IsDtor=*/true);
634 } else if (auto *CE = dyn_cast<CallExpr>(E)) {
635 if (CE->isTypeDependent())
636 return;
637
638 checkDeclNoexcept(CE->getCalleeDecl());
639 QualType ReturnType = CE->getCallReturnType(S.getASTContext());
640 // Check the destructor of the call return type, if any.
641 if (ReturnType.isDestructedType() ==
643 const auto *T =
645 checkDeclNoexcept(
646 cast<CXXRecordDecl>(T->getDecl())->getDefinition()->getDestructor(),
647 /*IsDtor=*/true);
648 }
649 } else
650 for (const auto *Child : E->children()) {
651 if (!Child)
652 continue;
653 checkNoThrow(S, Child, ThrowingDecls);
654 }
655}
656
657bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
659 // We first collect all declarations that should not throw but not declared
660 // with noexcept. We then sort them based on the location before printing.
661 // This is to avoid emitting the same note multiple times on the same
662 // declaration, and also provide a deterministic order for the messages.
663 checkNoThrow(*this, FinalSuspend, ThrowingDecls);
664 auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(),
665 ThrowingDecls.end()};
666 sort(SortedDecls, [](const Decl *A, const Decl *B) {
667 return A->getEndLoc() < B->getEndLoc();
668 });
669 for (const auto *D : SortedDecls) {
670 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
671 }
672 return ThrowingDecls.empty();
673}
674
675// [stmt.return.coroutine]p1:
676// A coroutine shall not enclose a return statement ([stmt.return]).
678 assert(FSI && "FunctionScopeInfo is null");
679 assert(FSI->FirstCoroutineStmtLoc.isValid() &&
680 "first coroutine location not set");
681 if (FSI->FirstReturnLoc.isInvalid())
682 return;
683 S.Diag(FSI->FirstReturnLoc, diag::err_return_in_coroutine);
684 S.Diag(FSI->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
686}
687
689 StringRef Keyword) {
690 // Ignore previous expr evaluation contexts.
693 dyn_cast_or_null<FunctionDecl>(CurContext));
694
695 if (!checkCoroutineContext(*this, KWLoc, Keyword))
696 return false;
697
698 // Support for coroutines is not stable on 32 bits windows
699 // Warn about it.
700 if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
701 Context.getTargetInfo().getTriple().isX86_32())
702 Diag(KWLoc, diag::warn_coroutines_x86_windows);
703
704 auto *ScopeInfo = getCurFunction();
705 assert(ScopeInfo->CoroutinePromise);
706
707 // Avoid duplicate errors, report only on first keyword.
708 if (ScopeInfo->FirstCoroutineStmtLoc == KWLoc)
709 checkReturnStmtInCoroutine(*this, ScopeInfo);
710
711 // If we have existing coroutine statements then we have already built
712 // the initial and final suspend points.
713 if (!ScopeInfo->NeedsCoroutineSuspends)
714 return true;
715
716 ScopeInfo->setNeedsCoroutineSuspends(false);
717
718 auto *Fn = cast<FunctionDecl>(CurContext);
719 SourceLocation Loc = Fn->getLocation();
720 // Build the initial suspend point
721 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
722 ExprResult Operand =
723 buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, {});
724 if (Operand.isInvalid())
725 return StmtError();
726 ExprResult Suspend =
727 buildOperatorCoawaitCall(*this, SC, Loc, Operand.get());
728 if (Suspend.isInvalid())
729 return StmtError();
730 Suspend = BuildResolvedCoawaitExpr(Loc, Operand.get(), Suspend.get(),
731 /*IsImplicit*/ true);
732 Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
733 if (Suspend.isInvalid()) {
734 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
735 << ((Name == "initial_suspend") ? 0 : 1);
736 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
737 return StmtError();
738 }
739 return cast<Stmt>(Suspend.get());
740 };
741
742 StmtResult InitSuspend = buildSuspends("initial_suspend");
743 if (InitSuspend.isInvalid())
744 return true;
745
746 StmtResult FinalSuspend = buildSuspends("final_suspend");
747 if (FinalSuspend.isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.get()))
748 return true;
749
750 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
751
752 return true;
753}
754
755// Recursively walks up the scope hierarchy until either a 'catch' or a function
756// scope is found, whichever comes first.
757static bool isWithinCatchScope(Scope *S) {
758 // 'co_await' and 'co_yield' keywords are disallowed within catch blocks, but
759 // lambdas that use 'co_await' are allowed. The loop below ends when a
760 // function scope is found in order to ensure the following behavior:
761 //
762 // void foo() { // <- function scope
763 // try { //
764 // co_await x; // <- 'co_await' is OK within a function scope
765 // } catch { // <- catch scope
766 // co_await x; // <- 'co_await' is not OK within a catch scope
767 // []() { // <- function scope
768 // co_await x; // <- 'co_await' is OK within a function scope
769 // }();
770 // }
771 // }
772 while (S && !S->isFunctionScope()) {
773 if (S->isCatchScope())
774 return true;
775 S = S->getParent();
776 }
777 return false;
778}
779
780// [expr.await]p2, emphasis added: "An await-expression shall appear only in
781// a *potentially evaluated* expression within the compound-statement of a
782// function-body *outside of a handler* [...] A context within a function
783// where an await-expression can appear is called a suspension context of the
784// function."
786 StringRef Keyword) {
787 // First emphasis of [expr.await]p2: must be a potentially evaluated context.
788 // That is, 'co_await' and 'co_yield' cannot appear in subexpressions of
789 // \c sizeof.
790 const auto ExprContext = S.currentEvaluationContext().ExprContext;
791 const bool BadContext =
795 if (BadContext) {
796 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
797 return false;
798 }
799
800 // Second emphasis of [expr.await]p2: must be outside of an exception handler.
802 S.Diag(Loc, diag::err_coroutine_within_handler) << Keyword;
803 return false;
804 }
805 return true;
806}
807
809 if (!checkSuspensionContext(*this, Loc, "co_await"))
810 return ExprError();
811
812 if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
813 return ExprError();
814 }
815
816 if (E->hasPlaceholderType()) {
818 if (R.isInvalid()) return ExprError();
819 E = R.get();
820 }
821
823 if (Lookup.isInvalid())
824 return ExprError();
825 return BuildUnresolvedCoawaitExpr(Loc, E,
827}
828
830 DeclarationName OpName =
831 Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
832 LookupResult Operators(*this, OpName, SourceLocation(),
834 LookupName(Operators, S);
835
836 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
837 const auto &Functions = Operators.asUnresolvedSet();
839 Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
840 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(),
841 Functions.end(), /*KnownDependent=*/false,
842 /*KnownInstantiationDependent=*/false);
843 assert(CoawaitOp);
844 return CoawaitOp;
845}
846
848 auto *Record = QT->getAsCXXRecordDecl();
849 return Record && Record->hasAttr<CoroAwaitElidableAttr>();
850}
851
852static void applySafeElideContext(Expr *Operand) {
853 // Strip both implicit nodes and parentheses to find the underlying CallExpr.
854 // The AST may have these in either order, so we apply both transformations
855 // iteratively until reaching a fixed point.
856 auto *Call = dyn_cast<CallExpr>(IgnoreExprNodes(
858 if (!Call || !Call->isPRValue())
859 return;
860
861 if (!isAttributedCoroAwaitElidable(Call->getType()))
862 return;
863
864 Call->setCoroElideSafe();
865
866 // Check parameter
867 auto *Fn = llvm::dyn_cast_if_present<FunctionDecl>(Call->getCalleeDecl());
868 if (!Fn)
869 return;
870
871 size_t ParmIdx = 0;
872 for (ParmVarDecl *PD : Fn->parameters()) {
873 if (PD->hasAttr<CoroAwaitElidableArgumentAttr>())
874 applySafeElideContext(Call->getArg(ParmIdx));
875
876 ParmIdx++;
877 }
878}
879
880// Attempts to resolve and build a CoawaitExpr from "raw" inputs, bailing out to
881// DependentCoawaitExpr if needed.
883 UnresolvedLookupExpr *Lookup) {
884 auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
885 if (!FSI)
886 return ExprError();
887
888 if (Operand->hasPlaceholderType()) {
889 ExprResult R = CheckPlaceholderExpr(Operand);
890 if (R.isInvalid())
891 return ExprError();
892 Operand = R.get();
893 }
894
895 auto *Promise = FSI->CoroutinePromise;
896 if (Promise->getType()->isDependentType()) {
897 Expr *Res = new (Context)
898 DependentCoawaitExpr(Loc, Context.DependentTy, Operand, Lookup);
899 return Res;
900 }
901
902 auto *RD = Promise->getType()->getAsCXXRecordDecl();
903
904 bool CurFnAwaitElidable = isAttributedCoroAwaitElidable(
905 getCurFunctionDecl(/*AllowLambda=*/true)->getReturnType());
906
907 if (CurFnAwaitElidable)
908 applySafeElideContext(Operand);
909
910 Expr *Transformed = Operand;
911 if (lookupMember(*this, "await_transform", RD, Loc)) {
912 ExprResult R =
913 buildPromiseCall(*this, Promise, Loc, "await_transform", Operand);
914 if (R.isInvalid()) {
915 Diag(Loc,
916 diag::note_coroutine_promise_implicit_await_transform_required_here)
917 << Operand->getSourceRange();
918 return ExprError();
919 }
920 Transformed = R.get();
921 }
922 ExprResult Awaiter = BuildOperatorCoawaitCall(Loc, Transformed, Lookup);
923 if (Awaiter.isInvalid())
924 return ExprError();
925
926 return BuildResolvedCoawaitExpr(Loc, Operand, Awaiter.get());
927}
928
930 Expr *Awaiter, bool IsImplicit) {
931 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
932 if (!Coroutine)
933 return ExprError();
934
935 if (Awaiter->hasPlaceholderType()) {
936 ExprResult R = CheckPlaceholderExpr(Awaiter);
937 if (R.isInvalid()) return ExprError();
938 Awaiter = R.get();
939 }
940
941 if (Awaiter->getType()->isDependentType()) {
942 Expr *Res = new (Context)
943 CoawaitExpr(Loc, Context.DependentTy, Operand, Awaiter, IsImplicit);
944 return Res;
945 }
946
947 // If the expression is a temporary, materialize it as an lvalue so that we
948 // can use it multiple times.
949 if (Awaiter->isPRValue())
950 Awaiter = CreateMaterializeTemporaryExpr(Awaiter->getType(), Awaiter, true);
951
952 // The location of the `co_await` token cannot be used when constructing
953 // the member call expressions since it's before the location of `Expr`, which
954 // is used as the start of the member call expression.
955 SourceLocation CallLoc = Awaiter->getExprLoc();
956
957 // Build the await_ready, await_suspend, await_resume calls.
959 buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, Awaiter);
960 if (RSS.IsInvalid)
961 return ExprError();
962
963 Expr *Res = new (Context)
964 CoawaitExpr(Loc, Operand, Awaiter, RSS.Results[0], RSS.Results[1],
965 RSS.Results[2], RSS.OpaqueValue, IsImplicit);
966
967 return Res;
968}
969
971 if (!checkSuspensionContext(*this, Loc, "co_yield"))
972 return ExprError();
973
974 if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
975 return ExprError();
976 }
977
978 // Build yield_value call.
979 ExprResult Awaitable = buildPromiseCall(
980 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
981 if (Awaitable.isInvalid())
982 return ExprError();
983
984 // Build 'operator co_await' call.
985 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
986 if (Awaitable.isInvalid())
987 return ExprError();
988
989 return BuildCoyieldExpr(Loc, Awaitable.get());
990}
992 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
993 if (!Coroutine)
994 return ExprError();
995
996 if (E->hasPlaceholderType()) {
998 if (R.isInvalid()) return ExprError();
999 E = R.get();
1000 }
1001
1002 Expr *Operand = E;
1003
1004 if (E->getType()->isDependentType()) {
1005 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, Operand, E);
1006 return Res;
1007 }
1008
1009 // If the expression is a temporary, materialize it as an lvalue so that we
1010 // can use it multiple times.
1011 if (E->isPRValue())
1012 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
1013
1014 // Build the await_ready, await_suspend, await_resume calls.
1016 *this, Coroutine->CoroutinePromise, Loc, E);
1017 if (RSS.IsInvalid)
1018 return ExprError();
1019
1020 Expr *Res =
1021 new (Context) CoyieldExpr(Loc, Operand, E, RSS.Results[0], RSS.Results[1],
1022 RSS.Results[2], RSS.OpaqueValue);
1023
1024 return Res;
1025}
1026
1028 if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
1029 return StmtError();
1030 }
1031 return BuildCoreturnStmt(Loc, E);
1032}
1033
1035 bool IsImplicit) {
1036 auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
1037 if (!FSI)
1038 return StmtError();
1039
1040 if (E && E->hasPlaceholderType() &&
1041 !E->hasPlaceholderType(BuiltinType::Overload)) {
1043 if (R.isInvalid()) return StmtError();
1044 E = R.get();
1045 }
1046
1047 VarDecl *Promise = FSI->CoroutinePromise;
1048 ExprResult PC;
1049 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
1051 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
1052 } else {
1054 PC = buildPromiseCall(*this, Promise, Loc, "return_void", {});
1055 }
1056 if (PC.isInvalid())
1057 return StmtError();
1058
1059 Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
1060
1061 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
1062 return Res;
1063}
1064
1065/// Look up the std::nothrow object.
1067 NamespaceDecl *Std = S.getStdNamespace();
1068 assert(Std && "Should already be diagnosed");
1069
1070 LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc,
1072 if (!S.LookupQualifiedName(Result, Std)) {
1073 // <coroutine> is not requred to include <new>, so we couldn't omit
1074 // the check here.
1075 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
1076 return nullptr;
1077 }
1078
1079 auto *VD = Result.getAsSingle<VarDecl>();
1080 if (!VD) {
1081 Result.suppressDiagnostics();
1082 // We found something weird. Complain about the first thing we found.
1083 NamedDecl *Found = *Result.begin();
1084 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);
1085 return nullptr;
1086 }
1087
1088 ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc);
1089 if (DR.isInvalid())
1090 return nullptr;
1091
1092 return DR.get();
1093}
1094
1096 SourceLocation Loc) {
1097 EnumDecl *StdAlignValDecl = S.getStdAlignValT();
1098 CanQualType StdAlignValT = S.Context.getCanonicalTagType(StdAlignValDecl);
1099 return S.Context.getTrivialTypeSourceInfo(StdAlignValT);
1100}
1101
1102// When searching for custom allocators on the PromiseType we want to
1103// warn that we will ignore type aware allocators.
1105 unsigned DiagnosticID,
1106 DeclarationName Name,
1107 QualType PromiseType) {
1108 assert(PromiseType->isRecordType());
1109
1110 LookupResult R(S, Name, Loc, Sema::LookupOrdinaryName);
1111 S.LookupQualifiedName(R, PromiseType->getAsCXXRecordDecl());
1112 bool HaveIssuedWarning = false;
1113 for (auto Decl : R) {
1114 if (!Decl->getUnderlyingDecl()
1115 ->getAsFunction()
1117 continue;
1118 if (!HaveIssuedWarning) {
1119 S.Diag(Loc, DiagnosticID) << Name;
1120 HaveIssuedWarning = true;
1121 }
1122 S.Diag(Decl->getLocation(), diag::note_type_aware_operator_declared)
1123 << /* isTypeAware=*/1 << Decl << Decl->getDeclContext();
1124 }
1125 R.suppressDiagnostics();
1126 return HaveIssuedWarning;
1127}
1128
1129// Find an appropriate delete for the promise.
1130static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType,
1131 FunctionDecl *&OperatorDelete) {
1132 DeclarationName DeleteName =
1135 diag::warn_coroutine_type_aware_allocator_ignored,
1136 DeleteName, PromiseType);
1137 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
1138 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
1139
1140 const bool Overaligned = S.getLangOpts().CoroAlignedAllocation;
1141
1142 // [dcl.fct.def.coroutine]p12
1143 // The deallocation function's name is looked up by searching for it in the
1144 // scope of the promise type. If nothing is found, a search is performed in
1145 // the global scope.
1148 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete,
1149 IDP, /*Diagnose=*/true))
1150 return false;
1151
1152 // [dcl.fct.def.coroutine]p12
1153 // If both a usual deallocation function with only a pointer parameter and a
1154 // usual deallocation function with both a pointer parameter and a size
1155 // parameter are found, then the selected deallocation function shall be the
1156 // one with two parameters. Otherwise, the selected deallocation function
1157 // shall be the function with one parameter.
1158 if (!OperatorDelete) {
1159 // Look for a global declaration.
1160 // Sema::FindUsualDeallocationFunction will try to find the one with two
1161 // parameters first. It will return the deallocation function with one
1162 // parameter if failed.
1163 // Coroutines can always provide their required size.
1165 OperatorDelete = S.FindUsualDeallocationFunction(Loc, IDP, DeleteName);
1166
1167 if (!OperatorDelete)
1168 return false;
1169 }
1170
1171 assert(!OperatorDelete->isTypeAwareOperatorNewOrDelete());
1172 S.MarkFunctionReferenced(Loc, OperatorDelete);
1173 return true;
1174}
1175
1176
1179 assert(Fn && Fn->isCoroutine() && "not a coroutine");
1180 if (!Body) {
1181 assert(FD->isInvalidDecl() &&
1182 "a null body is only allowed for invalid declarations");
1183 return;
1184 }
1185 // We have a function that uses coroutine keywords, but we failed to build
1186 // the promise type.
1187 if (!Fn->CoroutinePromise)
1188 return FD->setInvalidDecl();
1189
1190 if (isa<CoroutineBodyStmt>(Body)) {
1191 // Nothing todo. the body is already a transformed coroutine body statement.
1192 return;
1193 }
1194
1195 // The always_inline attribute doesn't reliably apply to a coroutine,
1196 // because the coroutine will be split into pieces and some pieces
1197 // might be called indirectly, as in a virtual call. Even the ramp
1198 // function cannot be inlined at -O0, due to pipeline ordering
1199 // problems (see https://llvm.org/PR53413). Tell the user about it.
1200 if (FD->hasAttr<AlwaysInlineAttr>())
1201 Diag(FD->getLocation(), diag::warn_always_inline_coroutine);
1202
1203 // The design of coroutines means we cannot allow use of VLAs within one, so
1204 // diagnose if we've seen a VLA in the body of this function.
1205 if (Fn->FirstVLALoc.isValid())
1206 Diag(Fn->FirstVLALoc, diag::err_vla_in_coroutine_unsupported);
1207
1208 // Coroutines will get splitted into pieces. The GNU address of label
1209 // extension wouldn't be meaningful in coroutines.
1210 for (AddrLabelExpr *ALE : Fn->AddrLabels)
1211 Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
1212
1213 // Coroutines always return a handle, so they can't be [[noreturn]].
1214 if (FD->isNoReturn())
1215 Diag(FD->getLocation(), diag::warn_noreturn_coroutine) << FD;
1216
1217 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
1218 if (Builder.isInvalid() || !Builder.buildStatements())
1219 return FD->setInvalidDecl();
1220
1221 // Build body for the coroutine wrapper statement.
1222 Body = CoroutineBodyStmt::Create(Context, Builder);
1223}
1224
1226 if (auto *CS = dyn_cast<CompoundStmt>(Body))
1227 return CS;
1228
1229 // The body of the coroutine may be a try statement if it is in
1230 // 'function-try-block' syntax. Here we wrap it into a compound
1231 // statement for consistency.
1232 assert(isa<CXXTryStmt>(Body) && "Unimaged coroutine body type");
1233 return CompoundStmt::Create(Context, {Body}, FPOptionsOverride(),
1235}
1236
1239 Stmt *Body)
1240 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1241 IsPromiseDependentType(
1242 !Fn.CoroutinePromise ||
1243 Fn.CoroutinePromise->getType()->isDependentType()) {
1244 this->Body = buildCoroutineBody(Body, S.getASTContext());
1245
1246 for (auto KV : Fn.CoroutineParameterMoves)
1247 this->ParamMovesVector.push_back(KV.second);
1248 this->ParamMoves = this->ParamMovesVector;
1249
1250 if (!IsPromiseDependentType) {
1251 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
1252 assert(PromiseRecordDecl && "Type should have already been checked");
1253 }
1254 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1255}
1256
1258 assert(this->IsValid && "coroutine already invalid");
1259 this->IsValid = makeReturnObject();
1260 if (this->IsValid && !IsPromiseDependentType)
1262 return this->IsValid;
1263}
1264
1266 assert(this->IsValid && "coroutine already invalid");
1267 assert(!this->IsPromiseDependentType &&
1268 "coroutine cannot have a dependent promise type");
1269 this->IsValid = makeOnException() && makeOnFallthrough() &&
1270 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1271 makeNewAndDeleteExpr();
1272 return this->IsValid;
1273}
1274
1275bool CoroutineStmtBuilder::makePromiseStmt() {
1276 // Form a declaration statement for the promise declaration, so that AST
1277 // visitors can more easily find it.
1278 StmtResult PromiseStmt =
1280 if (PromiseStmt.isInvalid())
1281 return false;
1282
1283 this->Promise = PromiseStmt.get();
1284 return true;
1285}
1286
1287bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1289 return false;
1291 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
1292 return true;
1293}
1294
1296 CXXRecordDecl *PromiseRecordDecl,
1297 FunctionScopeInfo &Fn) {
1298 auto Loc = E->getExprLoc();
1299 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1300 auto *Decl = DeclRef->getDecl();
1301 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) {
1302 if (Method->isStatic())
1303 return true;
1304 else
1305 Loc = Decl->getLocation();
1306 }
1307 }
1308
1309 S.Diag(
1310 Loc,
1311 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1312 << PromiseRecordDecl;
1313 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1314 << Fn.getFirstCoroutineStmtKeyword();
1315 return false;
1316}
1317
1318bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1319 assert(!IsPromiseDependentType &&
1320 "cannot make statement while the promise type is dependent");
1321
1322 // [dcl.fct.def.coroutine]p10
1323 // If a search for the name get_return_object_on_allocation_failure in
1324 // the scope of the promise type ([class.member.lookup]) finds any
1325 // declarations, then the result of a call to an allocation function used to
1326 // obtain storage for the coroutine state is assumed to return nullptr if it
1327 // fails to obtain storage, ... If the allocation function returns nullptr,
1328 // ... and the return value is obtained by a call to
1329 // T::get_return_object_on_allocation_failure(), where T is the
1330 // promise type.
1331 DeclarationName DN =
1332 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");
1333 LookupResult Found(S, DN, Loc, Sema::LookupMemberName);
1334 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))
1335 return true;
1336
1337 CXXScopeSpec SS;
1338 ExprResult DeclNameExpr =
1339 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
1340 if (DeclNameExpr.isInvalid())
1341 return false;
1342
1343 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn))
1344 return false;
1345
1346 ExprResult ReturnObjectOnAllocationFailure =
1347 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
1348 if (ReturnObjectOnAllocationFailure.isInvalid())
1349 return false;
1350
1352 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
1353 if (ReturnStmt.isInvalid()) {
1354 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1355 << DN;
1356 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1357 << Fn.getFirstCoroutineStmtKeyword();
1358 return false;
1359 }
1360
1362 return true;
1363}
1364
1365// Collect placement arguments for allocation function of coroutine FD.
1366// Return true if we collect placement arguments succesfully. Return false,
1367// otherwise.
1369 SmallVectorImpl<Expr *> &PlacementArgs) {
1370 if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1371 if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
1372 ExprResult ThisExpr = S.ActOnCXXThis(Loc);
1373 if (ThisExpr.isInvalid())
1374 return false;
1375 ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
1376 if (ThisExpr.isInvalid())
1377 return false;
1378 PlacementArgs.push_back(ThisExpr.get());
1379 }
1380 }
1381
1382 for (auto *PD : FD.parameters()) {
1383 if (PD->getType()->isDependentType())
1384 continue;
1385
1386 // Build a reference to the parameter.
1387 auto PDLoc = PD->getLocation();
1388 ExprResult PDRefExpr =
1389 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
1391 if (PDRefExpr.isInvalid())
1392 return false;
1393
1394 PlacementArgs.push_back(PDRefExpr.get());
1395 }
1396
1397 return true;
1398}
1399
1400bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1401 // Form and check allocation and deallocation calls.
1402 assert(!IsPromiseDependentType &&
1403 "cannot make statement while the promise type is dependent");
1404 QualType PromiseType = Fn.CoroutinePromise->getType();
1405
1406 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
1407 return false;
1408
1409 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
1410
1411 // According to [dcl.fct.def.coroutine]p9, Lookup allocation functions using a
1412 // parameter list composed of the requested size of the coroutine state being
1413 // allocated, followed by the coroutine function's arguments. If a matching
1414 // allocation function exists, use it. Otherwise, use an allocation function
1415 // that just takes the requested size.
1416 //
1417 // [dcl.fct.def.coroutine]p9
1418 // An implementation may need to allocate additional storage for a
1419 // coroutine.
1420 // This storage is known as the coroutine state and is obtained by calling a
1421 // non-array allocation function ([basic.stc.dynamic.allocation]). The
1422 // allocation function's name is looked up by searching for it in the scope of
1423 // the promise type.
1424 // - If any declarations are found, overload resolution is performed on a
1425 // function call created by assembling an argument list. The first argument is
1426 // the amount of space requested, and has type std::size_t. The
1427 // lvalues p1 ... pn are the succeeding arguments.
1428 //
1429 // ...where "p1 ... pn" are defined earlier as:
1430 //
1431 // [dcl.fct.def.coroutine]p3
1432 // The promise type of a coroutine is `std::coroutine_traits<R, P1, ...,
1433 // Pn>`
1434 // , where R is the return type of the function, and `P1, ..., Pn` are the
1435 // sequence of types of the non-object function parameters, preceded by the
1436 // type of the object parameter ([dcl.fct]) if the coroutine is a non-static
1437 // member function. [dcl.fct.def.coroutine]p4 In the following, p_i is an
1438 // lvalue of type P_i, where p1 denotes the object parameter and p_i+1 denotes
1439 // the i-th non-object function parameter for a non-static member function,
1440 // and p_i denotes the i-th function parameter otherwise. For a non-static
1441 // member function, q_1 is an lvalue that denotes *this; any other q_i is an
1442 // lvalue that denotes the parameter copy corresponding to p_i.
1443
1444 FunctionDecl *OperatorNew = nullptr;
1445 SmallVector<Expr *, 1> PlacementArgs;
1446 DeclarationName NewName =
1447 S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New);
1448
1449 const bool PromiseContainsNew = [this, &PromiseType, NewName]() -> bool {
1450 LookupResult R(S, NewName, Loc, Sema::LookupOrdinaryName);
1451
1452 if (PromiseType->isRecordType())
1453 S.LookupQualifiedName(R, PromiseType->getAsCXXRecordDecl());
1454
1455 return !R.empty() && !R.isAmbiguous();
1456 }();
1457
1458 // Helper function to indicate whether the last lookup found the aligned
1459 // allocation function.
1460 ImplicitAllocationParameters IAP(
1461 alignedAllocationModeFromBool(S.getLangOpts().CoroAlignedAllocation));
1462 auto LookupAllocationFunction = [&](AllocationFunctionScope NewScope =
1464 bool WithoutPlacementArgs = false,
1465 bool ForceNonAligned = false) {
1466 // [dcl.fct.def.coroutine]p9
1467 // The allocation function's name is looked up by searching for it in the
1468 // scope of the promise type.
1469 // - If any declarations are found, ...
1470 // - If no declarations are found in the scope of the promise type, a search
1471 // is performed in the global scope.
1472 if (NewScope == AllocationFunctionScope::Both)
1473 NewScope = PromiseContainsNew ? AllocationFunctionScope::Class
1475
1476 bool ShouldUseAlignedAlloc =
1477 !ForceNonAligned && S.getLangOpts().CoroAlignedAllocation;
1478 IAP = ImplicitAllocationParameters(
1479 alignedAllocationModeFromBool(ShouldUseAlignedAlloc));
1480
1481 FunctionDecl *UnusedResult = nullptr;
1482 S.FindAllocationFunctions(
1483 Loc, SourceRange(), NewScope,
1484 /*DeleteScope=*/AllocationFunctionScope::Both, PromiseType,
1485 /*isArray=*/false, IAP,
1486 WithoutPlacementArgs ? MultiExprArg{} : PlacementArgs, OperatorNew,
1487 UnusedResult, /*Diagnose=*/false);
1488 assert(!OperatorNew || !OperatorNew->isTypeAwareOperatorNewOrDelete());
1489 };
1490
1491 // We don't expect to call to global operator new with (size, p0, …, pn).
1492 // So if we choose to lookup the allocation function in global scope, we
1493 // shouldn't lookup placement arguments.
1494 if (PromiseContainsNew && !collectPlacementArgs(S, FD, Loc, PlacementArgs))
1495 return false;
1496
1497 LookupAllocationFunction();
1498
1499 if (PromiseContainsNew && !PlacementArgs.empty()) {
1500 // [dcl.fct.def.coroutine]p9
1501 // If no viable function is found ([over.match.viable]), overload
1502 // resolution
1503 // is performed again on a function call created by passing just the amount
1504 // of space required as an argument of type std::size_t.
1505 //
1506 // Proposed Change of [dcl.fct.def.coroutine]p9 in P2014R0:
1507 // Otherwise, overload resolution is performed again on a function call
1508 // created
1509 // by passing the amount of space requested as an argument of type
1510 // std::size_t as the first argument, and the requested alignment as
1511 // an argument of type std:align_val_t as the second argument.
1512 if (!OperatorNew || (S.getLangOpts().CoroAlignedAllocation &&
1513 !isAlignedAllocation(IAP.PassAlignment)))
1514 LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
1515 /*WithoutPlacementArgs*/ true);
1516 }
1517
1518 // Proposed Change of [dcl.fct.def.coroutine]p12 in P2014R0:
1519 // Otherwise, overload resolution is performed again on a function call
1520 // created
1521 // by passing the amount of space requested as an argument of type
1522 // std::size_t as the first argument, and the lvalues p1 ... pn as the
1523 // succeeding arguments. Otherwise, overload resolution is performed again
1524 // on a function call created by passing just the amount of space required as
1525 // an argument of type std::size_t.
1526 //
1527 // So within the proposed change in P2014RO, the priority order of aligned
1528 // allocation functions wiht promise_type is:
1529 //
1530 // void* operator new( std::size_t, std::align_val_t, placement_args... );
1531 // void* operator new( std::size_t, std::align_val_t);
1532 // void* operator new( std::size_t, placement_args... );
1533 // void* operator new( std::size_t);
1534
1535 // Helper variable to emit warnings.
1536 bool FoundNonAlignedInPromise = false;
1537 if (PromiseContainsNew && S.getLangOpts().CoroAlignedAllocation)
1538 if (!OperatorNew || !isAlignedAllocation(IAP.PassAlignment)) {
1539 FoundNonAlignedInPromise = OperatorNew;
1540
1541 LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
1542 /*WithoutPlacementArgs*/ false,
1543 /*ForceNonAligned*/ true);
1544
1545 if (!OperatorNew && !PlacementArgs.empty())
1546 LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
1547 /*WithoutPlacementArgs*/ true,
1548 /*ForceNonAligned*/ true);
1549 }
1550
1551 bool IsGlobalOverload =
1552 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
1553 // If we didn't find a class-local new declaration and non-throwing new
1554 // was is required then we need to lookup the non-throwing global operator
1555 // instead.
1556 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
1557 auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc);
1558 if (!StdNoThrow)
1559 return false;
1560 PlacementArgs = {StdNoThrow};
1561 OperatorNew = nullptr;
1562 LookupAllocationFunction(AllocationFunctionScope::Global);
1563 }
1564
1565 // If we found a non-aligned allocation function in the promise_type,
1566 // it indicates the user forgot to update the allocation function. Let's emit
1567 // a warning here.
1568 if (FoundNonAlignedInPromise) {
1569 S.Diag(OperatorNew->getLocation(),
1570 diag::warn_non_aligned_allocation_function)
1571 << &FD;
1572 }
1573
1574 if (!OperatorNew) {
1575 if (PromiseContainsNew) {
1576 S.Diag(Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD;
1578 S, Loc, diag::note_coroutine_unusable_type_aware_allocators, NewName,
1579 PromiseType);
1580 } else if (RequiresNoThrowAlloc)
1581 S.Diag(Loc, diag::err_coroutine_unfound_nothrow_new)
1582 << &FD << S.getLangOpts().CoroAlignedAllocation;
1583
1584 return false;
1585 }
1586 assert(!OperatorNew->isTypeAwareOperatorNewOrDelete());
1587
1589 diag::warn_coroutine_type_aware_allocator_ignored,
1590 NewName, PromiseType);
1591
1592 if (RequiresNoThrowAlloc) {
1593 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();
1594 if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
1595 S.Diag(OperatorNew->getLocation(),
1596 diag::err_coroutine_promise_new_requires_nothrow)
1597 << OperatorNew;
1598 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1599 << OperatorNew;
1600 return false;
1601 }
1602 }
1603
1604 FunctionDecl *OperatorDelete = nullptr;
1605 if (!findDeleteForPromise(S, Loc, PromiseType, OperatorDelete)) {
1606 // FIXME: We should add an error here. According to:
1607 // [dcl.fct.def.coroutine]p12
1608 // If no usual deallocation function is found, the program is ill-formed.
1609 return false;
1610 }
1611
1612 assert(!OperatorDelete->isTypeAwareOperatorNewOrDelete());
1613
1614 Expr *FramePtr =
1615 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
1616
1617 Expr *FrameSize =
1618 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
1619
1620 Expr *FrameAlignment = nullptr;
1621
1622 if (S.getLangOpts().CoroAlignedAllocation) {
1623 FrameAlignment =
1624 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_align, {});
1625
1626 TypeSourceInfo *AlignValTy = getTypeSourceInfoForStdAlignValT(S, Loc);
1627 if (!AlignValTy)
1628 return false;
1629
1630 FrameAlignment = S.BuildCXXNamedCast(Loc, tok::kw_static_cast, AlignValTy,
1631 FrameAlignment, SourceRange(Loc, Loc),
1632 SourceRange(Loc, Loc))
1633 .get();
1634 }
1635
1636 // Make new call.
1637 ExprResult NewRef =
1638 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
1639 if (NewRef.isInvalid())
1640 return false;
1641
1642 SmallVector<Expr *, 2> NewArgs(1, FrameSize);
1643 if (S.getLangOpts().CoroAlignedAllocation &&
1644 isAlignedAllocation(IAP.PassAlignment))
1645 NewArgs.push_back(FrameAlignment);
1646
1647 if (OperatorNew->getNumParams() > NewArgs.size())
1648 llvm::append_range(NewArgs, PlacementArgs);
1649
1650 ExprResult NewExpr =
1651 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
1652 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
1653 if (NewExpr.isInvalid())
1654 return false;
1655
1656 // Make delete call.
1657
1658 QualType OpDeleteQualType = OperatorDelete->getType();
1659
1660 ExprResult DeleteRef =
1661 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
1662 if (DeleteRef.isInvalid())
1663 return false;
1664
1665 Expr *CoroFree =
1666 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
1667
1668 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
1669
1670 // [dcl.fct.def.coroutine]p12
1671 // The selected deallocation function shall be called with the address of
1672 // the block of storage to be reclaimed as its first argument. If a
1673 // deallocation function with a parameter of type std::size_t is
1674 // used, the size of the block is passed as the corresponding argument.
1675 const auto *OpDeleteType =
1676 OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
1677 if (OpDeleteType->getNumParams() > DeleteArgs.size() &&
1678 S.getASTContext().hasSameUnqualifiedType(
1679 OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))
1680 DeleteArgs.push_back(FrameSize);
1681
1682 // Proposed Change of [dcl.fct.def.coroutine]p12 in P2014R0:
1683 // If deallocation function lookup finds a usual deallocation function with
1684 // a pointer parameter, size parameter and alignment parameter then this
1685 // will be the selected deallocation function, otherwise if lookup finds a
1686 // usual deallocation function with both a pointer parameter and a size
1687 // parameter, then this will be the selected deallocation function.
1688 // Otherwise, if lookup finds a usual deallocation function with only a
1689 // pointer parameter, then this will be the selected deallocation
1690 // function.
1691 //
1692 // So we are not forced to pass alignment to the deallocation function.
1693 if (S.getLangOpts().CoroAlignedAllocation &&
1694 OpDeleteType->getNumParams() > DeleteArgs.size() &&
1695 S.getASTContext().hasSameUnqualifiedType(
1696 OpDeleteType->getParamType(DeleteArgs.size()),
1697 FrameAlignment->getType()))
1698 DeleteArgs.push_back(FrameAlignment);
1699
1700 ExprResult DeleteExpr =
1701 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
1702 DeleteExpr =
1703 S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
1704 if (DeleteExpr.isInvalid())
1705 return false;
1706
1707 this->Allocate = NewExpr.get();
1708 this->Deallocate = DeleteExpr.get();
1709
1710 return true;
1711}
1712
1713bool CoroutineStmtBuilder::makeOnFallthrough() {
1714 assert(!IsPromiseDependentType &&
1715 "cannot make statement while the promise type is dependent");
1716
1717 // [dcl.fct.def.coroutine]/p6
1718 // If searches for the names return_void and return_value in the scope of
1719 // the promise type each find any declarations, the program is ill-formed.
1720 // [Note 1: If return_void is found, flowing off the end of a coroutine is
1721 // equivalent to a co_return with no operand. Otherwise, flowing off the end
1722 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
1723 // end note]
1724 bool HasRVoid, HasRValue;
1725 LookupResult LRVoid =
1726 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
1727 LookupResult LRValue =
1728 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
1729
1730 StmtResult Fallthrough;
1731 if (HasRVoid && HasRValue) {
1732 // FIXME Improve this diagnostic
1733 S.Diag(FD.getLocation(),
1734 diag::err_coroutine_promise_incompatible_return_functions)
1735 << PromiseRecordDecl;
1736 S.Diag(LRVoid.getRepresentativeDecl()->getLocation(),
1737 diag::note_member_first_declared_here)
1738 << LRVoid.getLookupName();
1739 S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
1740 diag::note_member_first_declared_here)
1741 << LRValue.getLookupName();
1742 return false;
1743 } else if (!HasRVoid && !HasRValue) {
1744 // We need to set 'Fallthrough'. Otherwise the other analysis part might
1745 // think the coroutine has defined a return_value method. So it might emit
1746 // **false** positive warning. e.g.,
1747 //
1748 // promise_without_return_func foo() {
1749 // co_await something();
1750 // }
1751 //
1752 // Then AnalysisBasedWarning would emit a warning about `foo()` lacking a
1753 // co_return statements, which isn't correct.
1754 Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());
1755 if (Fallthrough.isInvalid())
1756 return false;
1757 } else if (HasRVoid) {
1758 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
1759 /*IsImplicit=*/true);
1760 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
1761 if (Fallthrough.isInvalid())
1762 return false;
1763 }
1764
1765 this->OnFallthrough = Fallthrough.get();
1766 return true;
1767}
1768
1769bool CoroutineStmtBuilder::makeOnException() {
1770 // Try to form 'p.unhandled_exception();'
1771 assert(!IsPromiseDependentType &&
1772 "cannot make statement while the promise type is dependent");
1773
1774 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
1775
1776 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
1777 auto DiagID =
1778 RequireUnhandledException
1779 ? diag::err_coroutine_promise_unhandled_exception_required
1780 : diag::
1781 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1782 S.Diag(Loc, DiagID) << PromiseRecordDecl;
1783 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1784 << PromiseRecordDecl;
1785 return !RequireUnhandledException;
1786 }
1787
1788 // If exceptions are disabled, don't try to build OnException.
1789 if (!S.getLangOpts().CXXExceptions)
1790 return true;
1791
1792 ExprResult UnhandledException =
1793 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", {});
1794 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
1795 /*DiscardedValue*/ false);
1796 if (UnhandledException.isInvalid())
1797 return false;
1798
1799 // Since the body of the coroutine will be wrapped in try-catch, it will
1800 // be incompatible with SEH __try if present in a function.
1801 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
1802 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
1803 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1804 << Fn.getFirstCoroutineStmtKeyword();
1805 return false;
1806 }
1807
1808 this->OnException = UnhandledException.get();
1809 return true;
1810}
1811
1812bool CoroutineStmtBuilder::makeReturnObject() {
1813 // [dcl.fct.def.coroutine]p7
1814 // The expression promise.get_return_object() is used to initialize the
1815 // returned reference or prvalue result object of a call to a coroutine.
1816 ExprResult ReturnObject =
1817 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", {});
1818 if (ReturnObject.isInvalid())
1819 return false;
1820
1821 this->ReturnValue = ReturnObject.get();
1822 return true;
1823}
1824
1826 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1827 auto *MethodDecl = MbrRef->getMethodDecl();
1828 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1829 << MethodDecl;
1830 }
1831 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1832 << Fn.getFirstCoroutineStmtKeyword();
1833}
1834
1835bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1836 assert(!IsPromiseDependentType &&
1837 "cannot make statement while the promise type is dependent");
1838 assert(this->ReturnValue && "ReturnValue must be already formed");
1839
1840 QualType const GroType = this->ReturnValue->getType();
1841 assert(!GroType->isDependentType() &&
1842 "get_return_object type must no longer be dependent");
1843
1844 QualType const FnRetType = FD.getReturnType();
1845 assert(!FnRetType->isDependentType() &&
1846 "get_return_object type must no longer be dependent");
1847
1848 // The call to get_­return_­object is sequenced before the call to
1849 // initial_­suspend and is invoked at most once, but there are caveats
1850 // regarding on whether the prvalue result object may be initialized
1851 // directly/eager or delayed, depending on the types involved.
1852 //
1853 // More info at https://github.com/cplusplus/papers/issues/1414
1854 bool GroMatchesRetType = S.getASTContext().hasSameType(GroType, FnRetType);
1855
1856 if (FnRetType->isVoidType()) {
1857 ExprResult Res =
1858 S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
1859 if (Res.isInvalid())
1860 return false;
1861
1862 if (!GroMatchesRetType)
1863 this->ResultDecl = Res.get();
1864 return true;
1865 }
1866
1867 if (GroType->isVoidType()) {
1868 // Trigger a nice error message.
1869 InitializedEntity Entity =
1871 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1873 return false;
1874 }
1875
1877 clang::VarDecl *GroDecl = nullptr;
1878 if (GroMatchesRetType) {
1879 ReturnStmt = S.BuildReturnStmt(Loc, ReturnValue);
1880 } else {
1881 GroDecl = VarDecl::Create(
1882 S.Context, &FD, FD.getLocation(), FD.getLocation(),
1883 &S.PP.getIdentifierTable().get("__coro_gro"),
1884 S.BuildDecltypeType(ReturnValue).getCanonicalType(),
1885 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
1886 GroDecl->setImplicit();
1887
1888 S.CheckVariableDeclarationType(GroDecl);
1889 if (GroDecl->isInvalidDecl())
1890 return false;
1891
1892 InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
1893 ExprResult Res =
1894 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1895 if (Res.isInvalid())
1896 return false;
1897
1898 Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
1899 if (Res.isInvalid())
1900 return false;
1901
1902 S.AddInitializerToDecl(GroDecl, Res.get(),
1903 /*DirectInit=*/false);
1904
1905 S.FinalizeDeclaration(GroDecl);
1906
1907 // Form a declaration statement for the return declaration, so that AST
1908 // visitors can more easily find it.
1909 StmtResult GroDeclStmt =
1910 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
1911 if (GroDeclStmt.isInvalid())
1912 return false;
1913
1914 this->ResultDecl = GroDeclStmt.get();
1915
1916 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
1917 if (declRef.isInvalid())
1918 return false;
1919
1920 ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
1921 }
1922
1923 if (ReturnStmt.isInvalid()) {
1925 return false;
1926 }
1927
1928 if (!GroMatchesRetType &&
1929 cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
1930 GroDecl->setNRVOVariable(true);
1931
1932 this->ReturnStmt = ReturnStmt.get();
1933 return true;
1934}
1935
1936// Create a static_cast<T&&>(expr).
1938 if (T.isNull())
1939 T = E->getType();
1940 QualType TargetType = S.BuildReferenceType(
1941 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
1942 SourceLocation ExprLoc = E->getBeginLoc();
1943 TypeSourceInfo *TargetLoc =
1944 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
1945
1946 return S
1947 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
1948 SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
1949 .get();
1950}
1951
1952/// Build a variable declaration for move parameter.
1954 IdentifierInfo *II) {
1956 VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
1957 TInfo, SC_None);
1958 Decl->setImplicit();
1959 return Decl;
1960}
1961
1962// Build statements that move coroutine function parameters to the coroutine
1963// frame, and store them on the function scope info.
1965 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
1966 auto *FD = cast<FunctionDecl>(CurContext);
1967
1968 auto *ScopeInfo = getCurFunction();
1969 if (!ScopeInfo->CoroutineParameterMoves.empty())
1970 return false;
1971
1972 // [dcl.fct.def.coroutine]p13
1973 // When a coroutine is invoked, after initializing its parameters
1974 // ([expr.call]), a copy is created for each coroutine parameter. For a
1975 // parameter of type cv T, the copy is a variable of type cv T with
1976 // automatic storage duration that is direct-initialized from an xvalue of
1977 // type T referring to the parameter.
1978 for (auto *PD : FD->parameters()) {
1979 if (PD->getType()->isDependentType())
1980 continue;
1981
1982 // Preserve the referenced state for unused parameter diagnostics.
1983 bool DeclReferenced = PD->isReferenced();
1984
1985 ExprResult PDRefExpr =
1986 BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
1987 ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1988
1989 PD->setReferenced(DeclReferenced);
1990
1991 if (PDRefExpr.isInvalid())
1992 return false;
1993
1994 Expr *CExpr = nullptr;
1995 if (PD->getType()->getAsCXXRecordDecl() ||
1996 PD->getType()->isRValueReferenceType())
1997 CExpr = castForMoving(*this, PDRefExpr.get());
1998 else
1999 CExpr = PDRefExpr.get();
2000 // [dcl.fct.def.coroutine]p13
2001 // The initialization and destruction of each parameter copy occurs in the
2002 // context of the called coroutine.
2003 auto *D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
2004 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
2005
2006 // Convert decl to a statement.
2008 if (Stmt.isInvalid())
2009 return false;
2010
2011 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
2012 }
2013 return true;
2014}
2015
2018 if (!Res)
2019 return StmtError();
2020 return Res;
2021}
2022
2024 SourceLocation FuncLoc) {
2027
2028 IdentifierInfo const &TraitIdent =
2029 PP.getIdentifierTable().get("coroutine_traits");
2030
2031 NamespaceDecl *StdSpace = getStdNamespace();
2032 LookupResult Result(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
2033 bool Found = StdSpace && LookupQualifiedName(Result, StdSpace);
2034
2035 if (!Found) {
2036 // The goggles, we found nothing!
2037 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
2038 << "std::coroutine_traits";
2039 return nullptr;
2040 }
2041
2042 // coroutine_traits is required to be a class template.
2045 Result.suppressDiagnostics();
2046 NamedDecl *Found = *Result.begin();
2047 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
2048 return nullptr;
2049 }
2050
2052}
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines enum values for all the target-independent builtin functions.
Defines the clang::Expr interface and subclasses for C++ expressions.
TokenType getType() const
Returns the token's type, e.g.
Result
Implement __builtin_bit_cast and related operations.
llvm::MachO::Record Record
Definition MachO.h:31
Defines the clang::Preprocessor interface.
static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, SourceLocation Loc)
static bool DiagnoseTypeAwareAllocators(Sema &S, SourceLocation Loc, unsigned DiagnosticID, DeclarationName Name, QualType PromiseType)
static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn)
static void checkReturnStmtInCoroutine(Sema &S, FunctionScopeInfo *FSI)
static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static void applySafeElideContext(Expr *Operand)
static Expr * buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc)
Look up the std::nothrow object.
static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E)
static bool diagReturnOnAllocFailure(Sema &S, Expr *E, CXXRecordDecl *PromiseRecordDecl, FunctionScopeInfo &Fn)
static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, SourceLocation Loc, StringRef Name, MultiExprArg Args)
static Expr * castForMoving(Sema &S, Expr *E, QualType T=QualType())
static Expr * maybeTailCall(Sema &S, QualType RetType, Expr *E, SourceLocation Loc)
static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, StringRef Name, MultiExprArg Args)
static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, SourceLocation Loc, bool &Res)
static TypeSourceInfo * getTypeSourceInfoForStdAlignValT(Sema &S, SourceLocation Loc)
static bool isWithinCatchScope(Scope *S)
static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType, FunctionDecl *&OperatorDelete)
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
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...
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.
static bool checkSuspensionContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, SourceLocation Loc)
Look up the std::coroutine_handle<PromiseType>.
static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc, SmallVectorImpl< Expr * > &PlacementArgs)
static CompoundStmt * buildCoroutineBody(Stmt *Body, ASTContext &Context)
static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, SourceLocation KwLoc)
Look up the std::coroutine_traits<...>::promise_type for the given function type.
static bool isAttributedCoroAwaitElidable(const QualType &QT)
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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
DeclarationNameTable DeclarationNames
Definition ASTContext.h:809
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
CanQualType getCanonicalTagType(const TagDecl *TD) const
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition Expr.h:4553
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4573
Represents a C++ constructor within a class.
Definition DeclCXX.h:2620
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2132
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2271
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2131
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:75
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3129
Decl * getCalleeDecl()
Definition Expr.h:3123
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1603
Declaration of a class template.
void setExprNeedsCleanups(bool SideEffects)
Definition CleanupInfo.h:28
Represents a 'co_await' expression.
Definition ExprCXX.h:5365
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1746
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition StmtCXX.h:473
Represents the body of a coroutine.
Definition StmtCXX.h:320
static CoroutineBodyStmt * Create(const ASTContext &C, CtorArgs const &Args)
Definition StmtCXX.cpp:87
CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn, Stmt *Body)
Construct a CoroutineStmtBuilder and initialize the promise statement and initial/final suspends from...
bool buildDependentStatements()
Build the coroutine body statements that require a non-dependent promise type in order to construct.
bool buildStatements()
Build the coroutine body statements, including the "promise dependent" statements when the promise ty...
Represents a 'co_yield' expression.
Definition ExprCXX.h:5446
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1462
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition DeclBase.h:443
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
bool isInvalidDecl() const
Definition DeclBase.h:596
SourceLocation getLocation() const
Definition DeclBase.h:447
void setImplicit(bool I=true)
Definition DeclBase.h:602
DeclContext * getDeclContext()
Definition DeclBase.h:456
bool hasAttr() const
Definition DeclBase.h:585
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
Represents a 'co_await' expression while the type of the promise is dependent.
Definition ExprCXX.h:5397
RAII object that enters a new function expression evaluation context.
Represents an enum.
Definition Decl.h:4029
This represents one expression.
Definition Expr.h:112
bool isPRValue() const
Definition Expr.h:285
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:454
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:277
QualType getType() const
Definition Expr.h:144
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition Expr.h:526
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:2018
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Definition Decl.cpp:3646
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2792
bool isTypeAwareOperatorNewOrDelete() const
Determine whether this is a type aware operator new or delete.
Definition Decl.cpp:3554
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5362
ArrayRef< QualType > getParamTypes() const
Definition TypeBase.h:5647
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this function type.
Definition TypeBase.h:5796
QualType getReturnType() const
Definition TypeBase.h:4898
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)
Create an initialization from an initializer (which, for direct initialization from a parenthesized l...
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.
Describes an entity that is being initialized.
static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)
Create the initialization entity for the result of a function.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
Represents the results of name lookup.
Definition Lookup.h:147
bool isAmbiguous() const
Definition Lookup.h:324
const UnresolvedSetImpl & asUnresolvedSet() const
Definition Lookup.h:354
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition Lookup.h:576
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition Lookup.h:636
DeclarationName getLookupName() const
Gets the name to look up.
Definition Lookup.h:265
This represents a decl that may have a name.
Definition Decl.h:274
Represent a C++ namespace.
Definition Decl.h:592
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1181
decls_iterator decls_begin() const
Definition ExprCXX.h:3225
decls_iterator decls_end() const
Definition ExprCXX.h:3228
static ParenListExpr * Create(const ASTContext &Ctx, SourceLocation LParenLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc)
Create a paren list.
Definition Expr.cpp:4966
Represents a parameter to a function.
Definition Decl.h:1808
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
IdentifierTable & getIdentifierTable()
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8436
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8621
QualType getCanonicalType() const
Definition TypeBase.h:8488
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1556
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
bool isCatchScope() const
isCatchScope - Return true if this scope is a C++ catch statement.
Definition Scope.h:503
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:287
bool isFunctionScope() const
isFunctionScope() - Return true if this scope is a function scope.
Definition Scope.h:425
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Expr * get() const
Definition Sema.h:7850
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
FunctionDecl * FindUsualDeallocationFunction(SourceLocation StartLoc, ImplicitDeallocationParameters, DeclarationName Name, bool Diagnose=true)
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.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1141
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)
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9415
@ LookupOperatorName
Look up of an operator name (e.g., operator+) for use with operator overloading.
Definition Sema.h:9427
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
Definition Sema.h:9423
bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend)
Check that the expression co_await promise.final_suspend() shall not be potentially-throwing.
StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs)
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl *&Operator, ImplicitDeallocationParameters, bool Diagnose=true)
ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body)
bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword)
VarDecl * buildCoroutinePromise(SourceLocation Loc)
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
Definition Sema.h:7010
StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, bool IsImplicit=false)
Expr * BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs)
BuildBuiltinCallExpr - Create a call to a builtin function specified by Id.
ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, Expr *Awaiter, bool IsImplicit=false)
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition Sema.cpp:1725
ASTContext & Context
Definition Sema.h:1308
ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E)
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:81
ClassTemplateDecl * StdCoroutineTraitsCache
The C++ "std::coroutine_traits" template, which is defined in <coroutine_traits>
Definition Sema.h:3199
ASTContext & getASTContext() const
Definition Sema.h:939
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
EnumDecl * getStdAlignValT() const
NamedReturnInfo getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode=SimplerImplicitMoveMode::Normal)
Determine whether the given expression might be move-eligible or copy-elidable in either a (co_)retur...
StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E)
const LangOptions & getLangOpts() const
Definition Sema.h:932
Preprocessor & PP
Definition Sema.h:1307
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.
CleanupInfo Cleanup
Used to control the generation of ExprWithCleanups.
Definition Sema.h:7046
ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, UnresolvedLookupExpr *Lookup)
bool buildCoroutineParameterMoves(SourceLocation Loc)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1341
QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity)
Build a reference type.
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *input, bool RequiresADL=true)
Create a unary operation that may resolve to an overloaded operator.
ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1446
MaterializeTemporaryExpr * CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference)
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
bool isUnevaluatedContext() const
Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.
Definition Sema.h:8261
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
ClassTemplateDecl * lookupCoroutineTraits(SourceLocation KwLoc, SourceLocation FuncLoc)
Lookup 'coroutine_traits' in std namespace and std::experimental namespace.
DeclContext * computeDeclContext(QualType T)
Compute the DeclContext that is associated with the given type.
void CheckCompleteVariableDeclaration(VarDecl *VD)
QualType CheckTemplateIdType(ElaboratedTypeKeyword Keyword, TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, Scope *Scope, bool ForNestedNameSpecifier)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6821
ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
FullExprArg MakeFullDiscardedValueExpr(Expr *Arg)
Definition Sema.h:7871
NamespaceDecl * getStdNamespace() const
friend class InitializationSequence
Definition Sema.h:1588
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, TypeSourceInfo *Ty, Expr *E, SourceRange AngleBrackets, SourceRange Parens)
Definition SemaCast.cpp:338
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,...
void CheckVariableDeclarationType(VarDecl *NewVD)
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
ExprResult ActOnCXXThis(SourceLocation Loc)
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.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8743
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:86
child_range children()
Definition Stmt.cpp:304
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
Location wrapper for a TemplateArgument.
Represents a template argument.
Represents a declaration of a type.
Definition Decl.h:3531
A container of type source information.
Definition TypeBase.h:8407
The base class of the type hierarchy.
Definition TypeBase.h:1871
bool isVoidType() const
Definition TypeBase.h:9039
bool isBooleanType() const
Definition TypeBase.h:9176
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isVoidPointerType() const
Definition Type.cpp:749
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9333
bool isReferenceType() const
Definition TypeBase.h:8697
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2837
bool isRecordType() const
Definition TypeBase.h:8800
A reference to a name which we were able to look up during parsing but could not resolve to a specifi...
Definition ExprCXX.h:3390
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
Definition ExprCXX.cpp:432
void append(iterator I, iterator E)
A set of unresolved declarations.
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:924
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2130
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:932
void setNRVOVariable(bool NRVO)
Definition Decl.h:1528
Retains information about a function, method, or block that is currently being parsed.
Definition ScopeInfo.h:104
SourceLocation FirstCoroutineStmtLoc
First coroutine statement in the current function.
Definition ScopeInfo.h:183
std::pair< Stmt *, Stmt * > CoroutineSuspends
The initial and final coroutine suspend points.
Definition ScopeInfo.h:224
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
Definition ScopeInfo.h:217
bool hasInvalidCoroutineSuspends() const
Definition ScopeInfo.h:544
StringRef getFirstCoroutineStmtKeyword() const
Definition ScopeInfo.h:522
SourceLocation FirstReturnLoc
First 'return' statement in the current function.
Definition ScopeInfo.h:186
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
AllocationFunctionScope
The scope in which to find allocation functions.
Definition Sema.h:791
@ Both
Look for allocation functions in both the global scope and in the scope of the allocated class.
Definition Sema.h:799
@ Global
Only look for allocation functions in the global scope.
Definition Sema.h:793
@ Class
Only look for allocation functions in the scope of the allocated class.
Definition Sema.h:796
AlignedAllocationMode alignedAllocationModeFromBool(bool IsAligned)
Definition ExprCXX.h:2273
Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)
Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...
Definition IgnoreExpr.h:24
@ RQ_RValue
An rvalue ref-qualifier was provided (&&).
Definition TypeBase.h:1799
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
@ SC_None
Definition Specifiers.h:251
bool isAlignedAllocation(AlignedAllocationMode Mode)
Definition ExprCXX.h:2269
ExprResult ExprEmpty()
Definition Ownership.h:272
MutableArrayRef< Expr * > MultiExprArg
Definition Ownership.h:259
StmtResult StmtError()
Definition Ownership.h:266
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ExprResult ExprError()
Definition Ownership.h:265
@ Keyword
The name has been typo-corrected to a keyword.
Definition Sema.h:562
Expr * IgnoreImplicitSingleStep(Expr *E)
Definition IgnoreExpr.h:101
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:140
Expr * IgnoreParensSingleStep(Expr *E)
Definition IgnoreExpr.h:157
U cast(CodeGen::Address addr)
Definition Address.h:327
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:5982
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
OpaqueValueExpr * OpaqueValue
ArrayRef< Stmt * > ParamMoves
Definition StmtCXX.h:361
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SizedDeallocationMode PassSize
Definition ExprCXX.h:2344
enum clang::Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext