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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/Sema/SemaCoroutine.cpp