1 //===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements semantic analysis for C++ Coroutines.
11 //
12 //===----------------------------------------------------------------------===//
13 
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;
22 using namespace sema;
23 
24 static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
25                          SourceLocation Loc) {
26   DeclarationName DN = S.PP.getIdentifierInfo(Name);
27   LookupResult LR(S, DN, Loc, Sema::LookupMemberName);
28   // Suppress diagnostics when a private member is selected. The same warnings
29   // will be produced again when building the call.
30   LR.suppressDiagnostics();
31   return S.LookupQualifiedName(LR, RD);
32 }
33 
34 /// Look up the std::coroutine_traits<...>::promise_type for the given
35 /// function type.
36 static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
37                                   SourceLocation KwLoc,
38                                   SourceLocation FuncLoc) {
39   // FIXME: Cache std::coroutine_traits once we've found it.
40   NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
41   if (!StdExp) {
42     S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
43         << "std::experimental::coroutine_traits";
44     return QualType();
45   }
46 
47   LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
48                       FuncLoc, Sema::LookupOrdinaryName);
49   if (!S.LookupQualifiedName(Result, StdExp)) {
50     S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
51         << "std::experimental::coroutine_traits";
52     return QualType();
53   }
54 
55   ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
56   if (!CoroTraits) {
57     Result.suppressDiagnostics();
58     // We found something weird. Complain about the first thing we found.
59     NamedDecl *Found = *Result.begin();
60     S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
61     return QualType();
62   }
63 
64   // Form template argument list for coroutine_traits<R, P1, P2, ...>.
65   TemplateArgumentListInfo Args(KwLoc, KwLoc);
66   Args.addArgument(TemplateArgumentLoc(
67       TemplateArgument(FnType->getReturnType()),
68       S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), KwLoc)));
69   // FIXME: If the function is a non-static member function, add the type
70   // of the implicit object parameter before the formal parameters.
71   for (QualType T : FnType->getParamTypes())
72     Args.addArgument(TemplateArgumentLoc(
73         TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc)));
74 
75   // Build the template-id.
76   QualType CoroTrait =
77       S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args);
78   if (CoroTrait.isNull())
79     return QualType();
80   if (S.RequireCompleteType(KwLoc, CoroTrait,
81                             diag::err_coroutine_type_missing_specialization))
82     return QualType();
83 
84   auto *RD = CoroTrait->getAsCXXRecordDecl();
85   assert(RD && "specialization of class template is not a class?");
86 
87   // Look up the ::promise_type member.
88   LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc,
89                  Sema::LookupOrdinaryName);
90   S.LookupQualifiedName(R, RD);
91   auto *Promise = R.getAsSingle<TypeDecl>();
92   if (!Promise) {
93     S.Diag(FuncLoc,
94            diag::err_implied_std_coroutine_traits_promise_type_not_found)
95         << RD;
96     return QualType();
97   }
98   // The promise type is required to be a class type.
99   QualType PromiseType = S.Context.getTypeDeclType(Promise);
100 
101   auto buildElaboratedType = [&]() {
102     auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp);
103     NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
104                                       CoroTrait.getTypePtr());
105     return S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
106   };
107 
108   if (!PromiseType->getAsCXXRecordDecl()) {
109     S.Diag(FuncLoc,
110            diag::err_implied_std_coroutine_traits_promise_type_not_class)
111         << buildElaboratedType();
112     return QualType();
113   }
114   if (S.RequireCompleteType(FuncLoc, buildElaboratedType(),
115                             diag::err_coroutine_promise_type_incomplete))
116     return QualType();
117 
118   return PromiseType;
119 }
120 
121 /// Look up the std::coroutine_traits<...>::promise_type for the given
122 /// function type.
123 static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
124                                           SourceLocation Loc) {
125   if (PromiseType.isNull())
126     return QualType();
127 
128   NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
129   assert(StdExp && "Should already be diagnosed");
130 
131   LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
132                       Loc, Sema::LookupOrdinaryName);
133   if (!S.LookupQualifiedName(Result, StdExp)) {
134     S.Diag(Loc, diag::err_implied_coroutine_type_not_found)
135         << "std::experimental::coroutine_handle";
136     return QualType();
137   }
138 
139   ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>();
140   if (!CoroHandle) {
141     Result.suppressDiagnostics();
142     // We found something weird. Complain about the first thing we found.
143     NamedDecl *Found = *Result.begin();
144     S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle);
145     return QualType();
146   }
147 
148   // Form template argument list for coroutine_handle<Promise>.
149   TemplateArgumentListInfo Args(Loc, Loc);
150   Args.addArgument(TemplateArgumentLoc(
151       TemplateArgument(PromiseType),
152       S.Context.getTrivialTypeSourceInfo(PromiseType, Loc)));
153 
154   // Build the template-id.
155   QualType CoroHandleType =
156       S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args);
157   if (CoroHandleType.isNull())
158     return QualType();
159   if (S.RequireCompleteType(Loc, CoroHandleType,
160                             diag::err_coroutine_type_missing_specialization))
161     return QualType();
162 
163   return CoroHandleType;
164 }
165 
166 static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
167                                     StringRef Keyword) {
168   // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
169   if (S.isUnevaluatedContext()) {
170     S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
171     return false;
172   }
173 
174   // Any other usage must be within a function.
175   auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
176   if (!FD) {
177     S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
178                     ? diag::err_coroutine_objc_method
179                     : diag::err_coroutine_outside_function) << Keyword;
180     return false;
181   }
182 
183   // An enumeration for mapping the diagnostic type to the correct diagnostic
184   // selection index.
185   enum InvalidFuncDiag {
186     DiagCtor = 0,
187     DiagDtor,
188     DiagCopyAssign,
189     DiagMoveAssign,
190     DiagMain,
191     DiagConstexpr,
192     DiagAutoRet,
193     DiagVarargs,
194   };
195   bool Diagnosed = false;
196   auto DiagInvalid = [&](InvalidFuncDiag ID) {
197     S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
198     Diagnosed = true;
199     return false;
200   };
201 
202   // Diagnose when a constructor, destructor, copy/move assignment operator,
203   // or the function 'main' are declared as a coroutine.
204   auto *MD = dyn_cast<CXXMethodDecl>(FD);
205   if (MD && isa<CXXConstructorDecl>(MD))
206     return DiagInvalid(DiagCtor);
207   else if (MD && isa<CXXDestructorDecl>(MD))
208     return DiagInvalid(DiagDtor);
209   else if (MD && MD->isCopyAssignmentOperator())
210     return DiagInvalid(DiagCopyAssign);
211   else if (MD && MD->isMoveAssignmentOperator())
212     return DiagInvalid(DiagMoveAssign);
213   else if (FD->isMain())
214     return DiagInvalid(DiagMain);
215 
216   // Emit a diagnostics for each of the following conditions which is not met.
217   if (FD->isConstexpr())
218     DiagInvalid(DiagConstexpr);
219   if (FD->getReturnType()->isUndeducedType())
220     DiagInvalid(DiagAutoRet);
221   if (FD->isVariadic())
222     DiagInvalid(DiagVarargs);
223 
224   return !Diagnosed;
225 }
226 
227 static ExprResult buildOperatorCoawaitLookupExpr(Sema &SemaRef, Scope *S,
228                                                  SourceLocation Loc) {
229   DeclarationName OpName =
230       SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
231   LookupResult Operators(SemaRef, OpName, SourceLocation(),
232                          Sema::LookupOperatorName);
233   SemaRef.LookupName(Operators, S);
234 
235   assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
236   const auto &Functions = Operators.asUnresolvedSet();
237   bool IsOverloaded =
238       Functions.size() > 1 ||
239       (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
240   Expr *CoawaitOp = UnresolvedLookupExpr::Create(
241       SemaRef.Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
242       DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded,
243       Functions.begin(), Functions.end());
244   assert(CoawaitOp);
245   return CoawaitOp;
246 }
247 
248 /// Build a call to 'operator co_await' if there is a suitable operator for
249 /// the given expression.
250 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, SourceLocation Loc,
251                                            Expr *E,
252                                            UnresolvedLookupExpr *Lookup) {
253   UnresolvedSet<16> Functions;
254   Functions.append(Lookup->decls_begin(), Lookup->decls_end());
255   return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
256 }
257 
258 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
259                                            SourceLocation Loc, Expr *E) {
260   ExprResult R = buildOperatorCoawaitLookupExpr(SemaRef, S, Loc);
261   if (R.isInvalid())
262     return ExprError();
263   return buildOperatorCoawaitCall(SemaRef, Loc, E,
264                                   cast<UnresolvedLookupExpr>(R.get()));
265 }
266 
267 static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
268                               MultiExprArg CallArgs) {
269   StringRef Name = S.Context.BuiltinInfo.getName(Id);
270   LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
271   S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
272 
273   auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
274   assert(BuiltInDecl && "failed to find builtin declaration");
275 
276   ExprResult DeclRef =
277       S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
278   assert(DeclRef.isUsable() && "Builtin reference cannot fail");
279 
280   ExprResult Call =
281       S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
282 
283   assert(!Call.isInvalid() && "Call to builtin cannot fail!");
284   return Call.get();
285 }
286 
287 static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
288                                        SourceLocation Loc) {
289   QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
290   if (CoroHandleType.isNull())
291     return ExprError();
292 
293   DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType);
294   LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc,
295                      Sema::LookupOrdinaryName);
296   if (!S.LookupQualifiedName(Found, LookupCtx)) {
297     S.Diag(Loc, diag::err_coroutine_handle_missing_member)
298         << "from_address";
299     return ExprError();
300   }
301 
302   Expr *FramePtr =
303       buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
304 
305   CXXScopeSpec SS;
306   ExprResult FromAddr =
307       S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
308   if (FromAddr.isInvalid())
309     return ExprError();
310 
311   return S.ActOnCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc);
312 }
313 
314 struct ReadySuspendResumeResult {
315   Expr *Results[3];
316   OpaqueValueExpr *OpaqueValue;
317   bool IsInvalid;
318 };
319 
320 static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
321                                   StringRef Name, MultiExprArg Args) {
322   DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
323 
324   // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
325   CXXScopeSpec SS;
326   ExprResult Result = S.BuildMemberReferenceExpr(
327       Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
328       SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
329       /*Scope=*/nullptr);
330   if (Result.isInvalid())
331     return ExprError();
332 
333   return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
334 }
335 
336 /// Build calls to await_ready, await_suspend, and await_resume for a co_await
337 /// expression.
338 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
339                                                   SourceLocation Loc, Expr *E) {
340   OpaqueValueExpr *Operand = new (S.Context)
341       OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
342 
343   // Assume invalid until we see otherwise.
344   ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true};
345 
346   ExprResult CoroHandleRes = buildCoroutineHandle(S, CoroPromise->getType(), Loc);
347   if (CoroHandleRes.isInvalid())
348     return Calls;
349   Expr *CoroHandle = CoroHandleRes.get();
350 
351   const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
352   MultiExprArg Args[] = {None, CoroHandle, None};
353   for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
354     ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], Args[I]);
355     if (Result.isInvalid())
356       return Calls;
357     Calls.Results[I] = Result.get();
358   }
359 
360   Calls.IsInvalid = false;
361   return Calls;
362 }
363 
364 static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise,
365                                    SourceLocation Loc, StringRef Name,
366                                    MultiExprArg Args) {
367 
368   // Form a reference to the promise.
369   ExprResult PromiseRef = S.BuildDeclRefExpr(
370       Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
371   if (PromiseRef.isInvalid())
372     return ExprError();
373 
374   // Call 'yield_value', passing in E.
375   return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
376 }
377 
378 VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
379   assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
380   auto *FD = cast<FunctionDecl>(CurContext);
381 
382   QualType T =
383       FD->getType()->isDependentType()
384           ? Context.DependentTy
385           : lookupPromiseType(*this, FD->getType()->castAs<FunctionProtoType>(),
386                               Loc, FD->getLocation());
387   if (T.isNull())
388     return nullptr;
389 
390   auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
391                              &PP.getIdentifierTable().get("__promise"), T,
392                              Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
393   CheckVariableDeclarationType(VD);
394   if (VD->isInvalidDecl())
395     return nullptr;
396   ActOnUninitializedDecl(VD);
397   assert(!VD->isInvalidDecl());
398   return VD;
399 }
400 
401 /// Check that this is a context in which a coroutine suspension can appear.
402 static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
403                                                 StringRef Keyword,
404                                                 bool IsImplicit = false) {
405   if (!isValidCoroutineContext(S, Loc, Keyword))
406     return nullptr;
407 
408   assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
409 
410   auto *ScopeInfo = S.getCurFunction();
411   assert(ScopeInfo && "missing function scope for function");
412 
413   if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
414     ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
415 
416   if (ScopeInfo->CoroutinePromise)
417     return ScopeInfo;
418 
419   ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
420   if (!ScopeInfo->CoroutinePromise)
421     return nullptr;
422 
423   return ScopeInfo;
424 }
425 
426 static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
427                                     StringRef Keyword) {
428   if (!checkCoroutineContext(S, KWLoc, Keyword))
429     return false;
430   auto *ScopeInfo = S.getCurFunction();
431   assert(ScopeInfo->CoroutinePromise);
432 
433   // If we have existing coroutine statements then we have already built
434   // the initial and final suspend points.
435   if (!ScopeInfo->NeedsCoroutineSuspends)
436     return true;
437 
438   ScopeInfo->setNeedsCoroutineSuspends(false);
439 
440   auto *Fn = cast<FunctionDecl>(S.CurContext);
441   SourceLocation Loc = Fn->getLocation();
442   // Build the initial suspend point
443   auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
444     ExprResult Suspend =
445         buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None);
446     if (Suspend.isInvalid())
447       return StmtError();
448     Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get());
449     if (Suspend.isInvalid())
450       return StmtError();
451     Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(),
452                                          /*IsImplicit*/ true);
453     Suspend = S.ActOnFinishFullExpr(Suspend.get());
454     if (Suspend.isInvalid()) {
455       S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
456           << ((Name == "initial_suspend") ? 0 : 1);
457       S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
458       return StmtError();
459     }
460     return cast<Stmt>(Suspend.get());
461   };
462 
463   StmtResult InitSuspend = buildSuspends("initial_suspend");
464   if (InitSuspend.isInvalid())
465     return true;
466 
467   StmtResult FinalSuspend = buildSuspends("final_suspend");
468   if (FinalSuspend.isInvalid())
469     return true;
470 
471   ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
472 
473   return true;
474 }
475 
476 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
477   if (!actOnCoroutineBodyStart(*this, S, Loc, "co_await")) {
478     CorrectDelayedTyposInExpr(E);
479     return ExprError();
480   }
481 
482   if (E->getType()->isPlaceholderType()) {
483     ExprResult R = CheckPlaceholderExpr(E);
484     if (R.isInvalid()) return ExprError();
485     E = R.get();
486   }
487   ExprResult Lookup = buildOperatorCoawaitLookupExpr(*this, S, Loc);
488   if (Lookup.isInvalid())
489     return ExprError();
490   return BuildUnresolvedCoawaitExpr(Loc, E,
491                                    cast<UnresolvedLookupExpr>(Lookup.get()));
492 }
493 
494 ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
495                                             UnresolvedLookupExpr *Lookup) {
496   auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
497   if (!FSI)
498     return ExprError();
499 
500   if (E->getType()->isPlaceholderType()) {
501     ExprResult R = CheckPlaceholderExpr(E);
502     if (R.isInvalid())
503       return ExprError();
504     E = R.get();
505   }
506 
507   auto *Promise = FSI->CoroutinePromise;
508   if (Promise->getType()->isDependentType()) {
509     Expr *Res =
510         new (Context) DependentCoawaitExpr(Loc, Context.DependentTy, E, Lookup);
511     return Res;
512   }
513 
514   auto *RD = Promise->getType()->getAsCXXRecordDecl();
515   if (lookupMember(*this, "await_transform", RD, Loc)) {
516     ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E);
517     if (R.isInvalid()) {
518       Diag(Loc,
519            diag::note_coroutine_promise_implicit_await_transform_required_here)
520           << E->getSourceRange();
521       return ExprError();
522     }
523     E = R.get();
524   }
525   ExprResult Awaitable = buildOperatorCoawaitCall(*this, Loc, E, Lookup);
526   if (Awaitable.isInvalid())
527     return ExprError();
528 
529   return BuildResolvedCoawaitExpr(Loc, Awaitable.get());
530 }
531 
532 ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
533                                   bool IsImplicit) {
534   auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
535   if (!Coroutine)
536     return ExprError();
537 
538   if (E->getType()->isPlaceholderType()) {
539     ExprResult R = CheckPlaceholderExpr(E);
540     if (R.isInvalid()) return ExprError();
541     E = R.get();
542   }
543 
544   if (E->getType()->isDependentType()) {
545     Expr *Res = new (Context)
546         CoawaitExpr(Loc, Context.DependentTy, E, IsImplicit);
547     return Res;
548   }
549 
550   // If the expression is a temporary, materialize it as an lvalue so that we
551   // can use it multiple times.
552   if (E->getValueKind() == VK_RValue)
553     E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
554 
555   // Build the await_ready, await_suspend, await_resume calls.
556   ReadySuspendResumeResult RSS =
557       buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
558   if (RSS.IsInvalid)
559     return ExprError();
560 
561   Expr *Res =
562       new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
563                                 RSS.Results[2], RSS.OpaqueValue, IsImplicit);
564 
565   return Res;
566 }
567 
568 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
569   if (!actOnCoroutineBodyStart(*this, S, Loc, "co_yield")) {
570     CorrectDelayedTyposInExpr(E);
571     return ExprError();
572   }
573 
574   // Build yield_value call.
575   ExprResult Awaitable = buildPromiseCall(
576       *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
577   if (Awaitable.isInvalid())
578     return ExprError();
579 
580   // Build 'operator co_await' call.
581   Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
582   if (Awaitable.isInvalid())
583     return ExprError();
584 
585   return BuildCoyieldExpr(Loc, Awaitable.get());
586 }
587 ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
588   auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
589   if (!Coroutine)
590     return ExprError();
591 
592   if (E->getType()->isPlaceholderType()) {
593     ExprResult R = CheckPlaceholderExpr(E);
594     if (R.isInvalid()) return ExprError();
595     E = R.get();
596   }
597 
598   if (E->getType()->isDependentType()) {
599     Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
600     return Res;
601   }
602 
603   // If the expression is a temporary, materialize it as an lvalue so that we
604   // can use it multiple times.
605   if (E->getValueKind() == VK_RValue)
606     E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
607 
608   // Build the await_ready, await_suspend, await_resume calls.
609   ReadySuspendResumeResult RSS =
610       buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
611   if (RSS.IsInvalid)
612     return ExprError();
613 
614   Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
615                                         RSS.Results[2], RSS.OpaqueValue);
616 
617   return Res;
618 }
619 
620 StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
621   if (!actOnCoroutineBodyStart(*this, S, Loc, "co_return")) {
622     CorrectDelayedTyposInExpr(E);
623     return StmtError();
624   }
625   return BuildCoreturnStmt(Loc, E);
626 }
627 
628 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
629                                    bool IsImplicit) {
630   auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
631   if (!FSI)
632     return StmtError();
633 
634   if (E && E->getType()->isPlaceholderType() &&
635       !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
636     ExprResult R = CheckPlaceholderExpr(E);
637     if (R.isInvalid()) return StmtError();
638     E = R.get();
639   }
640 
641   // FIXME: If the operand is a reference to a variable that's about to go out
642   // of scope, we should treat the operand as an xvalue for this overload
643   // resolution.
644   VarDecl *Promise = FSI->CoroutinePromise;
645   ExprResult PC;
646   if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
647     PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
648   } else {
649     E = MakeFullDiscardedValueExpr(E).get();
650     PC = buildPromiseCall(*this, Promise, Loc, "return_void", None);
651   }
652   if (PC.isInvalid())
653     return StmtError();
654 
655   Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
656 
657   Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
658   return Res;
659 }
660 
661 // Find an appropriate delete for the promise.
662 static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
663                                           QualType PromiseType) {
664   FunctionDecl *OperatorDelete = nullptr;
665 
666   DeclarationName DeleteName =
667       S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
668 
669   auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
670   assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
671 
672   if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
673     return nullptr;
674 
675   if (!OperatorDelete) {
676     // Look for a global declaration.
677     const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
678     const bool Overaligned = false;
679     OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
680                                                      Overaligned, DeleteName);
681   }
682   S.MarkFunctionReferenced(Loc, OperatorDelete);
683   return OperatorDelete;
684 }
685 
686 namespace {
687 class SubStmtBuilder : public CoroutineBodyStmt::CtorArgs {
688   Sema &S;
689   FunctionDecl &FD;
690   FunctionScopeInfo &Fn;
691   bool IsValid;
692   SourceLocation Loc;
693   QualType RetType;
694   SmallVector<Stmt *, 4> ParamMovesVector;
695   const bool IsPromiseDependentType;
696   CXXRecordDecl *PromiseRecordDecl = nullptr;
697 
698 public:
699   SubStmtBuilder(Sema &S, FunctionDecl &FD, FunctionScopeInfo &Fn, Stmt *Body)
700       : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
701         IsPromiseDependentType(
702             !Fn.CoroutinePromise ||
703             Fn.CoroutinePromise->getType()->isDependentType()) {
704     this->Body = Body;
705     if (!IsPromiseDependentType) {
706       PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
707       assert(PromiseRecordDecl && "Type should have already been checked");
708     }
709     this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend() &&
710                     makeOnException() && makeOnFallthrough() &&
711                     makeNewAndDeleteExpr() && makeReturnObject() &&
712                     makeParamMoves();
713   }
714 
715   bool isInvalid() const { return !this->IsValid; }
716 
717   bool makePromiseStmt();
718   bool makeInitialAndFinalSuspend();
719   bool makeNewAndDeleteExpr();
720   bool makeOnFallthrough();
721   bool makeOnException();
722   bool makeReturnObject();
723   bool makeParamMoves();
724 };
725 }
726 
727 void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
728   FunctionScopeInfo *Fn = getCurFunction();
729   assert(Fn && Fn->CoroutinePromise && "not a coroutine");
730 
731   if (!Body) {
732     assert(FD->isInvalidDecl() &&
733            "a null body is only allowed for invalid declarations");
734     return;
735   }
736 
737   if (isa<CoroutineBodyStmt>(Body)) {
738     // FIXME(EricWF): Nothing todo. the body is already a transformed coroutine
739     // body statement.
740     return;
741   }
742 
743   // Coroutines [stmt.return]p1:
744   //   A return statement shall not appear in a coroutine.
745   if (Fn->FirstReturnLoc.isValid()) {
746     assert(Fn->FirstCoroutineStmtLoc.isValid() &&
747                    "first coroutine location not set");
748     Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
749     Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
750             << Fn->getFirstCoroutineStmtKeyword();
751   }
752   SubStmtBuilder Builder(*this, *FD, *Fn, Body);
753   if (Builder.isInvalid())
754     return FD->setInvalidDecl();
755 
756   // Build body for the coroutine wrapper statement.
757   Body = CoroutineBodyStmt::Create(Context, Builder);
758 }
759 
760 bool SubStmtBuilder::makePromiseStmt() {
761   // Form a declaration statement for the promise declaration, so that AST
762   // visitors can more easily find it.
763   StmtResult PromiseStmt =
764       S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc);
765   if (PromiseStmt.isInvalid())
766     return false;
767 
768   this->Promise = PromiseStmt.get();
769   return true;
770 }
771 
772 bool SubStmtBuilder::makeInitialAndFinalSuspend() {
773   if (Fn.hasInvalidCoroutineSuspends())
774     return false;
775   this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first);
776   this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
777   return true;
778 }
779 
780 bool SubStmtBuilder::makeNewAndDeleteExpr() {
781   // Form and check allocation and deallocation calls.
782   QualType PromiseType = Fn.CoroutinePromise->getType();
783   if (PromiseType->isDependentType())
784     return true;
785 
786   if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
787     return false;
788 
789   // FIXME: Add support for get_return_object_on_allocation failure.
790   // FIXME: Add support for stateful allocators.
791 
792   FunctionDecl *OperatorNew = nullptr;
793   FunctionDecl *OperatorDelete = nullptr;
794   FunctionDecl *UnusedResult = nullptr;
795   bool PassAlignment = false;
796 
797   S.FindAllocationFunctions(Loc, SourceRange(),
798                             /*UseGlobal*/ false, PromiseType,
799                             /*isArray*/ false, PassAlignment,
800                             /*PlacementArgs*/ None, OperatorNew, UnusedResult);
801 
802   OperatorDelete = findDeleteForPromise(S, Loc, PromiseType);
803 
804   if (!OperatorDelete || !OperatorNew)
805     return false;
806 
807   Expr *FramePtr =
808       buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
809 
810   Expr *FrameSize =
811       buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
812 
813   // Make new call.
814 
815   ExprResult NewRef =
816       S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
817   if (NewRef.isInvalid())
818     return false;
819 
820   ExprResult NewExpr =
821       S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc);
822   if (NewExpr.isInvalid())
823     return false;
824 
825   // Make delete call.
826 
827   QualType OpDeleteQualType = OperatorDelete->getType();
828 
829   ExprResult DeleteRef =
830       S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
831   if (DeleteRef.isInvalid())
832     return false;
833 
834   Expr *CoroFree =
835       buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
836 
837   SmallVector<Expr *, 2> DeleteArgs{CoroFree};
838 
839   // Check if we need to pass the size.
840   const auto *OpDeleteType =
841       OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>();
842   if (OpDeleteType->getNumParams() > 1)
843     DeleteArgs.push_back(FrameSize);
844 
845   ExprResult DeleteExpr =
846       S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
847   if (DeleteExpr.isInvalid())
848     return false;
849 
850   this->Allocate = NewExpr.get();
851   this->Deallocate = DeleteExpr.get();
852 
853   return true;
854 }
855 
856 bool SubStmtBuilder::makeOnFallthrough() {
857   if (!PromiseRecordDecl)
858     return true;
859 
860   // [dcl.fct.def.coroutine]/4
861   // The unqualified-ids 'return_void' and 'return_value' are looked up in
862   // the scope of class P. If both are found, the program is ill-formed.
863   const bool HasRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc);
864   const bool HasRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc);
865 
866   StmtResult Fallthrough;
867   if (HasRVoid && HasRValue) {
868     // FIXME Improve this diagnostic
869     S.Diag(FD.getLocation(), diag::err_coroutine_promise_return_ill_formed)
870         << PromiseRecordDecl;
871     return false;
872   } else if (HasRVoid) {
873     // If the unqualified-id return_void is found, flowing off the end of a
874     // coroutine is equivalent to a co_return with no operand. Otherwise,
875     // flowing off the end of a coroutine results in undefined behavior.
876     Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
877                                       /*IsImplicit*/false);
878     Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
879     if (Fallthrough.isInvalid())
880       return false;
881   }
882 
883   this->OnFallthrough = Fallthrough.get();
884   return true;
885 }
886 
887 bool SubStmtBuilder::makeOnException() {
888   // Try to form 'p.unhandled_exception();'
889 
890   if (!PromiseRecordDecl)
891     return true;
892 
893   const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
894 
895   if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
896     auto DiagID =
897         RequireUnhandledException
898             ? diag::err_coroutine_promise_unhandled_exception_required
899             : diag::
900                   warn_coroutine_promise_unhandled_exception_required_with_exceptions;
901     S.Diag(Loc, DiagID) << PromiseRecordDecl;
902     return !RequireUnhandledException;
903   }
904 
905   // If exceptions are disabled, don't try to build OnException.
906   if (!S.getLangOpts().CXXExceptions)
907     return true;
908 
909   ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
910                                                    "unhandled_exception", None);
911   UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc);
912   if (UnhandledException.isInvalid())
913     return false;
914 
915   this->OnException = UnhandledException.get();
916   return true;
917 }
918 
919 bool SubStmtBuilder::makeReturnObject() {
920 
921   // Build implicit 'p.get_return_object()' expression and form initialization
922   // of return type from it.
923   ExprResult ReturnObject =
924       buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
925   if (ReturnObject.isInvalid())
926     return false;
927   QualType RetType = FD.getReturnType();
928   if (!RetType->isDependentType()) {
929     InitializedEntity Entity =
930         InitializedEntity::InitializeResult(Loc, RetType, false);
931     ReturnObject = S.PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
932                                                    ReturnObject.get());
933     if (ReturnObject.isInvalid())
934       return false;
935   }
936   ReturnObject = S.ActOnFinishFullExpr(ReturnObject.get(), Loc);
937   if (ReturnObject.isInvalid())
938     return false;
939 
940   this->ReturnValue = ReturnObject.get();
941   return true;
942 }
943 
944 bool SubStmtBuilder::makeParamMoves() {
945   // FIXME: Perform move-initialization of parameters into frame-local copies.
946   return true;
947 }
948 
949 StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
950   CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args);
951   if (!Res)
952     return StmtError();
953   return Res;
954 }
955