clang 18.0.0git
SemaCoroutine.cpp
Go to the documentation of this file.
1//===-- SemaCoroutine.cpp - Semantic Analysis for Coroutines --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for C++ Coroutines.
10//
11// This file contains references to sections of the Coroutines TS, which
12// can be found at http://wg21.link/coroutines.
13//
14//===----------------------------------------------------------------------===//
15
17#include "clang/AST/ASTLambda.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/StmtCXX.h"
24#include "clang/Sema/Overload.h"
27#include "llvm/ADT/SmallSet.h"
28
29using namespace clang;
30using namespace sema;
31
32static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
33 SourceLocation Loc, bool &Res) {
36 // Suppress diagnostics when a private member is selected. The same warnings
37 // will be produced again when building the call.
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.
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) {
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>(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
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(TemplateName(CoroTraits), KwLoc, 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("promise_type"), KwLoc,
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(Promise);
116
117 auto buildElaboratedType = [&]() {
118 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace());
119 NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
120 CoroTrait.getTypePtr());
121 return S.Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS,
122 PromiseType);
123 };
124
125 if (!PromiseType->getAsCXXRecordDecl()) {
126 S.Diag(FuncLoc,
127 diag::err_implied_std_coroutine_traits_promise_type_not_class)
128 << buildElaboratedType();
129 return QualType();
130 }
131 if (S.RequireCompleteType(FuncLoc, buildElaboratedType(),
132 diag::err_coroutine_promise_type_incomplete))
133 return QualType();
134
135 return PromiseType;
136}
137
138/// Look up the std::coroutine_handle<PromiseType>.
140 SourceLocation Loc) {
141 if (PromiseType.isNull())
142 return QualType();
143
144 NamespaceDecl *CoroNamespace = S.getStdNamespace();
145 assert(CoroNamespace && "Should already be diagnosed");
146
147 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
149 if (!S.LookupQualifiedName(Result, CoroNamespace)) {
150 S.Diag(Loc, diag::err_implied_coroutine_type_not_found)
151 << "std::coroutine_handle";
152 return QualType();
153 }
154
155 ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>();
156 if (!CoroHandle) {
157 Result.suppressDiagnostics();
158 // We found something weird. Complain about the first thing we found.
159 NamedDecl *Found = *Result.begin();
160 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle);
161 return QualType();
162 }
163
164 // Form template argument list for coroutine_handle<Promise>.
165 TemplateArgumentListInfo Args(Loc, Loc);
167 TemplateArgument(PromiseType),
168 S.Context.getTrivialTypeSourceInfo(PromiseType, Loc)));
169
170 // Build the template-id.
171 QualType CoroHandleType =
172 S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args);
173 if (CoroHandleType.isNull())
174 return QualType();
175 if (S.RequireCompleteType(Loc, CoroHandleType,
176 diag::err_coroutine_type_missing_specialization))
177 return QualType();
178
179 return CoroHandleType;
180}
181
183 StringRef Keyword) {
184 // [expr.await]p2 dictates that 'co_await' and 'co_yield' must be used within
185 // a function body.
186 // FIXME: This also covers [expr.await]p2: "An await-expression shall not
187 // appear in a default argument." But the diagnostic QoI here could be
188 // improved to inform the user that default arguments specifically are not
189 // allowed.
190 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
191 if (!FD) {
192 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
193 ? diag::err_coroutine_objc_method
194 : diag::err_coroutine_outside_function) << Keyword;
195 return false;
196 }
197
198 // An enumeration for mapping the diagnostic type to the correct diagnostic
199 // selection index.
200 enum InvalidFuncDiag {
201 DiagCtor = 0,
202 DiagDtor,
203 DiagMain,
204 DiagConstexpr,
205 DiagAutoRet,
206 DiagVarargs,
207 DiagConsteval,
208 };
209 bool Diagnosed = false;
210 auto DiagInvalid = [&](InvalidFuncDiag ID) {
211 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
212 Diagnosed = true;
213 return false;
214 };
215
216 // Diagnose when a constructor, destructor
217 // or the function 'main' are declared as a coroutine.
218 auto *MD = dyn_cast<CXXMethodDecl>(FD);
219 // [class.ctor]p11: "A constructor shall not be a coroutine."
220 if (MD && isa<CXXConstructorDecl>(MD))
221 return DiagInvalid(DiagCtor);
222 // [class.dtor]p17: "A destructor shall not be a coroutine."
223 else if (MD && isa<CXXDestructorDecl>(MD))
224 return DiagInvalid(DiagDtor);
225 // [basic.start.main]p3: "The function main shall not be a coroutine."
226 else if (FD->isMain())
227 return DiagInvalid(DiagMain);
228
229 // Emit a diagnostics for each of the following conditions which is not met.
230 // [expr.const]p2: "An expression e is a core constant expression unless the
231 // evaluation of e [...] would evaluate one of the following expressions:
232 // [...] an await-expression [...] a yield-expression."
233 if (FD->isConstexpr())
234 DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);
235 // [dcl.spec.auto]p15: "A function declared with a return type that uses a
236 // placeholder type shall not be a coroutine."
237 if (FD->getReturnType()->isUndeducedType())
238 DiagInvalid(DiagAutoRet);
239 // [dcl.fct.def.coroutine]p1
240 // The parameter-declaration-clause of the coroutine shall not terminate with
241 // an ellipsis that is not part of a parameter-declaration.
242 if (FD->isVariadic())
243 DiagInvalid(DiagVarargs);
244
245 return !Diagnosed;
246}
247
248/// Build a call to 'operator co_await' if there is a suitable operator for
249/// the given expression.
251 UnresolvedLookupExpr *Lookup) {
252 UnresolvedSet<16> Functions;
253 Functions.append(Lookup->decls_begin(), Lookup->decls_end());
254 return CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
255}
256
258 SourceLocation Loc, Expr *E) {
259 ExprResult R = SemaRef.BuildOperatorCoawaitLookupExpr(S, Loc);
260 if (R.isInvalid())
261 return ExprError();
262 return SemaRef.BuildOperatorCoawaitCall(Loc, E,
263 cast<UnresolvedLookupExpr>(R.get()));
264}
265
267 SourceLocation Loc) {
268 QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
269 if (CoroHandleType.isNull())
270 return ExprError();
271
272 DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType);
273 LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc,
275 if (!S.LookupQualifiedName(Found, LookupCtx)) {
276 S.Diag(Loc, diag::err_coroutine_handle_missing_member)
277 << "from_address";
278 return ExprError();
279 }
280
281 Expr *FramePtr =
282 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
283
284 CXXScopeSpec SS;
285 ExprResult FromAddr =
286 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
287 if (FromAddr.isInvalid())
288 return ExprError();
289
290 return S.BuildCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc);
291}
292
294 enum AwaitCallType { ACT_Ready, ACT_Suspend, ACT_Resume };
295 Expr *Results[3];
298};
299
301 StringRef Name, MultiExprArg Args) {
302 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
303
304 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
305 CXXScopeSpec SS;
307 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
308 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
309 /*Scope=*/nullptr);
310 if (Result.isInvalid())
311 return ExprError();
312
313 // We meant exactly what we asked for. No need for typo correction.
314 if (auto *TE = dyn_cast<TypoExpr>(Result.get())) {
315 S.clearDelayedTypo(TE);
316 S.Diag(Loc, diag::err_no_member)
317 << NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
318 << Base->getSourceRange();
319 return ExprError();
320 }
321
322 auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
323 return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
324}
325
326// See if return type is coroutine-handle and if so, invoke builtin coro-resume
327// on its address. This is to enable the support for coroutine-handle
328// returning await_suspend that results in a guaranteed tail call to the target
329// coroutine.
330static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
331 SourceLocation Loc) {
332 if (RetType->isReferenceType())
333 return nullptr;
334 Type const *T = RetType.getTypePtr();
335 if (!T->isClassType() && !T->isStructureType())
336 return nullptr;
337
338 // FIXME: Add convertability check to coroutine_handle<>. Possibly via
339 // EvaluateBinaryTypeTrait(BTT_IsConvertible, ...) which is at the moment
340 // a private function in SemaExprCXX.cpp
341
342 ExprResult AddressExpr = buildMemberCall(S, E, Loc, "address", std::nullopt);
343 if (AddressExpr.isInvalid())
344 return nullptr;
345
346 Expr *JustAddress = AddressExpr.get();
347
348 // FIXME: Without optimizations, the temporary result from `await_suspend()`
349 // may be put on the coroutine frame since the coroutine frame constructor
350 // will think the temporary variable will escape from the
351 // `coroutine_handle<>::address()` call. This is problematic since the
352 // coroutine should be considered to be suspended after it enters
353 // `await_suspend` so it shouldn't access/update the coroutine frame after
354 // that.
355 //
356 // See https://github.com/llvm/llvm-project/issues/65054 for the report.
357 //
358 // The long term solution may wrap the whole logic about `await-suspend`
359 // into a standalone function. This is similar to the proposed solution
360 // in tryMarkAwaitSuspendNoInline. See the comments there for details.
361 //
362 // The short term solution here is to mark `coroutine_handle<>::address()`
363 // function as always-inline so that the coroutine frame constructor won't
364 // think the temporary result is escaped incorrectly.
365 if (auto *FD = cast<CallExpr>(JustAddress)->getDirectCallee())
366 if (!FD->hasAttr<AlwaysInlineAttr>() && !FD->hasAttr<NoInlineAttr>())
367 FD->addAttr(AlwaysInlineAttr::CreateImplicit(S.getASTContext(),
368 FD->getLocation()));
369
370 // Check that the type of AddressExpr is void*
371 if (!JustAddress->getType().getTypePtr()->isVoidPointerType())
372 S.Diag(cast<CallExpr>(JustAddress)->getCalleeDecl()->getLocation(),
373 diag::warn_coroutine_handle_address_invalid_return_type)
374 << JustAddress->getType();
375
376 // Clean up temporary objects so that they don't live across suspension points
377 // unnecessarily. We choose to clean up before the call to
378 // __builtin_coro_resume so that the cleanup code are not inserted in-between
379 // the resume call and return instruction, which would interfere with the
380 // musttail call contract.
381 JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
382 return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume,
383 JustAddress);
384}
385
386/// The await_suspend call performed by co_await is essentially asynchronous
387/// to the execution of the coroutine. Inlining it normally into an unsplit
388/// coroutine can cause miscompilation because the coroutine CFG misrepresents
389/// the true control flow of the program: things that happen in the
390/// await_suspend are not guaranteed to happen prior to the resumption of the
391/// coroutine, and things that happen after the resumption of the coroutine
392/// (including its exit and the potential deallocation of the coroutine frame)
393/// are not guaranteed to happen only after the end of await_suspend.
394///
395/// See https://github.com/llvm/llvm-project/issues/56301 and
396/// https://reviews.llvm.org/D157070 for the example and the full discussion.
397///
398/// The short-term solution to this problem is to mark the call as uninlinable.
399/// But we don't want to do this if the call is known to be trivial, which is
400/// very common.
401///
402/// The long-term solution may introduce patterns like:
403///
404/// call @llvm.coro.await_suspend(ptr %awaiter, ptr %handle,
405/// ptr @awaitSuspendFn)
406///
407/// Then it is much easier to perform the safety analysis in the middle end.
408/// If it is safe to inline the call to awaitSuspend, we can replace it in the
409/// CoroEarly pass. Otherwise we could replace it in the CoroSplit pass.
411 CallExpr *AwaitSuspend) {
412 // The method here to extract the awaiter decl is not precise.
413 // This is intentional. Since it is hard to perform the analysis in the
414 // frontend due to the complexity of C++'s type systems.
415 // And we prefer to perform such analysis in the middle end since it is
416 // easier to implement and more powerful.
417 CXXRecordDecl *AwaiterDecl =
419
420 if (AwaiterDecl && AwaiterDecl->field_empty())
421 return;
422
423 FunctionDecl *FD = AwaitSuspend->getDirectCallee();
424
425 assert(FD);
426
427 // If the `await_suspend()` function is marked as `always_inline` explicitly,
428 // we should give the user the right to control the codegen.
429 if (FD->hasAttr<NoInlineAttr>() || FD->hasAttr<AlwaysInlineAttr>())
430 return;
431
432 // This is problematic if the user calls the await_suspend standalone. But on
433 // the on hand, it is not incorrect semantically since inlining is not part
434 // of the standard. On the other hand, it is relatively rare to call
435 // the await_suspend function standalone.
436 //
437 // And given we've already had the long-term plan, the current workaround
438 // looks relatively tolerant.
439 FD->addAttr(
440 NoInlineAttr::CreateImplicit(S.getASTContext(), FD->getLocation()));
441}
442
443/// Build calls to await_ready, await_suspend, and await_resume for a co_await
444/// expression.
445/// The generated AST tries to clean up temporary objects as early as
446/// possible so that they don't live across suspension points if possible.
447/// Having temporary objects living across suspension points unnecessarily can
448/// lead to large frame size, and also lead to memory corruptions if the
449/// coroutine frame is destroyed after coming back from suspension. This is done
450/// by wrapping both the await_ready call and the await_suspend call with
451/// ExprWithCleanups. In the end of this function, we also need to explicitly
452/// set cleanup state so that the CoawaitExpr is also wrapped with an
453/// ExprWithCleanups to clean up the awaiter associated with the co_await
454/// expression.
456 SourceLocation Loc, Expr *E) {
457 OpaqueValueExpr *Operand = new (S.Context)
458 OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
459
460 // Assume valid until we see otherwise.
461 // Further operations are responsible for setting IsInalid to true.
462 ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/false};
463
465
466 auto BuildSubExpr = [&](ACT CallType, StringRef Func,
467 MultiExprArg Arg) -> Expr * {
468 ExprResult Result = buildMemberCall(S, Operand, Loc, Func, Arg);
469 if (Result.isInvalid()) {
470 Calls.IsInvalid = true;
471 return nullptr;
472 }
473 Calls.Results[CallType] = Result.get();
474 return Result.get();
475 };
476
477 CallExpr *AwaitReady = cast_or_null<CallExpr>(
478 BuildSubExpr(ACT::ACT_Ready, "await_ready", std::nullopt));
479 if (!AwaitReady)
480 return Calls;
481 if (!AwaitReady->getType()->isDependentType()) {
482 // [expr.await]p3 [...]
483 // — await-ready is the expression e.await_ready(), contextually converted
484 // to bool.
485 ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady);
486 if (Conv.isInvalid()) {
487 S.Diag(AwaitReady->getDirectCallee()->getBeginLoc(),
488 diag::note_await_ready_no_bool_conversion);
489 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
490 << AwaitReady->getDirectCallee() << E->getSourceRange();
491 Calls.IsInvalid = true;
492 } else
493 Calls.Results[ACT::ACT_Ready] = S.MaybeCreateExprWithCleanups(Conv.get());
494 }
495
496 ExprResult CoroHandleRes =
497 buildCoroutineHandle(S, CoroPromise->getType(), Loc);
498 if (CoroHandleRes.isInvalid()) {
499 Calls.IsInvalid = true;
500 return Calls;
501 }
502 Expr *CoroHandle = CoroHandleRes.get();
503 CallExpr *AwaitSuspend = cast_or_null<CallExpr>(
504 BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
505 if (!AwaitSuspend)
506 return Calls;
507 if (!AwaitSuspend->getType()->isDependentType()) {
508 // [expr.await]p3 [...]
509 // - await-suspend is the expression e.await_suspend(h), which shall be
510 // a prvalue of type void, bool, or std::coroutine_handle<Z> for some
511 // type Z.
512 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
513
514 // We need to mark await_suspend as noinline temporarily. See the comment
515 // of tryMarkAwaitSuspendNoInline for details.
516 tryMarkAwaitSuspendNoInline(S, Operand, AwaitSuspend);
517
518 // Support for coroutine_handle returning await_suspend.
519 if (Expr *TailCallSuspend =
520 maybeTailCall(S, RetType, AwaitSuspend, Loc))
521 // Note that we don't wrap the expression with ExprWithCleanups here
522 // because that might interfere with tailcall contract (e.g. inserting
523 // clean up instructions in-between tailcall and return). Instead
524 // ExprWithCleanups is wrapped within maybeTailCall() prior to the resume
525 // call.
526 Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
527 else {
528 // non-class prvalues always have cv-unqualified types
529 if (RetType->isReferenceType() ||
530 (!RetType->isBooleanType() && !RetType->isVoidType())) {
531 S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
532 diag::err_await_suspend_invalid_return_type)
533 << RetType;
534 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
535 << AwaitSuspend->getDirectCallee();
536 Calls.IsInvalid = true;
537 } else
538 Calls.Results[ACT::ACT_Suspend] =
539 S.MaybeCreateExprWithCleanups(AwaitSuspend);
540 }
541 }
542
543 BuildSubExpr(ACT::ACT_Resume, "await_resume", std::nullopt);
544
545 // Make sure the awaiter object gets a chance to be cleaned up.
547
548 return Calls;
549}
550
552 SourceLocation Loc, StringRef Name,
553 MultiExprArg Args) {
554
555 // Form a reference to the promise.
556 ExprResult PromiseRef = S.BuildDeclRefExpr(
557 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
558 if (PromiseRef.isInvalid())
559 return ExprError();
560
561 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
562}
563
565 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
566 auto *FD = cast<FunctionDecl>(CurContext);
567 bool IsThisDependentType = [&] {
568 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD))
569 return MD->isImplicitObjectMemberFunction() &&
570 MD->getThisType()->isDependentType();
571 return false;
572 }();
573
574 QualType T = FD->getType()->isDependentType() || IsThisDependentType
576 : lookupPromiseType(*this, FD, Loc);
577 if (T.isNull())
578 return nullptr;
579
580 auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
581 &PP.getIdentifierTable().get("__promise"), T,
583 VD->setImplicit();
585 if (VD->isInvalidDecl())
586 return nullptr;
587
588 auto *ScopeInfo = getCurFunction();
589
590 // Build a list of arguments, based on the coroutine function's arguments,
591 // that if present will be passed to the promise type's constructor.
592 llvm::SmallVector<Expr *, 4> CtorArgExprs;
593
594 // Add implicit object parameter.
595 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
596 if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
597 ExprResult ThisExpr = ActOnCXXThis(Loc);
598 if (ThisExpr.isInvalid())
599 return nullptr;
600 ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
601 if (ThisExpr.isInvalid())
602 return nullptr;
603 CtorArgExprs.push_back(ThisExpr.get());
604 }
605 }
606
607 // Add the coroutine function's parameters.
608 auto &Moves = ScopeInfo->CoroutineParameterMoves;
609 for (auto *PD : FD->parameters()) {
610 if (PD->getType()->isDependentType())
611 continue;
612
613 auto RefExpr = ExprEmpty();
614 auto Move = Moves.find(PD);
615 assert(Move != Moves.end() &&
616 "Coroutine function parameter not inserted into move map");
617 // If a reference to the function parameter exists in the coroutine
618 // frame, use that reference.
619 auto *MoveDecl =
620 cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
621 RefExpr =
622 BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
623 ExprValueKind::VK_LValue, FD->getLocation());
624 if (RefExpr.isInvalid())
625 return nullptr;
626 CtorArgExprs.push_back(RefExpr.get());
627 }
628
629 // If we have a non-zero number of constructor arguments, try to use them.
630 // Otherwise, fall back to the promise type's default constructor.
631 if (!CtorArgExprs.empty()) {
632 // Create an initialization sequence for the promise type using the
633 // constructor arguments, wrapped in a parenthesized list expression.
634 Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(),
635 CtorArgExprs, FD->getLocation());
638 VD->getLocation(), /*DirectInit=*/true, PLE);
639 InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
640 /*TopLevelOfInitList=*/false,
641 /*TreatUnavailableAsInvalid=*/false);
642
643 // [dcl.fct.def.coroutine]5.7
644 // promise-constructor-arguments is determined as follows: overload
645 // resolution is performed on a promise constructor call created by
646 // assembling an argument list q_1 ... q_n . If a viable constructor is
647 // found ([over.match.viable]), then promise-constructor-arguments is ( q_1
648 // , ..., q_n ), otherwise promise-constructor-arguments is empty.
649 if (InitSeq) {
650 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
651 if (Result.isInvalid()) {
652 VD->setInvalidDecl();
653 } else if (Result.get()) {
654 VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
655 VD->setInitStyle(VarDecl::CallInit);
657 }
658 } else
660 } else
662
663 FD->addDecl(VD);
664 return VD;
665}
666
667/// Check that this is a context in which a coroutine suspension can appear.
669 StringRef Keyword,
670 bool IsImplicit = false) {
671 if (!isValidCoroutineContext(S, Loc, Keyword))
672 return nullptr;
673
674 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
675
676 auto *ScopeInfo = S.getCurFunction();
677 assert(ScopeInfo && "missing function scope for function");
678
679 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
680 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
681
682 if (ScopeInfo->CoroutinePromise)
683 return ScopeInfo;
684
686 return nullptr;
687
688 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
689 if (!ScopeInfo->CoroutinePromise)
690 return nullptr;
691
692 return ScopeInfo;
693}
694
695/// Recursively check \p E and all its children to see if any call target
696/// (including constructor call) is declared noexcept. Also any value returned
697/// from the call has a noexcept destructor.
698static void checkNoThrow(Sema &S, const Stmt *E,
699 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {
700 auto checkDeclNoexcept = [&](const Decl *D, bool IsDtor = false) {
701 // In the case of dtor, the call to dtor is implicit and hence we should
702 // pass nullptr to canCalleeThrow.
703 if (Sema::canCalleeThrow(S, IsDtor ? nullptr : cast<Expr>(E), D)) {
704 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
705 // co_await promise.final_suspend() could end up calling
706 // __builtin_coro_resume for symmetric transfer if await_suspend()
707 // returns a handle. In that case, even __builtin_coro_resume is not
708 // declared as noexcept and may throw, it does not throw _into_ the
709 // coroutine that just suspended, but rather throws back out from
710 // whoever called coroutine_handle::resume(), hence we claim that
711 // logically it does not throw.
712 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)
713 return;
714 }
715 if (ThrowingDecls.empty()) {
716 // [dcl.fct.def.coroutine]p15
717 // The expression co_await promise.final_suspend() shall not be
718 // potentially-throwing ([except.spec]).
719 //
720 // First time seeing an error, emit the error message.
721 S.Diag(cast<FunctionDecl>(S.CurContext)->getLocation(),
722 diag::err_coroutine_promise_final_suspend_requires_nothrow);
723 }
724 ThrowingDecls.insert(D);
725 }
726 };
727
728 if (auto *CE = dyn_cast<CXXConstructExpr>(E)) {
729 CXXConstructorDecl *Ctor = CE->getConstructor();
730 checkDeclNoexcept(Ctor);
731 // Check the corresponding destructor of the constructor.
732 checkDeclNoexcept(Ctor->getParent()->getDestructor(), /*IsDtor=*/true);
733 } else if (auto *CE = dyn_cast<CallExpr>(E)) {
734 if (CE->isTypeDependent())
735 return;
736
737 checkDeclNoexcept(CE->getCalleeDecl());
738 QualType ReturnType = CE->getCallReturnType(S.getASTContext());
739 // Check the destructor of the call return type, if any.
740 if (ReturnType.isDestructedType() ==
742 const auto *T =
743 cast<RecordType>(ReturnType.getCanonicalType().getTypePtr());
744 checkDeclNoexcept(cast<CXXRecordDecl>(T->getDecl())->getDestructor(),
745 /*IsDtor=*/true);
746 }
747 } else
748 for (const auto *Child : E->children()) {
749 if (!Child)
750 continue;
751 checkNoThrow(S, Child, ThrowingDecls);
752 }
753}
754
755bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
757 // We first collect all declarations that should not throw but not declared
758 // with noexcept. We then sort them based on the location before printing.
759 // This is to avoid emitting the same note multiple times on the same
760 // declaration, and also provide a deterministic order for the messages.
761 checkNoThrow(*this, FinalSuspend, ThrowingDecls);
762 auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(),
763 ThrowingDecls.end()};
764 sort(SortedDecls, [](const Decl *A, const Decl *B) {
765 return A->getEndLoc() < B->getEndLoc();
766 });
767 for (const auto *D : SortedDecls) {
768 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
769 }
770 return ThrowingDecls.empty();
771}
772
774 StringRef Keyword) {
775 if (!checkCoroutineContext(*this, KWLoc, Keyword))
776 return false;
777 auto *ScopeInfo = getCurFunction();
778 assert(ScopeInfo->CoroutinePromise);
779
780 // If we have existing coroutine statements then we have already built
781 // the initial and final suspend points.
782 if (!ScopeInfo->NeedsCoroutineSuspends)
783 return true;
784
785 ScopeInfo->setNeedsCoroutineSuspends(false);
786
787 auto *Fn = cast<FunctionDecl>(CurContext);
788 SourceLocation Loc = Fn->getLocation();
789 // Build the initial suspend point
790 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
791 ExprResult Operand = buildPromiseCall(*this, ScopeInfo->CoroutinePromise,
792 Loc, Name, std::nullopt);
793 if (Operand.isInvalid())
794 return StmtError();
795 ExprResult Suspend =
796 buildOperatorCoawaitCall(*this, SC, Loc, Operand.get());
797 if (Suspend.isInvalid())
798 return StmtError();
799 Suspend = BuildResolvedCoawaitExpr(Loc, Operand.get(), Suspend.get(),
800 /*IsImplicit*/ true);
801 Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
802 if (Suspend.isInvalid()) {
803 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
804 << ((Name == "initial_suspend") ? 0 : 1);
805 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
806 return StmtError();
807 }
808 return cast<Stmt>(Suspend.get());
809 };
810
811 StmtResult InitSuspend = buildSuspends("initial_suspend");
812 if (InitSuspend.isInvalid())
813 return true;
814
815 StmtResult FinalSuspend = buildSuspends("final_suspend");
816 if (FinalSuspend.isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.get()))
817 return true;
818
819 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
820
821 return true;
822}
823
824// Recursively walks up the scope hierarchy until either a 'catch' or a function
825// scope is found, whichever comes first.
826static bool isWithinCatchScope(Scope *S) {
827 // 'co_await' and 'co_yield' keywords are disallowed within catch blocks, but
828 // lambdas that use 'co_await' are allowed. The loop below ends when a
829 // function scope is found in order to ensure the following behavior:
830 //
831 // void foo() { // <- function scope
832 // try { //
833 // co_await x; // <- 'co_await' is OK within a function scope
834 // } catch { // <- catch scope
835 // co_await x; // <- 'co_await' is not OK within a catch scope
836 // []() { // <- function scope
837 // co_await x; // <- 'co_await' is OK within a function scope
838 // }();
839 // }
840 // }
841 while (S && !S->isFunctionScope()) {
842 if (S->isCatchScope())
843 return true;
844 S = S->getParent();
845 }
846 return false;
847}
848
849// [expr.await]p2, emphasis added: "An await-expression shall appear only in
850// a *potentially evaluated* expression within the compound-statement of a
851// function-body *outside of a handler* [...] A context within a function
852// where an await-expression can appear is called a suspension context of the
853// function."
855 StringRef Keyword) {
856 // First emphasis of [expr.await]p2: must be a potentially evaluated context.
857 // That is, 'co_await' and 'co_yield' cannot appear in subexpressions of
858 // \c sizeof.
859 if (S.isUnevaluatedContext()) {
860 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
861 return false;
862 }
863
864 // Second emphasis of [expr.await]p2: must be outside of an exception handler.
866 S.Diag(Loc, diag::err_coroutine_within_handler) << Keyword;
867 return false;
868 }
869
870 return true;
871}
872
874 if (!checkSuspensionContext(*this, Loc, "co_await"))
875 return ExprError();
876
877 if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
879 return ExprError();
880 }
881
882 if (E->hasPlaceholderType()) {
884 if (R.isInvalid()) return ExprError();
885 E = R.get();
886 }
888 if (Lookup.isInvalid())
889 return ExprError();
890 return BuildUnresolvedCoawaitExpr(Loc, E,
891 cast<UnresolvedLookupExpr>(Lookup.get()));
892}
893
895 DeclarationName OpName =
897 LookupResult Operators(*this, OpName, SourceLocation(),
899 LookupName(Operators, S);
900
901 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
902 const auto &Functions = Operators.asUnresolvedSet();
903 bool IsOverloaded =
904 Functions.size() > 1 ||
905 (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
907 Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
908 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded,
909 Functions.begin(), Functions.end());
910 assert(CoawaitOp);
911 return CoawaitOp;
912}
913
914// Attempts to resolve and build a CoawaitExpr from "raw" inputs, bailing out to
915// DependentCoawaitExpr if needed.
917 UnresolvedLookupExpr *Lookup) {
918 auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
919 if (!FSI)
920 return ExprError();
921
922 if (Operand->hasPlaceholderType()) {
923 ExprResult R = CheckPlaceholderExpr(Operand);
924 if (R.isInvalid())
925 return ExprError();
926 Operand = R.get();
927 }
928
929 auto *Promise = FSI->CoroutinePromise;
930 if (Promise->getType()->isDependentType()) {
931 Expr *Res = new (Context)
932 DependentCoawaitExpr(Loc, Context.DependentTy, Operand, Lookup);
933 return Res;
934 }
935
936 auto *RD = Promise->getType()->getAsCXXRecordDecl();
937 auto *Transformed = Operand;
938 if (lookupMember(*this, "await_transform", RD, Loc)) {
939 ExprResult R =
940 buildPromiseCall(*this, Promise, Loc, "await_transform", Operand);
941 if (R.isInvalid()) {
942 Diag(Loc,
943 diag::note_coroutine_promise_implicit_await_transform_required_here)
944 << Operand->getSourceRange();
945 return ExprError();
946 }
947 Transformed = R.get();
948 }
949 ExprResult Awaiter = BuildOperatorCoawaitCall(Loc, Transformed, Lookup);
950 if (Awaiter.isInvalid())
951 return ExprError();
952
953 return BuildResolvedCoawaitExpr(Loc, Operand, Awaiter.get());
954}
955
957 Expr *Awaiter, bool IsImplicit) {
958 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
959 if (!Coroutine)
960 return ExprError();
961
962 if (Awaiter->hasPlaceholderType()) {
963 ExprResult R = CheckPlaceholderExpr(Awaiter);
964 if (R.isInvalid()) return ExprError();
965 Awaiter = R.get();
966 }
967
968 if (Awaiter->getType()->isDependentType()) {
969 Expr *Res = new (Context)
970 CoawaitExpr(Loc, Context.DependentTy, Operand, Awaiter, IsImplicit);
971 return Res;
972 }
973
974 // If the expression is a temporary, materialize it as an lvalue so that we
975 // can use it multiple times.
976 if (Awaiter->isPRValue())
977 Awaiter = CreateMaterializeTemporaryExpr(Awaiter->getType(), Awaiter, true);
978
979 // The location of the `co_await` token cannot be used when constructing
980 // the member call expressions since it's before the location of `Expr`, which
981 // is used as the start of the member call expression.
982 SourceLocation CallLoc = Awaiter->getExprLoc();
983
984 // Build the await_ready, await_suspend, await_resume calls.
986 buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, Awaiter);
987 if (RSS.IsInvalid)
988 return ExprError();
989
990 Expr *Res = new (Context)
991 CoawaitExpr(Loc, Operand, Awaiter, RSS.Results[0], RSS.Results[1],
992 RSS.Results[2], RSS.OpaqueValue, IsImplicit);
993
994 return Res;
995}
996
998 if (!checkSuspensionContext(*this, Loc, "co_yield"))
999 return ExprError();
1000
1001 if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
1003 return ExprError();
1004 }
1005
1006 // Build yield_value call.
1007 ExprResult Awaitable = buildPromiseCall(
1008 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
1009 if (Awaitable.isInvalid())
1010 return ExprError();
1011
1012 // Build 'operator co_await' call.
1013 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
1014 if (Awaitable.isInvalid())
1015 return ExprError();
1016
1017 return BuildCoyieldExpr(Loc, Awaitable.get());
1018}
1020 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
1021 if (!Coroutine)
1022 return ExprError();
1023
1024 if (E->hasPlaceholderType()) {
1026 if (R.isInvalid()) return ExprError();
1027 E = R.get();
1028 }
1029
1030 Expr *Operand = E;
1031
1032 if (E->getType()->isDependentType()) {
1033 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, Operand, E);
1034 return Res;
1035 }
1036
1037 // If the expression is a temporary, materialize it as an lvalue so that we
1038 // can use it multiple times.
1039 if (E->isPRValue())
1040 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
1041
1042 // Build the await_ready, await_suspend, await_resume calls.
1044 *this, Coroutine->CoroutinePromise, Loc, E);
1045 if (RSS.IsInvalid)
1046 return ExprError();
1047
1048 Expr *Res =
1049 new (Context) CoyieldExpr(Loc, Operand, E, RSS.Results[0], RSS.Results[1],
1050 RSS.Results[2], RSS.OpaqueValue);
1051
1052 return Res;
1053}
1054
1056 if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
1058 return StmtError();
1059 }
1060 return BuildCoreturnStmt(Loc, E);
1061}
1062
1064 bool IsImplicit) {
1065 auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
1066 if (!FSI)
1067 return StmtError();
1068
1069 if (E && E->hasPlaceholderType() &&
1070 !E->hasPlaceholderType(BuiltinType::Overload)) {
1072 if (R.isInvalid()) return StmtError();
1073 E = R.get();
1074 }
1075
1076 VarDecl *Promise = FSI->CoroutinePromise;
1077 ExprResult PC;
1078 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
1080 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
1081 } else {
1083 PC = buildPromiseCall(*this, Promise, Loc, "return_void", std::nullopt);
1084 }
1085 if (PC.isInvalid())
1086 return StmtError();
1087
1088 Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
1089
1090 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
1091 return Res;
1092}
1093
1094/// Look up the std::nothrow object.
1097 assert(Std && "Should already be diagnosed");
1098
1099 LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc,
1101 if (!S.LookupQualifiedName(Result, Std)) {
1102 // <coroutine> is not requred to include <new>, so we couldn't omit
1103 // the check here.
1104 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
1105 return nullptr;
1106 }
1107
1108 auto *VD = Result.getAsSingle<VarDecl>();
1109 if (!VD) {
1110 Result.suppressDiagnostics();
1111 // We found something weird. Complain about the first thing we found.
1112 NamedDecl *Found = *Result.begin();
1113 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);
1114 return nullptr;
1115 }
1116
1117 ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc);
1118 if (DR.isInvalid())
1119 return nullptr;
1120
1121 return DR.get();
1122}
1123
1125 SourceLocation Loc) {
1126 EnumDecl *StdAlignValT = S.getStdAlignValT();
1127 QualType StdAlignValDecl = S.Context.getTypeDeclType(StdAlignValT);
1128 return S.Context.getTrivialTypeSourceInfo(StdAlignValDecl);
1129}
1130
1131// Find an appropriate delete for the promise.
1132static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType,
1133 FunctionDecl *&OperatorDelete) {
1134 DeclarationName DeleteName =
1136
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 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete,
1147 /*Diagnose*/ true, /*WantSize*/ true,
1148 /*WantAligned*/ Overaligned))
1149 return false;
1150
1151 // [dcl.fct.def.coroutine]p12
1152 // If both a usual deallocation function with only a pointer parameter and a
1153 // usual deallocation function with both a pointer parameter and a size
1154 // parameter are found, then the selected deallocation function shall be the
1155 // one with two parameters. Otherwise, the selected deallocation function
1156 // shall be the function with one parameter.
1157 if (!OperatorDelete) {
1158 // Look for a global declaration.
1159 // Coroutines can always provide their required size.
1160 const bool CanProvideSize = true;
1161 // Sema::FindUsualDeallocationFunction will try to find the one with two
1162 // parameters first. It will return the deallocation function with one
1163 // parameter if failed.
1164 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
1165 Overaligned, DeleteName);
1166
1167 if (!OperatorDelete)
1168 return false;
1169 }
1170
1171 S.MarkFunctionReferenced(Loc, OperatorDelete);
1172 return true;
1173}
1174
1175
1178 assert(Fn && Fn->isCoroutine() && "not a coroutine");
1179 if (!Body) {
1180 assert(FD->isInvalidDecl() &&
1181 "a null body is only allowed for invalid declarations");
1182 return;
1183 }
1184 // We have a function that uses coroutine keywords, but we failed to build
1185 // the promise type.
1186 if (!Fn->CoroutinePromise)
1187 return FD->setInvalidDecl();
1188
1189 if (isa<CoroutineBodyStmt>(Body)) {
1190 // Nothing todo. the body is already a transformed coroutine body statement.
1191 return;
1192 }
1193
1194 // The always_inline attribute doesn't reliably apply to a coroutine,
1195 // because the coroutine will be split into pieces and some pieces
1196 // might be called indirectly, as in a virtual call. Even the ramp
1197 // function cannot be inlined at -O0, due to pipeline ordering
1198 // problems (see https://llvm.org/PR53413). Tell the user about it.
1199 if (FD->hasAttr<AlwaysInlineAttr>())
1200 Diag(FD->getLocation(), diag::warn_always_inline_coroutine);
1201
1202 // The design of coroutines means we cannot allow use of VLAs within one, so
1203 // diagnose if we've seen a VLA in the body of this function.
1204 if (Fn->FirstVLALoc.isValid())
1205 Diag(Fn->FirstVLALoc, diag::err_vla_in_coroutine_unsupported);
1206
1207 // [stmt.return.coroutine]p1:
1208 // A coroutine shall not enclose a return statement ([stmt.return]).
1209 if (Fn->FirstReturnLoc.isValid()) {
1210 assert(Fn->FirstCoroutineStmtLoc.isValid() &&
1211 "first coroutine location not set");
1212 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
1213 Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1215 }
1216
1217 // Coroutines will get splitted into pieces. The GNU address of label
1218 // extension wouldn't be meaningful in coroutines.
1219 for (AddrLabelExpr *ALE : Fn->AddrLabels)
1220 Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
1221
1222 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
1223 if (Builder.isInvalid() || !Builder.buildStatements())
1224 return FD->setInvalidDecl();
1225
1226 // Build body for the coroutine wrapper statement.
1227 Body = CoroutineBodyStmt::Create(Context, Builder);
1228}
1229
1231 if (auto *CS = dyn_cast<CompoundStmt>(Body))
1232 return CS;
1233
1234 // The body of the coroutine may be a try statement if it is in
1235 // 'function-try-block' syntax. Here we wrap it into a compound
1236 // statement for consistency.
1237 assert(isa<CXXTryStmt>(Body) && "Unimaged coroutine body type");
1238 return CompoundStmt::Create(Context, {Body}, FPOptionsOverride(),
1240}
1241
1244 Stmt *Body)
1245 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1246 IsPromiseDependentType(
1247 !Fn.CoroutinePromise ||
1248 Fn.CoroutinePromise->getType()->isDependentType()) {
1249 this->Body = buildCoroutineBody(Body, S.getASTContext());
1250
1251 for (auto KV : Fn.CoroutineParameterMoves)
1252 this->ParamMovesVector.push_back(KV.second);
1253 this->ParamMoves = this->ParamMovesVector;
1254
1255 if (!IsPromiseDependentType) {
1256 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
1257 assert(PromiseRecordDecl && "Type should have already been checked");
1258 }
1259 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1260}
1261
1263 assert(this->IsValid && "coroutine already invalid");
1264 this->IsValid = makeReturnObject();
1265 if (this->IsValid && !IsPromiseDependentType)
1267 return this->IsValid;
1268}
1269
1271 assert(this->IsValid && "coroutine already invalid");
1272 assert(!this->IsPromiseDependentType &&
1273 "coroutine cannot have a dependent promise type");
1274 this->IsValid = makeOnException() && makeOnFallthrough() &&
1275 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1276 makeNewAndDeleteExpr();
1277 return this->IsValid;
1278}
1279
1280bool CoroutineStmtBuilder::makePromiseStmt() {
1281 // Form a declaration statement for the promise declaration, so that AST
1282 // visitors can more easily find it.
1283 StmtResult PromiseStmt =
1285 if (PromiseStmt.isInvalid())
1286 return false;
1287
1288 this->Promise = PromiseStmt.get();
1289 return true;
1290}
1291
1292bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1294 return false;
1295 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first);
1296 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
1297 return true;
1298}
1299
1301 CXXRecordDecl *PromiseRecordDecl,
1302 FunctionScopeInfo &Fn) {
1303 auto Loc = E->getExprLoc();
1304 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1305 auto *Decl = DeclRef->getDecl();
1306 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) {
1307 if (Method->isStatic())
1308 return true;
1309 else
1310 Loc = Decl->getLocation();
1311 }
1312 }
1313
1314 S.Diag(
1315 Loc,
1316 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1317 << PromiseRecordDecl;
1318 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1320 return false;
1321}
1322
1323bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1324 assert(!IsPromiseDependentType &&
1325 "cannot make statement while the promise type is dependent");
1326
1327 // [dcl.fct.def.coroutine]p10
1328 // If a search for the name get_return_object_on_allocation_failure in
1329 // the scope of the promise type ([class.member.lookup]) finds any
1330 // declarations, then the result of a call to an allocation function used to
1331 // obtain storage for the coroutine state is assumed to return nullptr if it
1332 // fails to obtain storage, ... If the allocation function returns nullptr,
1333 // ... and the return value is obtained by a call to
1334 // T::get_return_object_on_allocation_failure(), where T is the
1335 // promise type.
1336 DeclarationName DN =
1337 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");
1338 LookupResult Found(S, DN, Loc, Sema::LookupMemberName);
1339 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))
1340 return true;
1341
1342 CXXScopeSpec SS;
1343 ExprResult DeclNameExpr =
1344 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
1345 if (DeclNameExpr.isInvalid())
1346 return false;
1347
1348 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn))
1349 return false;
1350
1351 ExprResult ReturnObjectOnAllocationFailure =
1352 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
1353 if (ReturnObjectOnAllocationFailure.isInvalid())
1354 return false;
1355
1357 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
1358 if (ReturnStmt.isInvalid()) {
1359 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1360 << DN;
1361 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1363 return false;
1364 }
1365
1366 this->ReturnStmtOnAllocFailure = ReturnStmt.get();
1367 return true;
1368}
1369
1370// Collect placement arguments for allocation function of coroutine FD.
1371// Return true if we collect placement arguments succesfully. Return false,
1372// otherwise.
1374 SmallVectorImpl<Expr *> &PlacementArgs) {
1375 if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1376 if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
1377 ExprResult ThisExpr = S.ActOnCXXThis(Loc);
1378 if (ThisExpr.isInvalid())
1379 return false;
1380 ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
1381 if (ThisExpr.isInvalid())
1382 return false;
1383 PlacementArgs.push_back(ThisExpr.get());
1384 }
1385 }
1386
1387 for (auto *PD : FD.parameters()) {
1388 if (PD->getType()->isDependentType())
1389 continue;
1390
1391 // Build a reference to the parameter.
1392 auto PDLoc = PD->getLocation();
1393 ExprResult PDRefExpr =
1394 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
1396 if (PDRefExpr.isInvalid())
1397 return false;
1398
1399 PlacementArgs.push_back(PDRefExpr.get());
1400 }
1401
1402 return true;
1403}
1404
1405bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1406 // Form and check allocation and deallocation calls.
1407 assert(!IsPromiseDependentType &&
1408 "cannot make statement while the promise type is dependent");
1409 QualType PromiseType = Fn.CoroutinePromise->getType();
1410
1411 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
1412 return false;
1413
1414 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
1415
1416 // According to [dcl.fct.def.coroutine]p9, Lookup allocation functions using a
1417 // parameter list composed of the requested size of the coroutine state being
1418 // allocated, followed by the coroutine function's arguments. If a matching
1419 // allocation function exists, use it. Otherwise, use an allocation function
1420 // that just takes the requested size.
1421 //
1422 // [dcl.fct.def.coroutine]p9
1423 // An implementation may need to allocate additional storage for a
1424 // coroutine.
1425 // This storage is known as the coroutine state and is obtained by calling a
1426 // non-array allocation function ([basic.stc.dynamic.allocation]). The
1427 // allocation function's name is looked up by searching for it in the scope of
1428 // the promise type.
1429 // - If any declarations are found, overload resolution is performed on a
1430 // function call created by assembling an argument list. The first argument is
1431 // the amount of space requested, and has type std::size_t. The
1432 // lvalues p1 ... pn are the succeeding arguments.
1433 //
1434 // ...where "p1 ... pn" are defined earlier as:
1435 //
1436 // [dcl.fct.def.coroutine]p3
1437 // The promise type of a coroutine is `std::coroutine_traits<R, P1, ...,
1438 // Pn>`
1439 // , where R is the return type of the function, and `P1, ..., Pn` are the
1440 // sequence of types of the non-object function parameters, preceded by the
1441 // type of the object parameter ([dcl.fct]) if the coroutine is a non-static
1442 // member function. [dcl.fct.def.coroutine]p4 In the following, p_i is an
1443 // lvalue of type P_i, where p1 denotes the object parameter and p_i+1 denotes
1444 // the i-th non-object function parameter for a non-static member function,
1445 // and p_i denotes the i-th function parameter otherwise. For a non-static
1446 // member function, q_1 is an lvalue that denotes *this; any other q_i is an
1447 // lvalue that denotes the parameter copy corresponding to p_i.
1448
1449 FunctionDecl *OperatorNew = nullptr;
1450 SmallVector<Expr *, 1> PlacementArgs;
1451
1452 const bool PromiseContainsNew = [this, &PromiseType]() -> bool {
1453 DeclarationName NewName =
1455 LookupResult R(S, NewName, Loc, Sema::LookupOrdinaryName);
1456
1457 if (PromiseType->isRecordType())
1458 S.LookupQualifiedName(R, PromiseType->getAsCXXRecordDecl());
1459
1460 return !R.empty() && !R.isAmbiguous();
1461 }();
1462
1463 // Helper function to indicate whether the last lookup found the aligned
1464 // allocation function.
1465 bool PassAlignment = S.getLangOpts().CoroAlignedAllocation;
1466 auto LookupAllocationFunction = [&](Sema::AllocationFunctionScope NewScope =
1468 bool WithoutPlacementArgs = false,
1469 bool ForceNonAligned = false) {
1470 // [dcl.fct.def.coroutine]p9
1471 // The allocation function's name is looked up by searching for it in the
1472 // scope of the promise type.
1473 // - If any declarations are found, ...
1474 // - If no declarations are found in the scope of the promise type, a search
1475 // is performed in the global scope.
1476 if (NewScope == Sema::AFS_Both)
1477 NewScope = PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
1478
1479 PassAlignment = !ForceNonAligned && S.getLangOpts().CoroAlignedAllocation;
1480 FunctionDecl *UnusedResult = nullptr;
1481 S.FindAllocationFunctions(Loc, SourceRange(), NewScope,
1482 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1483 /*isArray*/ false, PassAlignment,
1484 WithoutPlacementArgs ? MultiExprArg{}
1485 : PlacementArgs,
1486 OperatorNew, UnusedResult, /*Diagnose*/ false);
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 ||
1511 (S.getLangOpts().CoroAlignedAllocation && !PassAlignment))
1512 LookupAllocationFunction(/*NewScope*/ Sema::AFS_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 || !PassAlignment) {
1537 FoundNonAlignedInPromise = OperatorNew;
1538
1539 LookupAllocationFunction(/*NewScope*/ Sema::AFS_Class,
1540 /*WithoutPlacementArgs*/ false,
1541 /*ForceNonAligned*/ true);
1542
1543 if (!OperatorNew && !PlacementArgs.empty())
1544 LookupAllocationFunction(/*NewScope*/ Sema::AFS_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(Sema::AFS_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 else if (RequiresNoThrowAlloc)
1576 S.Diag(Loc, diag::err_coroutine_unfound_nothrow_new)
1577 << &FD << S.getLangOpts().CoroAlignedAllocation;
1578
1579 return false;
1580 }
1581
1582 if (RequiresNoThrowAlloc) {
1583 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();
1584 if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
1585 S.Diag(OperatorNew->getLocation(),
1586 diag::err_coroutine_promise_new_requires_nothrow)
1587 << OperatorNew;
1588 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1589 << OperatorNew;
1590 return false;
1591 }
1592 }
1593
1594 FunctionDecl *OperatorDelete = nullptr;
1595 if (!findDeleteForPromise(S, Loc, PromiseType, OperatorDelete)) {
1596 // FIXME: We should add an error here. According to:
1597 // [dcl.fct.def.coroutine]p12
1598 // If no usual deallocation function is found, the program is ill-formed.
1599 return false;
1600 }
1601
1602 Expr *FramePtr =
1603 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
1604
1605 Expr *FrameSize =
1606 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
1607
1608 Expr *FrameAlignment = nullptr;
1609
1610 if (S.getLangOpts().CoroAlignedAllocation) {
1611 FrameAlignment =
1612 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_align, {});
1613
1615 if (!AlignValTy)
1616 return false;
1617
1618 FrameAlignment = S.BuildCXXNamedCast(Loc, tok::kw_static_cast, AlignValTy,
1619 FrameAlignment, SourceRange(Loc, Loc),
1620 SourceRange(Loc, Loc))
1621 .get();
1622 }
1623
1624 // Make new call.
1625 ExprResult NewRef =
1626 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
1627 if (NewRef.isInvalid())
1628 return false;
1629
1630 SmallVector<Expr *, 2> NewArgs(1, FrameSize);
1631 if (S.getLangOpts().CoroAlignedAllocation && PassAlignment)
1632 NewArgs.push_back(FrameAlignment);
1633
1634 if (OperatorNew->getNumParams() > NewArgs.size())
1635 llvm::append_range(NewArgs, PlacementArgs);
1636
1637 ExprResult NewExpr =
1638 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
1639 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
1640 if (NewExpr.isInvalid())
1641 return false;
1642
1643 // Make delete call.
1644
1645 QualType OpDeleteQualType = OperatorDelete->getType();
1646
1647 ExprResult DeleteRef =
1648 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
1649 if (DeleteRef.isInvalid())
1650 return false;
1651
1652 Expr *CoroFree =
1653 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
1654
1655 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
1656
1657 // [dcl.fct.def.coroutine]p12
1658 // The selected deallocation function shall be called with the address of
1659 // the block of storage to be reclaimed as its first argument. If a
1660 // deallocation function with a parameter of type std::size_t is
1661 // used, the size of the block is passed as the corresponding argument.
1662 const auto *OpDeleteType =
1663 OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
1664 if (OpDeleteType->getNumParams() > DeleteArgs.size() &&
1666 OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))
1667 DeleteArgs.push_back(FrameSize);
1668
1669 // Proposed Change of [dcl.fct.def.coroutine]p12 in P2014R0:
1670 // If deallocation function lookup finds a usual deallocation function with
1671 // a pointer parameter, size parameter and alignment parameter then this
1672 // will be the selected deallocation function, otherwise if lookup finds a
1673 // usual deallocation function with both a pointer parameter and a size
1674 // parameter, then this will be the selected deallocation function.
1675 // Otherwise, if lookup finds a usual deallocation function with only a
1676 // pointer parameter, then this will be the selected deallocation
1677 // function.
1678 //
1679 // So we are not forced to pass alignment to the deallocation function.
1680 if (S.getLangOpts().CoroAlignedAllocation &&
1681 OpDeleteType->getNumParams() > DeleteArgs.size() &&
1683 OpDeleteType->getParamType(DeleteArgs.size()),
1684 FrameAlignment->getType()))
1685 DeleteArgs.push_back(FrameAlignment);
1686
1687 ExprResult DeleteExpr =
1688 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
1689 DeleteExpr =
1690 S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
1691 if (DeleteExpr.isInvalid())
1692 return false;
1693
1694 this->Allocate = NewExpr.get();
1695 this->Deallocate = DeleteExpr.get();
1696
1697 return true;
1698}
1699
1700bool CoroutineStmtBuilder::makeOnFallthrough() {
1701 assert(!IsPromiseDependentType &&
1702 "cannot make statement while the promise type is dependent");
1703
1704 // [dcl.fct.def.coroutine]/p6
1705 // If searches for the names return_void and return_value in the scope of
1706 // the promise type each find any declarations, the program is ill-formed.
1707 // [Note 1: If return_void is found, flowing off the end of a coroutine is
1708 // equivalent to a co_return with no operand. Otherwise, flowing off the end
1709 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
1710 // end note]
1711 bool HasRVoid, HasRValue;
1712 LookupResult LRVoid =
1713 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
1714 LookupResult LRValue =
1715 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
1716
1717 StmtResult Fallthrough;
1718 if (HasRVoid && HasRValue) {
1719 // FIXME Improve this diagnostic
1720 S.Diag(FD.getLocation(),
1721 diag::err_coroutine_promise_incompatible_return_functions)
1722 << PromiseRecordDecl;
1724 diag::note_member_first_declared_here)
1725 << LRVoid.getLookupName();
1726 S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
1727 diag::note_member_first_declared_here)
1728 << LRValue.getLookupName();
1729 return false;
1730 } else if (!HasRVoid && !HasRValue) {
1731 // We need to set 'Fallthrough'. Otherwise the other analysis part might
1732 // think the coroutine has defined a return_value method. So it might emit
1733 // **false** positive warning. e.g.,
1734 //
1735 // promise_without_return_func foo() {
1736 // co_await something();
1737 // }
1738 //
1739 // Then AnalysisBasedWarning would emit a warning about `foo()` lacking a
1740 // co_return statements, which isn't correct.
1741 Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());
1742 if (Fallthrough.isInvalid())
1743 return false;
1744 } else if (HasRVoid) {
1745 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
1746 /*IsImplicit*/false);
1747 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
1748 if (Fallthrough.isInvalid())
1749 return false;
1750 }
1751
1752 this->OnFallthrough = Fallthrough.get();
1753 return true;
1754}
1755
1756bool CoroutineStmtBuilder::makeOnException() {
1757 // Try to form 'p.unhandled_exception();'
1758 assert(!IsPromiseDependentType &&
1759 "cannot make statement while the promise type is dependent");
1760
1761 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
1762
1763 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
1764 auto DiagID =
1765 RequireUnhandledException
1766 ? diag::err_coroutine_promise_unhandled_exception_required
1767 : diag::
1768 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1769 S.Diag(Loc, DiagID) << PromiseRecordDecl;
1770 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1771 << PromiseRecordDecl;
1772 return !RequireUnhandledException;
1773 }
1774
1775 // If exceptions are disabled, don't try to build OnException.
1776 if (!S.getLangOpts().CXXExceptions)
1777 return true;
1778
1779 ExprResult UnhandledException = buildPromiseCall(
1780 S, Fn.CoroutinePromise, Loc, "unhandled_exception", std::nullopt);
1781 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
1782 /*DiscardedValue*/ false);
1783 if (UnhandledException.isInvalid())
1784 return false;
1785
1786 // Since the body of the coroutine will be wrapped in try-catch, it will
1787 // be incompatible with SEH __try if present in a function.
1788 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
1789 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
1790 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1792 return false;
1793 }
1794
1795 this->OnException = UnhandledException.get();
1796 return true;
1797}
1798
1799bool CoroutineStmtBuilder::makeReturnObject() {
1800 // [dcl.fct.def.coroutine]p7
1801 // The expression promise.get_return_object() is used to initialize the
1802 // returned reference or prvalue result object of a call to a coroutine.
1803 ExprResult ReturnObject = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
1804 "get_return_object", std::nullopt);
1805 if (ReturnObject.isInvalid())
1806 return false;
1807
1808 this->ReturnValue = ReturnObject.get();
1809 return true;
1810}
1811
1813 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1814 auto *MethodDecl = MbrRef->getMethodDecl();
1815 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1816 << MethodDecl;
1817 }
1818 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1820}
1821
1822bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1823 assert(!IsPromiseDependentType &&
1824 "cannot make statement while the promise type is dependent");
1825 assert(this->ReturnValue && "ReturnValue must be already formed");
1826
1827 QualType const GroType = this->ReturnValue->getType();
1828 assert(!GroType->isDependentType() &&
1829 "get_return_object type must no longer be dependent");
1830
1831 QualType const FnRetType = FD.getReturnType();
1832 assert(!FnRetType->isDependentType() &&
1833 "get_return_object type must no longer be dependent");
1834
1835 // The call to get_­return_­object is sequenced before the call to
1836 // initial_­suspend and is invoked at most once, but there are caveats
1837 // regarding on whether the prvalue result object may be initialized
1838 // directly/eager or delayed, depending on the types involved.
1839 //
1840 // More info at https://github.com/cplusplus/papers/issues/1414
1841 bool GroMatchesRetType = S.getASTContext().hasSameType(GroType, FnRetType);
1842
1843 if (FnRetType->isVoidType()) {
1844 ExprResult Res =
1845 S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
1846 if (Res.isInvalid())
1847 return false;
1848
1849 if (!GroMatchesRetType)
1850 this->ResultDecl = Res.get();
1851 return true;
1852 }
1853
1854 if (GroType->isVoidType()) {
1855 // Trigger a nice error message.
1856 InitializedEntity Entity =
1860 return false;
1861 }
1862
1864 clang::VarDecl *GroDecl = nullptr;
1865 if (GroMatchesRetType) {
1867 } else {
1868 GroDecl = VarDecl::Create(
1869 S.Context, &FD, FD.getLocation(), FD.getLocation(),
1870 &S.PP.getIdentifierTable().get("__coro_gro"), GroType,
1871 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
1872 GroDecl->setImplicit();
1873
1875 if (GroDecl->isInvalidDecl())
1876 return false;
1877
1879 ExprResult Res =
1881 if (Res.isInvalid())
1882 return false;
1883
1884 Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
1885 if (Res.isInvalid())
1886 return false;
1887
1888 S.AddInitializerToDecl(GroDecl, Res.get(),
1889 /*DirectInit=*/false);
1890
1891 S.FinalizeDeclaration(GroDecl);
1892
1893 // Form a declaration statement for the return declaration, so that AST
1894 // visitors can more easily find it.
1895 StmtResult GroDeclStmt =
1896 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
1897 if (GroDeclStmt.isInvalid())
1898 return false;
1899
1900 this->ResultDecl = GroDeclStmt.get();
1901
1902 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
1903 if (declRef.isInvalid())
1904 return false;
1905
1906 ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
1907 }
1908
1909 if (ReturnStmt.isInvalid()) {
1911 return false;
1912 }
1913
1914 if (!GroMatchesRetType &&
1915 cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
1916 GroDecl->setNRVOVariable(true);
1917
1918 this->ReturnStmt = ReturnStmt.get();
1919 return true;
1920}
1921
1922// Create a static_cast<T&&>(expr).
1924 if (T.isNull())
1925 T = E->getType();
1926 QualType TargetType = S.BuildReferenceType(
1927 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
1928 SourceLocation ExprLoc = E->getBeginLoc();
1929 TypeSourceInfo *TargetLoc =
1930 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
1931
1932 return S
1933 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
1934 SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
1935 .get();
1936}
1937
1938/// Build a variable declaration for move parameter.
1940 IdentifierInfo *II) {
1942 VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
1943 TInfo, SC_None);
1944 Decl->setImplicit();
1945 return Decl;
1946}
1947
1948// Build statements that move coroutine function parameters to the coroutine
1949// frame, and store them on the function scope info.
1951 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
1952 auto *FD = cast<FunctionDecl>(CurContext);
1953
1954 auto *ScopeInfo = getCurFunction();
1955 if (!ScopeInfo->CoroutineParameterMoves.empty())
1956 return false;
1957
1958 // [dcl.fct.def.coroutine]p13
1959 // When a coroutine is invoked, after initializing its parameters
1960 // ([expr.call]), a copy is created for each coroutine parameter. For a
1961 // parameter of type cv T, the copy is a variable of type cv T with
1962 // automatic storage duration that is direct-initialized from an xvalue of
1963 // type T referring to the parameter.
1964 for (auto *PD : FD->parameters()) {
1965 if (PD->getType()->isDependentType())
1966 continue;
1967
1968 // Preserve the referenced state for unused parameter diagnostics.
1969 bool DeclReferenced = PD->isReferenced();
1970
1971 ExprResult PDRefExpr =
1972 BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
1973 ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1974
1975 PD->setReferenced(DeclReferenced);
1976
1977 if (PDRefExpr.isInvalid())
1978 return false;
1979
1980 Expr *CExpr = nullptr;
1981 if (PD->getType()->getAsCXXRecordDecl() ||
1982 PD->getType()->isRValueReferenceType())
1983 CExpr = castForMoving(*this, PDRefExpr.get());
1984 else
1985 CExpr = PDRefExpr.get();
1986 // [dcl.fct.def.coroutine]p13
1987 // The initialization and destruction of each parameter copy occurs in the
1988 // context of the called coroutine.
1989 auto *D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
1990 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
1991
1992 // Convert decl to a statement.
1994 if (Stmt.isInvalid())
1995 return false;
1996
1997 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
1998 }
1999 return true;
2000}
2001
2004 if (!Res)
2005 return StmtError();
2006 return Res;
2007}
2008
2010 SourceLocation FuncLoc) {
2013
2014 IdentifierInfo const &TraitIdent =
2015 PP.getIdentifierTable().get("coroutine_traits");
2016
2017 NamespaceDecl *StdSpace = getStdNamespace();
2018 LookupResult Result(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
2019 bool Found = StdSpace && LookupQualifiedName(Result, StdSpace);
2020
2021 if (!Found) {
2022 // The goggles, we found nothing!
2023 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
2024 << "std::coroutine_traits";
2025 return nullptr;
2026 }
2027
2028 // coroutine_traits is required to be a class template.
2031 Result.suppressDiagnostics();
2032 NamedDecl *Found = *Result.begin();
2033 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
2034 return nullptr;
2035 }
2036
2038}
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines enum values for all the target-independent builtin functions.
Defines the clang::Expr interface and subclasses for C++ expressions.
LangStandard::Kind Std
Defines the clang::Preprocessor interface.
static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, SourceLocation Loc)
static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn)
static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static Expr * buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc)
Look up the std::nothrow object.
static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E)
static bool diagReturnOnAllocFailure(Sema &S, Expr *E, CXXRecordDecl *PromiseRecordDecl, FunctionScopeInfo &Fn)
static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, SourceLocation Loc, StringRef Name, MultiExprArg Args)
static Expr * castForMoving(Sema &S, Expr *E, QualType T=QualType())
static Expr * maybeTailCall(Sema &S, QualType RetType, Expr *E, SourceLocation Loc)
static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, StringRef Name, MultiExprArg Args)
static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, SourceLocation Loc, bool &Res)
static void tryMarkAwaitSuspendNoInline(Sema &S, OpaqueValueExpr *Awaiter, CallExpr *AwaitSuspend)
The await_suspend call performed by co_await is essentially asynchronous to the execution of the coro...
static TypeSourceInfo * getTypeSourceInfoForStdAlignValT(Sema &S, SourceLocation Loc)
static bool isWithinCatchScope(Scope *S)
static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType, FunctionDecl *&OperatorDelete)
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static void checkNoThrow(Sema &S, const Stmt *E, llvm::SmallPtrSetImpl< const Decl * > &ThrowingDecls)
Recursively check E and all its children to see if any call target (including constructor call) is de...
static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, SourceLocation Loc, Expr *E)
Build calls to await_ready, await_suspend, and await_resume for a co_await expression.
static bool checkSuspensionContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, SourceLocation Loc)
Look up the std::coroutine_handle<PromiseType>.
static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc, SmallVectorImpl< Expr * > &PlacementArgs)
static CompoundStmt * buildCoroutineBody(Stmt *Body, ASTContext &Context)
static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, SourceLocation KwLoc)
Look up the std::coroutine_traits<...>::promise_type for the given function type.
static FunctionScopeInfo * checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword, bool IsImplicit=false)
Check that this is a context in which a coroutine suspension can appear.
static bool IsOverloaded(const UnresolvedSetImpl &Functions)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:640
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2551
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
CanQualType DependentTy
Definition: ASTContext.h:1111
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1572
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl=nullptr) const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2578
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition: Expr.h:4360
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:4380
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2528
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2053
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2179
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition: DeclCXX.cpp:1934
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:73
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2847
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3017
Decl * getCalleeDecl()
Definition: Expr.h:3011
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition: Expr.cpp:1560
Declaration of a class template.
void setExprNeedsCleanups(bool SideEffects)
Definition: CleanupInfo.h:28
Represents a 'co_await' expression.
Definition: ExprCXX.h:5037
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1602
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:382
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition: StmtCXX.h:473
Represents the body of a coroutine.
Definition: StmtCXX.h:320
static CoroutineBodyStmt * Create(const ASTContext &C, CtorArgs const &Args)
Definition: StmtCXX.cpp:87
CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn, Stmt *Body)
Construct a CoroutineStmtBuilder and initialize the promise statement and initial/final suspends from...
bool buildDependentStatements()
Build the coroutine body statements that require a non-dependent promise type in order to construct.
bool buildStatements()
Build the coroutine body statements, including the "promise dependent" statements when the promise ty...
Represents a 'co_yield' expression.
Definition: ExprCXX.h:5118
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:440
void addAttr(Attr *A)
Definition: DeclBase.cpp:975
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:132
bool isInvalidDecl() const
Definition: DeclBase.h:592
SourceLocation getLocation() const
Definition: DeclBase.h:444
void setImplicit(bool I=true)
Definition: DeclBase.h:598
DeclContext * getDeclContext()
Definition: DeclBase.h:453
bool hasAttr() const
Definition: DeclBase.h:581
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:820
Represents a 'co_await' expression while the type of the promise is dependent.
Definition: ExprCXX.h:5069
Represents an enum.
Definition: Decl.h:3816
This represents one expression.
Definition: Expr.h:110
bool isPRValue() const
Definition: Expr.h:272
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:438
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:267
QualType getType() const
Definition: Expr.h:142
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition: Expr.h:503
Represents difference between two FPOptions values.
Definition: LangOptions.h:829
Represents a function declaration or definition.
Definition: Decl.h:1957
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2641
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3629
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4160
ArrayRef< QualType > getParamTypes() const
Definition: Type.h:4384
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this function type.
Definition: Type.h:4526
QualType getReturnType() const
Definition: Type.h:4078
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)
Create an initialization from an initializer (which, for direct initialization from a parenthesized l...
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Definition: SemaInit.cpp:8514
Describes an entity that is being initialized.
static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)
Create the initialization entity for the result of a function.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
Represents the results of name lookup.
Definition: Lookup.h:46
DeclClass * getAsSingle() const
Definition: Lookup.h:553
bool isAmbiguous() const
Definition: Lookup.h:321
const UnresolvedSetImpl & asUnresolvedSet() const
Definition: Lookup.h:351
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition: Lookup.h:570
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:629
DeclarationName getLookupName() const
Gets the name to look up.
Definition: Lookup.h:263
This represents a decl that may have a name.
Definition: Decl.h:248
Represent a C++ namespace.
Definition: Decl.h:545
A C++ nested-name-specifier augmented with source location information.
static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, IdentifierInfo *II)
Builds a specifier combining a prefix and an identifier.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1156
decls_iterator decls_begin() const
Definition: ExprCXX.h:3071
decls_iterator decls_end() const
Definition: ExprCXX.h:3074
static ParenListExpr * Create(const ASTContext &Ctx, SourceLocation LParenLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc)
Create a paren list.
Definition: Expr.cpp:4652
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
IdentifierTable & getIdentifierTable()
A (possibly-)qualified type.
Definition: Type.h:736
@ DK_cxx_destructor
Definition: Type.h:1309
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:803
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6781
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:6981
QualType getCanonicalType() const
Definition: Type.h:6833
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition: Type.h:1319
bool field_empty() const
Definition: Decl.h:4331
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3013
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
Expr * get() const
Definition: Sema.h:5076
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:358
FunctionDecl * FindUsualDeallocationFunction(SourceLocation StartLoc, bool CanProvideSize, bool Overaligned, DeclarationName Name)
ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E, UnresolvedLookupExpr *Lookup)
Build a call to 'operator co_await' if there is a suitable operator for the given expression.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:14155
ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs=nullptr)
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:16301
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:4364
@ LookupOperatorName
Look up of an operator name (e.g., operator+) for use with operator overloading.
Definition: Sema.h:4376
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
Definition: Sema.h:4372
bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend)
Check that the expression co_await promise.final_suspend() shall not be potentially-throwing.
StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs)
ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: Sema.cpp:1924
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body)
bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword)
VarDecl * buildCoroutinePromise(SourceLocation Loc)
StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, bool IsImplicit=false)
Expr * BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs)
BuildBuiltinCallExpr - Create a call to a builtin function specified by Id.
Definition: SemaExpr.cpp:7385
ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, Expr *Awaiter, bool IsImplicit=false)
ASTContext & Context
Definition: Sema.h:409
void FinalizeDeclaration(Decl *D)
FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...
Definition: SemaDecl.cpp:14638
ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E)
ExprResult ActOnCXXThis(SourceLocation loc)
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:62
ClassTemplateDecl * StdCoroutineTraitsCache
The C++ "std::coroutine_traits" template, which is defined in <coroutine_traits>
Definition: Sema.h:1177
ASTContext & getASTContext() const
Definition: Sema.h:1689
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2199
EnumDecl * getStdAlignValT() const
NamedReturnInfo getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode=SimplerImplicitMoveMode::Normal)
Determine whether the given expression might be move-eligible or copy-elidable in either a (co_)retur...
Definition: SemaStmt.cpp:3372
StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E)
const LangOptions & getLangOpts() const
Definition: Sema.h:1682
StmtResult ActOnFinishFullStmt(Stmt *Stmt)
Preprocessor & PP
Definition: Sema.h:408
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
Definition: SemaExpr.cpp:7183
bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, AllocationFunctionScope NewScope, AllocationFunctionScope DeleteScope, QualType AllocType, bool IsArray, bool &PassAlignment, MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, FunctionDecl *&OperatorDelete, bool Diagnose=true)
Finds the overloads of operator new and delete that are appropriate for the allocation.
CleanupInfo Cleanup
Used to control the generation of ExprWithCleanups.
Definition: Sema.h:806
StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro=false)
Definition: SemaStmt.cpp:69
ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, UnresolvedLookupExpr *Lookup)
bool buildCoroutineParameterMoves(SourceLocation Loc)
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:2020
QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity)
Build a reference type.
Definition: SemaType.cpp:2248
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *input, bool RequiresADL=true)
Create a unary operation that may resolve to an overloaded operator.
ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
Definition: SemaExpr.cpp:3423
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:422
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl *&Operator, bool Diagnose=true, bool WantSize=false, bool WantAligned=false)
MaterializeTemporaryExpr * CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference)
Definition: SemaInit.cpp:8462
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
bool isUnevaluatedContext() const
Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.
Definition: Sema.h:9953
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:21735
ClassTemplateDecl * lookupCoroutineTraits(SourceLocation KwLoc, SourceLocation FuncLoc)
Lookup 'coroutine_traits' in std namespace and std::experimental namespace.
DeclContext * computeDeclContext(QualType T)
Compute the DeclContext that is associated with the given type.
QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs)
StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, bool AllowRecovery=false)
Definition: SemaStmt.cpp:3934
void CheckCompleteVariableDeclaration(VarDecl *VD)
Definition: SemaDecl.cpp:14274
ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:74
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9088
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
FullExprArg MakeFullDiscardedValueExpr(Expr *Arg)
Definition: Sema.h:5099
NamespaceDecl * getStdNamespace() const
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Definition: SemaInit.cpp:10487
void ActOnUninitializedDecl(Decl *dcl)
Definition: SemaDecl.cpp:13906
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13363
ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, TypeSourceInfo *Ty, Expr *E, SourceRange AngleBrackets, SourceRange Parens)
Definition: SemaCast.cpp:301
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
Definition: SemaExpr.cpp:18892
void clearDelayedTypo(TypoExpr *TE)
Clears the state of the given TypoExpr.
void CheckVariableDeclarationType(VarDecl *NewVD)
Definition: SemaDecl.cpp:8639
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
AllocationFunctionScope
The scope in which to find allocation functions.
Definition: Sema.h:6862
@ AFS_Both
Look for allocation functions in both the global scope and in the scope of the allocated class.
Definition: Sema.h:6870
@ AFS_Class
Only look for allocation functions in the scope of the allocated class.
Definition: Sema.h:6867
@ AFS_Global
Only look for allocation functions in the global scope.
Definition: Sema.h:6864
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, SourceLocation Loc=SourceLocation())
Determine whether the callee of a particular function call can throw.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:6988
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition: Stmt.h:84
child_range children()
Definition: Stmt.cpp:286
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:325
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:337
A convenient class for passing around template argument information.
Definition: TemplateBase.h:601
void addArgument(const TemplateArgumentLoc &Loc)
Definition: TemplateBase.h:641
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:495
Represents a template argument.
Definition: TemplateBase.h:60
Represents a C++ template name within the type system.
Definition: TemplateName.h:202
Represents a declaration of a type.
Definition: Decl.h:3341
A container of type source information.
Definition: Type.h:6752
The base class of the type hierarchy.
Definition: Type.h:1602
bool isStructureType() const
Definition: Type.cpp:589
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1819
bool isVoidType() const
Definition: Type.h:7352
bool isBooleanType() const
Definition: Type.h:7468
bool isVoidPointerType() const
Definition: Type.cpp:615
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:7625
bool isReferenceType() const
Definition: Type.h:7045
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2421
bool isClassType() const
Definition: Type.cpp:583
bool isRecordType() const
Definition: Type.h:7123
A reference to a name which we were able to look up during parsing but could not resolve to a specifi...
Definition: ExprCXX.h:3176
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End)
Definition: ExprCXX.cpp:373
void append(iterator I, iterator E)
A set of unresolved declarations.
QualType getType() const
Definition: Decl.h:715
Represents a variable declaration or definition.
Definition: Decl.h:916
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2143
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:924
void setNRVOVariable(bool NRVO)
Definition: Decl.h:1490
Retains information about a function, method, or block that is currently being parsed.
Definition: ScopeInfo.h:102
SourceLocation FirstVLALoc
First use of a VLA within the current function.
Definition: ScopeInfo.h:193
llvm::SmallMapVector< ParmVarDecl *, Stmt *, 4 > CoroutineParameterMoves
A mapping between the coroutine function parameters that were moved to the coroutine frame,...
Definition: ScopeInfo.h:218
SourceLocation FirstCoroutineStmtLoc
First coroutine statement in the current function.
Definition: ScopeInfo.h:180
std::pair< Stmt *, Stmt * > CoroutineSuspends
The initial and final coroutine suspend points.
Definition: ScopeInfo.h:221
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
Definition: ScopeInfo.h:214
bool hasInvalidCoroutineSuspends() const
Definition: ScopeInfo.h:529
StringRef getFirstCoroutineStmtKeyword() const
Definition: ScopeInfo.h:511
SourceLocation FirstReturnLoc
First 'return' statement in the current function.
Definition: ScopeInfo.h:183
SourceLocation FirstSEHTryLoc
First SEH '__try' statement in the current function.
Definition: ScopeInfo.h:190
llvm::SmallVector< AddrLabelExpr *, 4 > AddrLabels
The set of GNU address of label extension "&&label".
Definition: ScopeInfo.h:243
@ RQ_RValue
An rvalue ref-qualifier was provided (&&).
Definition: Type.h:1557
@ SC_None
Definition: Specifiers.h:245
ExprResult ExprEmpty()
Definition: Ownership.h:271
StmtResult StmtError()
Definition: Ownership.h:265
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition: ASTLambda.h:27
@ Result
The result type of a method or function.
ExprResult ExprError()
Definition: Ownership.h:264
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:134
OpaqueValueExpr * OpaqueValue
ArrayRef< Stmt * > ParamMoves
Definition: StmtCXX.h:361
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
DeclarationName getName() const
getName - Returns the embedded declaration name.