1 //===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements semantic analysis for C++ Coroutines.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Sema/SemaInternal.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/ExprCXX.h"
17 #include "clang/AST/StmtCXX.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "clang/Sema/Initialization.h"
20 #include "clang/Sema/Overload.h"
21 using namespace clang;
24 /// Look up the std::coroutine_traits<...>::promise_type for the given
26 static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
28 // FIXME: Cache std::coroutine_traits once we've found it.
29 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
31 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
35 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
36 Loc, Sema::LookupOrdinaryName);
37 if (!S.LookupQualifiedName(Result, StdExp)) {
38 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
42 ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
44 Result.suppressDiagnostics();
45 // We found something weird. Complain about the first thing we found.
46 NamedDecl *Found = *Result.begin();
47 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
51 // Form template argument list for coroutine_traits<R, P1, P2, ...>.
52 TemplateArgumentListInfo Args(Loc, Loc);
53 Args.addArgument(TemplateArgumentLoc(
54 TemplateArgument(FnType->getReturnType()),
55 S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc)));
56 // FIXME: If the function is a non-static member function, add the type
57 // of the implicit object parameter before the formal parameters.
58 for (QualType T : FnType->getParamTypes())
59 Args.addArgument(TemplateArgumentLoc(
60 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc)));
62 // Build the template-id.
64 S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args);
65 if (CoroTrait.isNull())
67 if (S.RequireCompleteType(Loc, CoroTrait,
68 diag::err_coroutine_traits_missing_specialization))
71 CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl();
72 assert(RD && "specialization of class template is not a class?");
74 // Look up the ::promise_type member.
75 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc,
76 Sema::LookupOrdinaryName);
77 S.LookupQualifiedName(R, RD);
78 auto *Promise = R.getAsSingle<TypeDecl>();
80 S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
85 // The promise type is required to be a class type.
86 QualType PromiseType = S.Context.getTypeDeclType(Promise);
87 if (!PromiseType->getAsCXXRecordDecl()) {
88 // Use the fully-qualified name of the type.
89 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp);
90 NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
91 CoroTrait.getTypePtr());
92 PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
94 S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
102 static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
104 // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
105 if (S.isUnevaluatedContext()) {
106 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
110 // Any other usage must be within a function.
111 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
113 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
114 ? diag::err_coroutine_objc_method
115 : diag::err_coroutine_outside_function) << Keyword;
119 // An enumeration for mapping the diagnostic type to the correct diagnostic
121 enum InvalidFuncDiag {
131 bool Diagnosed = false;
132 auto DiagInvalid = [&](InvalidFuncDiag ID) {
133 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
138 // Diagnose when a constructor, destructor, copy/move assignment operator,
139 // or the function 'main' are declared as a coroutine.
140 auto *MD = dyn_cast<CXXMethodDecl>(FD);
141 if (MD && isa<CXXConstructorDecl>(MD))
142 return DiagInvalid(DiagCtor);
143 else if (MD && isa<CXXDestructorDecl>(MD))
144 return DiagInvalid(DiagDtor);
145 else if (MD && MD->isCopyAssignmentOperator())
146 return DiagInvalid(DiagCopyAssign);
147 else if (MD && MD->isMoveAssignmentOperator())
148 return DiagInvalid(DiagMoveAssign);
149 else if (FD->isMain())
150 return DiagInvalid(DiagMain);
152 // Emit a diagnostics for each of the following conditions which is not met.
153 if (FD->isConstexpr())
154 DiagInvalid(DiagConstexpr);
155 if (FD->getReturnType()->isUndeducedType())
156 DiagInvalid(DiagAutoRet);
157 if (FD->isVariadic())
158 DiagInvalid(DiagVarargs);
163 /// Check that this is a context in which a coroutine suspension can appear.
164 static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
166 if (!isValidCoroutineContext(S, Loc, Keyword))
169 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
170 auto *FD = cast<FunctionDecl>(S.CurContext);
171 auto *ScopeInfo = S.getCurFunction();
172 assert(ScopeInfo && "missing function scope for function");
174 // If we don't have a promise variable, build one now.
175 if (!ScopeInfo->CoroutinePromise) {
176 QualType T = FD->getType()->isDependentType()
177 ? S.Context.DependentTy
179 S, FD->getType()->castAs<FunctionProtoType>(), Loc);
183 // Create and default-initialize the promise.
184 ScopeInfo->CoroutinePromise =
185 VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
186 &S.PP.getIdentifierTable().get("__promise"), T,
187 S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
188 S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
189 if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
190 S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise);
196 static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
197 MutableArrayRef<Expr *> CallArgs) {
198 StringRef Name = S.Context.BuiltinInfo.getName(Id);
199 LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
200 S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
202 auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
203 assert(BuiltInDecl && "failed to find builtin declaration");
206 S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
207 assert(DeclRef.isUsable() && "Builtin reference cannot fail");
210 S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
212 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
216 /// Build a call to 'operator co_await' if there is a suitable operator for
217 /// the given expression.
218 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
219 SourceLocation Loc, Expr *E) {
220 UnresolvedSet<16> Functions;
221 SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
223 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
226 struct ReadySuspendResumeResult {
231 static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
233 MutableArrayRef<Expr *> Args) {
234 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
236 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
238 ExprResult Result = S.BuildMemberReferenceExpr(
239 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
240 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
242 if (Result.isInvalid())
245 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
248 /// Build calls to await_ready, await_suspend, and await_resume for a co_await
250 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
252 // Assume invalid until we see otherwise.
253 ReadySuspendResumeResult Calls = {true, {}};
255 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
256 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
257 Expr *Operand = new (S.Context) OpaqueValueExpr(
258 Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
260 // FIXME: Pass coroutine handle to await_suspend.
261 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
262 if (Result.isInvalid())
264 Calls.Results[I] = Result.get();
267 Calls.IsInvalid = false;
271 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
272 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
274 CorrectDelayedTyposInExpr(E);
277 if (E->getType()->isPlaceholderType()) {
278 ExprResult R = CheckPlaceholderExpr(E);
279 if (R.isInvalid()) return ExprError();
283 ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
284 if (Awaitable.isInvalid())
287 return BuildCoawaitExpr(Loc, Awaitable.get());
289 ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
290 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
294 if (E->getType()->isPlaceholderType()) {
295 ExprResult R = CheckPlaceholderExpr(E);
296 if (R.isInvalid()) return ExprError();
300 if (E->getType()->isDependentType()) {
301 Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
302 Coroutine->CoroutineStmts.push_back(Res);
306 // If the expression is a temporary, materialize it as an lvalue so that we
307 // can use it multiple times.
308 if (E->getValueKind() == VK_RValue)
309 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
311 // Build the await_ready, await_suspend, await_resume calls.
312 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
316 Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
318 Coroutine->CoroutineStmts.push_back(Res);
322 static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
323 SourceLocation Loc, StringRef Name,
324 MutableArrayRef<Expr *> Args) {
325 assert(Coroutine->CoroutinePromise && "no promise for coroutine");
327 // Form a reference to the promise.
328 auto *Promise = Coroutine->CoroutinePromise;
329 ExprResult PromiseRef = S.BuildDeclRefExpr(
330 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
331 if (PromiseRef.isInvalid())
334 // Call 'yield_value', passing in E.
335 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
338 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
339 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
341 CorrectDelayedTyposInExpr(E);
345 // Build yield_value call.
346 ExprResult Awaitable =
347 buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
348 if (Awaitable.isInvalid())
351 // Build 'operator co_await' call.
352 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
353 if (Awaitable.isInvalid())
356 return BuildCoyieldExpr(Loc, Awaitable.get());
358 ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
359 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
363 if (E->getType()->isPlaceholderType()) {
364 ExprResult R = CheckPlaceholderExpr(E);
365 if (R.isInvalid()) return ExprError();
369 if (E->getType()->isDependentType()) {
370 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
371 Coroutine->CoroutineStmts.push_back(Res);
375 // If the expression is a temporary, materialize it as an lvalue so that we
376 // can use it multiple times.
377 if (E->getValueKind() == VK_RValue)
378 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
380 // Build the await_ready, await_suspend, await_resume calls.
381 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
385 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
387 Coroutine->CoroutineStmts.push_back(Res);
391 StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
392 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
394 CorrectDelayedTyposInExpr(E);
397 return BuildCoreturnStmt(Loc, E);
400 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
401 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
405 if (E && E->getType()->isPlaceholderType() &&
406 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
407 ExprResult R = CheckPlaceholderExpr(E);
408 if (R.isInvalid()) return StmtError();
412 // FIXME: If the operand is a reference to a variable that's about to go out
413 // of scope, we should treat the operand as an xvalue for this overload
416 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
417 PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
419 E = MakeFullDiscardedValueExpr(E).get();
420 PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
425 Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
427 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
428 Coroutine->CoroutineStmts.push_back(Res);
432 static ExprResult buildStdCurrentExceptionCall(Sema &S, SourceLocation Loc) {
433 NamespaceDecl *Std = S.getStdNamespace();
435 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
438 LookupResult Result(S, &S.PP.getIdentifierTable().get("current_exception"),
439 Loc, Sema::LookupOrdinaryName);
440 if (!S.LookupQualifiedName(Result, Std)) {
441 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
445 // FIXME The STL is free to provide more than one overload.
446 FunctionDecl *FD = Result.getAsSingle<FunctionDecl>();
448 S.Diag(Loc, diag::err_malformed_std_current_exception);
451 ExprResult Res = S.BuildDeclRefExpr(FD, FD->getType(), VK_LValue, Loc);
452 Res = S.ActOnCallExpr(/*Scope*/ nullptr, Res.get(), Loc, None, Loc);
453 if (Res.isInvalid()) {
454 S.Diag(Loc, diag::err_malformed_std_current_exception);
460 // Find an appropriate delete for the promise.
461 static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
462 QualType PromiseType) {
463 FunctionDecl *OperatorDelete = nullptr;
465 DeclarationName DeleteName =
466 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
468 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
469 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
471 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
474 if (!OperatorDelete) {
475 // Look for a global declaration.
476 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
477 const bool Overaligned = false;
478 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
479 Overaligned, DeleteName);
481 S.MarkFunctionReferenced(Loc, OperatorDelete);
482 return OperatorDelete;
485 // Builds allocation and deallocation for the coroutine. Returns false on
487 static bool buildAllocationAndDeallocation(Sema &S, SourceLocation Loc,
488 FunctionScopeInfo *Fn,
490 Stmt *&Deallocation) {
491 TypeSourceInfo *TInfo = Fn->CoroutinePromise->getTypeSourceInfo();
492 QualType PromiseType = TInfo->getType();
493 if (PromiseType->isDependentType())
496 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
499 // FIXME: Add support for get_return_object_on_allocation failure.
500 // FIXME: Add support for stateful allocators.
502 FunctionDecl *OperatorNew = nullptr;
503 FunctionDecl *OperatorDelete = nullptr;
504 FunctionDecl *UnusedResult = nullptr;
505 bool PassAlignment = false;
507 S.FindAllocationFunctions(Loc, SourceRange(),
508 /*UseGlobal*/ false, PromiseType,
509 /*isArray*/ false, PassAlignment,
510 /*PlacementArgs*/ None, OperatorNew, UnusedResult);
512 OperatorDelete = findDeleteForPromise(S, Loc, PromiseType);
514 if (!OperatorDelete || !OperatorNew)
518 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
521 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
526 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
527 if (NewRef.isInvalid())
531 S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc);
532 if (NewExpr.isInvalid())
535 Allocation = NewExpr.get();
539 QualType OpDeleteQualType = OperatorDelete->getType();
541 ExprResult DeleteRef =
542 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
543 if (DeleteRef.isInvalid())
547 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
549 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
551 // Check if we need to pass the size.
552 const auto *OpDeleteType =
553 OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>();
554 if (OpDeleteType->getNumParams() > 1)
555 DeleteArgs.push_back(FrameSize);
557 ExprResult DeleteExpr =
558 S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
559 if (DeleteExpr.isInvalid())
562 Deallocation = DeleteExpr.get();
567 void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
568 FunctionScopeInfo *Fn = getCurFunction();
569 assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
571 // Coroutines [stmt.return]p1:
572 // A return statement shall not appear in a coroutine.
573 if (Fn->FirstReturnLoc.isValid()) {
574 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
575 auto *First = Fn->CoroutineStmts[0];
576 Diag(First->getLocStart(), diag::note_declared_coroutine_here)
577 << (isa<CoawaitExpr>(First) ? 0 :
578 isa<CoyieldExpr>(First) ? 1 : 2);
581 SourceLocation Loc = FD->getLocation();
583 // Form a declaration statement for the promise declaration, so that AST
584 // visitors can more easily find it.
585 StmtResult PromiseStmt =
586 ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
587 if (PromiseStmt.isInvalid())
588 return FD->setInvalidDecl();
590 // Form and check implicit 'co_await p.initial_suspend();' statement.
591 ExprResult InitialSuspend =
592 buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
593 // FIXME: Support operator co_await here.
594 if (!InitialSuspend.isInvalid())
595 InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
596 InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
597 if (InitialSuspend.isInvalid())
598 return FD->setInvalidDecl();
600 // Form and check implicit 'co_await p.final_suspend();' statement.
601 ExprResult FinalSuspend =
602 buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
603 // FIXME: Support operator co_await here.
604 if (!FinalSuspend.isInvalid())
605 FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
606 FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
607 if (FinalSuspend.isInvalid())
608 return FD->setInvalidDecl();
610 // Form and check allocation and deallocation calls.
611 Expr *Allocation = nullptr;
612 Stmt *Deallocation = nullptr;
613 if (!buildAllocationAndDeallocation(*this, Loc, Fn, Allocation, Deallocation))
614 return FD->setInvalidDecl();
616 // control flowing off the end of the coroutine.
617 // Also try to form 'p.set_exception(std::current_exception());' to handle
618 // uncaught exceptions.
619 ExprResult SetException;
620 StmtResult Fallthrough;
621 if (Fn->CoroutinePromise &&
622 !Fn->CoroutinePromise->getType()->isDependentType()) {
623 CXXRecordDecl *RD = Fn->CoroutinePromise->getType()->getAsCXXRecordDecl();
624 assert(RD && "Type should have already been checked");
625 // [dcl.fct.def.coroutine]/4
626 // The unqualified-ids 'return_void' and 'return_value' are looked up in
627 // the scope of class P. If both are found, the program is ill-formed.
628 DeclarationName RVoidDN = PP.getIdentifierInfo("return_void");
629 LookupResult RVoidResult(*this, RVoidDN, Loc, Sema::LookupMemberName);
630 const bool HasRVoid = LookupQualifiedName(RVoidResult, RD);
632 DeclarationName RValueDN = PP.getIdentifierInfo("return_value");
633 LookupResult RValueResult(*this, RValueDN, Loc, Sema::LookupMemberName);
634 const bool HasRValue = LookupQualifiedName(RValueResult, RD);
636 if (HasRVoid && HasRValue) {
637 // FIXME Improve this diagnostic
638 Diag(FD->getLocation(), diag::err_coroutine_promise_return_ill_formed)
640 return FD->setInvalidDecl();
641 } else if (HasRVoid) {
642 // If the unqualified-id return_void is found, flowing off the end of a
643 // coroutine is equivalent to a co_return with no operand. Otherwise,
644 // flowing off the end of a coroutine results in undefined behavior.
645 Fallthrough = BuildCoreturnStmt(FD->getLocation(), nullptr);
646 Fallthrough = ActOnFinishFullStmt(Fallthrough.get());
647 if (Fallthrough.isInvalid())
648 return FD->setInvalidDecl();
651 // [dcl.fct.def.coroutine]/3
652 // The unqualified-id set_exception is found in the scope of P by class
653 // member access lookup (3.4.5).
654 DeclarationName SetExDN = PP.getIdentifierInfo("set_exception");
655 LookupResult SetExResult(*this, SetExDN, Loc, Sema::LookupMemberName);
656 if (LookupQualifiedName(SetExResult, RD)) {
657 // Form the call 'p.set_exception(std::current_exception())'
658 SetException = buildStdCurrentExceptionCall(*this, Loc);
659 if (SetException.isInvalid())
660 return FD->setInvalidDecl();
661 Expr *E = SetException.get();
662 SetException = buildPromiseCall(*this, Fn, Loc, "set_exception", E);
663 SetException = ActOnFinishFullExpr(SetException.get(), Loc);
664 if (SetException.isInvalid())
665 return FD->setInvalidDecl();
669 // Build implicit 'p.get_return_object()' expression and form initialization
670 // of return type from it.
671 ExprResult ReturnObject =
672 buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
673 if (ReturnObject.isInvalid())
674 return FD->setInvalidDecl();
675 QualType RetType = FD->getReturnType();
676 if (!RetType->isDependentType()) {
677 InitializedEntity Entity =
678 InitializedEntity::InitializeResult(Loc, RetType, false);
679 ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
681 if (ReturnObject.isInvalid())
682 return FD->setInvalidDecl();
684 ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
685 if (ReturnObject.isInvalid())
686 return FD->setInvalidDecl();
688 // FIXME: Perform move-initialization of parameters into frame-local copies.
689 SmallVector<Expr*, 16> ParamMoves;
691 // Build body for the coroutine wrapper statement.
692 Body = new (Context) CoroutineBodyStmt(
693 Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
694 SetException.get(), Fallthrough.get(), Allocation, Deallocation,
695 ReturnObject.get(), ParamMoves);