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