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