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