blob: 6de31462a4138e35a7e448a5ac37b40a86ed1def [file] [log] [blame]
Richard Smithcfd53b42015-10-22 06:13:50 +00001//===--- 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"
Richard Smith9f690bd2015-10-27 06:02:45 +000015#include "clang/AST/Decl.h"
16#include "clang/AST/ExprCXX.h"
17#include "clang/AST/StmtCXX.h"
18#include "clang/Lex/Preprocessor.h"
Richard Smith2af65c42015-11-24 02:34:39 +000019#include "clang/Sema/Initialization.h"
Richard Smith9f690bd2015-10-27 06:02:45 +000020#include "clang/Sema/Overload.h"
Richard Smithcfd53b42015-10-22 06:13:50 +000021using namespace clang;
22using namespace sema;
23
Eric Fiselier20f25cb2017-03-06 23:38:15 +000024static 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
Richard Smith9f690bd2015-10-27 06:02:45 +000034/// Look up the std::coroutine_traits<...>::promise_type for the given
35/// function type.
36static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
Eric Fiselier89bf0e72017-03-06 22:52:28 +000037 SourceLocation KwLoc,
38 SourceLocation FuncLoc) {
Richard Smith9f690bd2015-10-27 06:02:45 +000039 // FIXME: Cache std::coroutine_traits once we've found it.
Gor Nishanov3e048bb2016-10-04 00:31:16 +000040 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
41 if (!StdExp) {
Eric Fiselier89bf0e72017-03-06 22:52:28 +000042 S.Diag(KwLoc, diag::err_implied_std_coroutine_traits_not_found);
Richard Smith9f690bd2015-10-27 06:02:45 +000043 return QualType();
44 }
45
46 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
Eric Fiselier89bf0e72017-03-06 22:52:28 +000047 FuncLoc, Sema::LookupOrdinaryName);
Gor Nishanov3e048bb2016-10-04 00:31:16 +000048 if (!S.LookupQualifiedName(Result, StdExp)) {
Eric Fiselier89bf0e72017-03-06 22:52:28 +000049 S.Diag(KwLoc, diag::err_implied_std_coroutine_traits_not_found);
Richard Smith9f690bd2015-10-27 06:02:45 +000050 return QualType();
51 }
52
53 ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
54 if (!CoroTraits) {
55 Result.suppressDiagnostics();
56 // We found something weird. Complain about the first thing we found.
57 NamedDecl *Found = *Result.begin();
58 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
59 return QualType();
60 }
61
62 // Form template argument list for coroutine_traits<R, P1, P2, ...>.
Eric Fiselier89bf0e72017-03-06 22:52:28 +000063 TemplateArgumentListInfo Args(KwLoc, KwLoc);
Richard Smith9f690bd2015-10-27 06:02:45 +000064 Args.addArgument(TemplateArgumentLoc(
65 TemplateArgument(FnType->getReturnType()),
Eric Fiselier89bf0e72017-03-06 22:52:28 +000066 S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), KwLoc)));
Richard Smith71d403e2015-11-22 07:33:28 +000067 // FIXME: If the function is a non-static member function, add the type
68 // of the implicit object parameter before the formal parameters.
Richard Smith9f690bd2015-10-27 06:02:45 +000069 for (QualType T : FnType->getParamTypes())
70 Args.addArgument(TemplateArgumentLoc(
Eric Fiselier89bf0e72017-03-06 22:52:28 +000071 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc)));
Richard Smith9f690bd2015-10-27 06:02:45 +000072
73 // Build the template-id.
74 QualType CoroTrait =
Eric Fiselier89bf0e72017-03-06 22:52:28 +000075 S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args);
Richard Smith9f690bd2015-10-27 06:02:45 +000076 if (CoroTrait.isNull())
77 return QualType();
Eric Fiselier89bf0e72017-03-06 22:52:28 +000078 if (S.RequireCompleteType(KwLoc, CoroTrait,
Richard Smith9f690bd2015-10-27 06:02:45 +000079 diag::err_coroutine_traits_missing_specialization))
80 return QualType();
81
Eric Fiselier89bf0e72017-03-06 22:52:28 +000082 auto *RD = CoroTrait->getAsCXXRecordDecl();
Richard Smith9f690bd2015-10-27 06:02:45 +000083 assert(RD && "specialization of class template is not a class?");
84
85 // Look up the ::promise_type member.
Eric Fiselier89bf0e72017-03-06 22:52:28 +000086 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc,
Richard Smith9f690bd2015-10-27 06:02:45 +000087 Sema::LookupOrdinaryName);
88 S.LookupQualifiedName(R, RD);
89 auto *Promise = R.getAsSingle<TypeDecl>();
90 if (!Promise) {
Eric Fiselier89bf0e72017-03-06 22:52:28 +000091 S.Diag(FuncLoc,
92 diag::err_implied_std_coroutine_traits_promise_type_not_found)
Gor Nishanov8df64e92016-10-27 16:28:31 +000093 << RD;
Richard Smith9f690bd2015-10-27 06:02:45 +000094 return QualType();
95 }
Richard Smith9f690bd2015-10-27 06:02:45 +000096 // The promise type is required to be a class type.
97 QualType PromiseType = S.Context.getTypeDeclType(Promise);
Eric Fiselier89bf0e72017-03-06 22:52:28 +000098
99 auto buildElaboratedType = [&]() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000100 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp);
Richard Smith9b2f53e2015-11-19 02:36:35 +0000101 NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
102 CoroTrait.getTypePtr());
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000103 return S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
104 };
Richard Smith9b2f53e2015-11-19 02:36:35 +0000105
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000106 if (!PromiseType->getAsCXXRecordDecl()) {
107 S.Diag(FuncLoc,
108 diag::err_implied_std_coroutine_traits_promise_type_not_class)
109 << buildElaboratedType();
Richard Smith9f690bd2015-10-27 06:02:45 +0000110 return QualType();
111 }
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000112 if (S.RequireCompleteType(FuncLoc, buildElaboratedType(),
113 diag::err_coroutine_promise_type_incomplete))
114 return QualType();
Richard Smith9f690bd2015-10-27 06:02:45 +0000115
116 return PromiseType;
117}
118
Eric Fiselierc8efda72016-10-27 18:43:28 +0000119static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
120 StringRef Keyword) {
Richard Smith744b2242015-11-20 02:54:01 +0000121 // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
122 if (S.isUnevaluatedContext()) {
123 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
Eric Fiselierc8efda72016-10-27 18:43:28 +0000124 return false;
Richard Smith744b2242015-11-20 02:54:01 +0000125 }
Richard Smithcfd53b42015-10-22 06:13:50 +0000126
127 // Any other usage must be within a function.
128 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
129 if (!FD) {
130 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
131 ? diag::err_coroutine_objc_method
132 : diag::err_coroutine_outside_function) << Keyword;
Eric Fiselierc8efda72016-10-27 18:43:28 +0000133 return false;
Richard Smithcfd53b42015-10-22 06:13:50 +0000134 }
135
Eric Fiselierc8efda72016-10-27 18:43:28 +0000136 // An enumeration for mapping the diagnostic type to the correct diagnostic
137 // selection index.
138 enum InvalidFuncDiag {
139 DiagCtor = 0,
140 DiagDtor,
141 DiagCopyAssign,
142 DiagMoveAssign,
143 DiagMain,
144 DiagConstexpr,
145 DiagAutoRet,
146 DiagVarargs,
147 };
148 bool Diagnosed = false;
149 auto DiagInvalid = [&](InvalidFuncDiag ID) {
150 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
151 Diagnosed = true;
152 return false;
153 };
154
155 // Diagnose when a constructor, destructor, copy/move assignment operator,
156 // or the function 'main' are declared as a coroutine.
157 auto *MD = dyn_cast<CXXMethodDecl>(FD);
158 if (MD && isa<CXXConstructorDecl>(MD))
159 return DiagInvalid(DiagCtor);
160 else if (MD && isa<CXXDestructorDecl>(MD))
161 return DiagInvalid(DiagDtor);
162 else if (MD && MD->isCopyAssignmentOperator())
163 return DiagInvalid(DiagCopyAssign);
164 else if (MD && MD->isMoveAssignmentOperator())
165 return DiagInvalid(DiagMoveAssign);
166 else if (FD->isMain())
167 return DiagInvalid(DiagMain);
168
169 // Emit a diagnostics for each of the following conditions which is not met.
170 if (FD->isConstexpr())
171 DiagInvalid(DiagConstexpr);
172 if (FD->getReturnType()->isUndeducedType())
173 DiagInvalid(DiagAutoRet);
174 if (FD->isVariadic())
175 DiagInvalid(DiagVarargs);
176
177 return !Diagnosed;
178}
179
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000180static ExprResult buildOperatorCoawaitLookupExpr(Sema &SemaRef, Scope *S,
181 SourceLocation Loc) {
182 DeclarationName OpName =
183 SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
184 LookupResult Operators(SemaRef, OpName, SourceLocation(),
185 Sema::LookupOperatorName);
186 SemaRef.LookupName(Operators, S);
Eric Fiselierc8efda72016-10-27 18:43:28 +0000187
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000188 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
189 const auto &Functions = Operators.asUnresolvedSet();
190 bool IsOverloaded =
191 Functions.size() > 1 ||
192 (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
193 Expr *CoawaitOp = UnresolvedLookupExpr::Create(
194 SemaRef.Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
195 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded,
196 Functions.begin(), Functions.end());
197 assert(CoawaitOp);
198 return CoawaitOp;
199}
Eric Fiselierc8efda72016-10-27 18:43:28 +0000200
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000201/// Build a call to 'operator co_await' if there is a suitable operator for
202/// the given expression.
203static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, SourceLocation Loc,
204 Expr *E,
205 UnresolvedLookupExpr *Lookup) {
206 UnresolvedSet<16> Functions;
207 Functions.append(Lookup->decls_begin(), Lookup->decls_end());
208 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
209}
Eric Fiselierc8efda72016-10-27 18:43:28 +0000210
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000211static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
212 SourceLocation Loc, Expr *E) {
213 ExprResult R = buildOperatorCoawaitLookupExpr(SemaRef, S, Loc);
214 if (R.isInvalid())
215 return ExprError();
216 return buildOperatorCoawaitCall(SemaRef, Loc, E,
217 cast<UnresolvedLookupExpr>(R.get()));
Richard Smithcfd53b42015-10-22 06:13:50 +0000218}
219
Gor Nishanov8df64e92016-10-27 16:28:31 +0000220static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000221 MultiExprArg CallArgs) {
Gor Nishanov8df64e92016-10-27 16:28:31 +0000222 StringRef Name = S.Context.BuiltinInfo.getName(Id);
223 LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
224 S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
225
226 auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
227 assert(BuiltInDecl && "failed to find builtin declaration");
228
229 ExprResult DeclRef =
230 S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
231 assert(DeclRef.isUsable() && "Builtin reference cannot fail");
232
233 ExprResult Call =
234 S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
235
236 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
237 return Call.get();
238}
239
Richard Smithcfd53b42015-10-22 06:13:50 +0000240
Richard Smith9f690bd2015-10-27 06:02:45 +0000241struct ReadySuspendResumeResult {
242 bool IsInvalid;
243 Expr *Results[3];
244};
245
Richard Smith23da82c2015-11-20 22:40:06 +0000246static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000247 StringRef Name, MultiExprArg Args) {
Richard Smith23da82c2015-11-20 22:40:06 +0000248 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
249
250 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
251 CXXScopeSpec SS;
252 ExprResult Result = S.BuildMemberReferenceExpr(
253 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
254 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
255 /*Scope=*/nullptr);
256 if (Result.isInvalid())
257 return ExprError();
258
259 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
260}
261
Richard Smith9f690bd2015-10-27 06:02:45 +0000262/// Build calls to await_ready, await_suspend, and await_resume for a co_await
263/// expression.
264static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
265 Expr *E) {
266 // Assume invalid until we see otherwise.
267 ReadySuspendResumeResult Calls = {true, {}};
268
269 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
270 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000271 Expr *Operand = new (S.Context) OpaqueValueExpr(
Gor Nishanov8df64e92016-10-27 16:28:31 +0000272 Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000273
Richard Smith9f690bd2015-10-27 06:02:45 +0000274 // FIXME: Pass coroutine handle to await_suspend.
Richard Smith23da82c2015-11-20 22:40:06 +0000275 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
Richard Smith9f690bd2015-10-27 06:02:45 +0000276 if (Result.isInvalid())
277 return Calls;
278 Calls.Results[I] = Result.get();
279 }
280
281 Calls.IsInvalid = false;
282 return Calls;
283}
284
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000285static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise,
286 SourceLocation Loc, StringRef Name,
287 MultiExprArg Args) {
288
289 // Form a reference to the promise.
290 ExprResult PromiseRef = S.BuildDeclRefExpr(
291 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
292 if (PromiseRef.isInvalid())
293 return ExprError();
294
295 // Call 'yield_value', passing in E.
296 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
297}
298
299VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
300 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
301 auto *FD = cast<FunctionDecl>(CurContext);
302
303 QualType T =
304 FD->getType()->isDependentType()
305 ? Context.DependentTy
306 : lookupPromiseType(*this, FD->getType()->castAs<FunctionProtoType>(),
307 Loc, FD->getLocation());
308 if (T.isNull())
309 return nullptr;
310
311 auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
312 &PP.getIdentifierTable().get("__promise"), T,
313 Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
314 CheckVariableDeclarationType(VD);
315 if (VD->isInvalidDecl())
316 return nullptr;
317 ActOnUninitializedDecl(VD);
318 assert(!VD->isInvalidDecl());
319 return VD;
320}
321
322/// Check that this is a context in which a coroutine suspension can appear.
323static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
324 StringRef Keyword) {
325 if (!isValidCoroutineContext(S, Loc, Keyword))
326 return nullptr;
327
328 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000329
330 auto *ScopeInfo = S.getCurFunction();
331 assert(ScopeInfo && "missing function scope for function");
332
333 if (ScopeInfo->CoroutinePromise)
334 return ScopeInfo;
335
336 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
337 if (!ScopeInfo->CoroutinePromise)
338 return nullptr;
339
340 return ScopeInfo;
341}
342
343static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
344 StringRef Keyword) {
345 if (!checkCoroutineContext(S, KWLoc, Keyword))
346 return false;
347 auto *ScopeInfo = S.getCurFunction();
348 assert(ScopeInfo->CoroutinePromise);
349
350 // If we have existing coroutine statements then we have already built
351 // the initial and final suspend points.
352 if (!ScopeInfo->NeedsCoroutineSuspends)
353 return true;
354
355 ScopeInfo->setNeedsCoroutineSuspends(false);
356
357 auto *Fn = cast<FunctionDecl>(S.CurContext);
358 SourceLocation Loc = Fn->getLocation();
359 // Build the initial suspend point
360 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
361 ExprResult Suspend =
362 buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None);
363 if (Suspend.isInvalid())
364 return StmtError();
365 Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get());
366 if (Suspend.isInvalid())
367 return StmtError();
368 Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(),
369 /*IsImplicit*/ true);
370 Suspend = S.ActOnFinishFullExpr(Suspend.get());
371 if (Suspend.isInvalid()) {
372 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
373 << ((Name == "initial_suspend") ? 0 : 1);
374 S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
375 return StmtError();
376 }
377 return cast<Stmt>(Suspend.get());
378 };
379
380 StmtResult InitSuspend = buildSuspends("initial_suspend");
381 if (InitSuspend.isInvalid())
382 return true;
383
384 StmtResult FinalSuspend = buildSuspends("final_suspend");
385 if (FinalSuspend.isInvalid())
386 return true;
387
388 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
389
390 return true;
391}
392
Richard Smith9f690bd2015-10-27 06:02:45 +0000393ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000394 if (!actOnCoroutineBodyStart(*this, S, Loc, "co_await")) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000395 CorrectDelayedTyposInExpr(E);
396 return ExprError();
397 }
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000398
Richard Smith10610f72015-11-20 22:57:24 +0000399 if (E->getType()->isPlaceholderType()) {
400 ExprResult R = CheckPlaceholderExpr(E);
401 if (R.isInvalid()) return ExprError();
402 E = R.get();
403 }
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000404 ExprResult Lookup = buildOperatorCoawaitLookupExpr(*this, S, Loc);
405 if (Lookup.isInvalid())
406 return ExprError();
407 return BuildUnresolvedCoawaitExpr(Loc, E,
408 cast<UnresolvedLookupExpr>(Lookup.get()));
409}
Richard Smith10610f72015-11-20 22:57:24 +0000410
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000411ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
412 UnresolvedLookupExpr *Lookup) {
413 auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
414 if (!FSI)
415 return ExprError();
416
417 if (E->getType()->isPlaceholderType()) {
418 ExprResult R = CheckPlaceholderExpr(E);
419 if (R.isInvalid())
420 return ExprError();
421 E = R.get();
422 }
423
424 auto *Promise = FSI->CoroutinePromise;
425 if (Promise->getType()->isDependentType()) {
426 Expr *Res =
427 new (Context) DependentCoawaitExpr(Loc, Context.DependentTy, E, Lookup);
428 FSI->CoroutineStmts.push_back(Res);
429 return Res;
430 }
431
432 auto *RD = Promise->getType()->getAsCXXRecordDecl();
433 if (lookupMember(*this, "await_transform", RD, Loc)) {
434 ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E);
435 if (R.isInvalid()) {
436 Diag(Loc,
437 diag::note_coroutine_promise_implicit_await_transform_required_here)
438 << E->getSourceRange();
439 return ExprError();
440 }
441 E = R.get();
442 }
443 ExprResult Awaitable = buildOperatorCoawaitCall(*this, Loc, E, Lookup);
Richard Smith9f690bd2015-10-27 06:02:45 +0000444 if (Awaitable.isInvalid())
445 return ExprError();
Eric Fiseliera5465282016-09-29 21:47:39 +0000446
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000447 return BuildResolvedCoawaitExpr(Loc, Awaitable.get());
Richard Smith9f690bd2015-10-27 06:02:45 +0000448}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000449
450ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
451 bool IsImplicit) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000452 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
Richard Smith744b2242015-11-20 02:54:01 +0000453 if (!Coroutine)
454 return ExprError();
Richard Smith9f690bd2015-10-27 06:02:45 +0000455
Richard Smith9f690bd2015-10-27 06:02:45 +0000456 if (E->getType()->isPlaceholderType()) {
457 ExprResult R = CheckPlaceholderExpr(E);
458 if (R.isInvalid()) return ExprError();
459 E = R.get();
460 }
461
Richard Smith10610f72015-11-20 22:57:24 +0000462 if (E->getType()->isDependentType()) {
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000463 Expr *Res = new (Context)
464 CoawaitExpr(Loc, Context.DependentTy, E, IsImplicit);
465 if (!IsImplicit)
466 Coroutine->CoroutineStmts.push_back(Res);
Richard Smith10610f72015-11-20 22:57:24 +0000467 return Res;
468 }
469
Richard Smith1f38edd2015-11-22 03:13:02 +0000470 // If the expression is a temporary, materialize it as an lvalue so that we
471 // can use it multiple times.
472 if (E->getValueKind() == VK_RValue)
Tim Shen4a05bb82016-06-21 20:29:17 +0000473 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
Richard Smith9f690bd2015-10-27 06:02:45 +0000474
475 // Build the await_ready, await_suspend, await_resume calls.
476 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
477 if (RSS.IsInvalid)
478 return ExprError();
479
480 Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000481 RSS.Results[2], IsImplicit);
482 if (!IsImplicit)
483 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000484 return Res;
485}
486
Richard Smith9f690bd2015-10-27 06:02:45 +0000487ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000488 if (!actOnCoroutineBodyStart(*this, S, Loc, "co_yield")) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000489 CorrectDelayedTyposInExpr(E);
Richard Smith23da82c2015-11-20 22:40:06 +0000490 return ExprError();
Eric Fiseliera5465282016-09-29 21:47:39 +0000491 }
Richard Smith23da82c2015-11-20 22:40:06 +0000492
493 // Build yield_value call.
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000494 ExprResult Awaitable = buildPromiseCall(
495 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000496 if (Awaitable.isInvalid())
497 return ExprError();
Richard Smith23da82c2015-11-20 22:40:06 +0000498
499 // Build 'operator co_await' call.
500 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
501 if (Awaitable.isInvalid())
502 return ExprError();
503
Richard Smith9f690bd2015-10-27 06:02:45 +0000504 return BuildCoyieldExpr(Loc, Awaitable.get());
505}
506ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
507 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
Richard Smith744b2242015-11-20 02:54:01 +0000508 if (!Coroutine)
509 return ExprError();
Richard Smithcfd53b42015-10-22 06:13:50 +0000510
Richard Smith10610f72015-11-20 22:57:24 +0000511 if (E->getType()->isPlaceholderType()) {
512 ExprResult R = CheckPlaceholderExpr(E);
513 if (R.isInvalid()) return ExprError();
514 E = R.get();
515 }
516
Richard Smithd7bed4d2015-11-22 02:57:17 +0000517 if (E->getType()->isDependentType()) {
518 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
519 Coroutine->CoroutineStmts.push_back(Res);
520 return Res;
521 }
522
Richard Smith1f38edd2015-11-22 03:13:02 +0000523 // If the expression is a temporary, materialize it as an lvalue so that we
524 // can use it multiple times.
525 if (E->getValueKind() == VK_RValue)
Tim Shen4a05bb82016-06-21 20:29:17 +0000526 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
Richard Smithd7bed4d2015-11-22 02:57:17 +0000527
528 // Build the await_ready, await_suspend, await_resume calls.
529 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
530 if (RSS.IsInvalid)
531 return ExprError();
532
533 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
534 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000535 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000536 return Res;
537}
538
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000539StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
540 if (!actOnCoroutineBodyStart(*this, S, Loc, "co_return")) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000541 CorrectDelayedTyposInExpr(E);
542 return StmtError();
543 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000544 return BuildCoreturnStmt(Loc, E);
545}
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000546
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000547StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
548 bool IsImplicit) {
549 auto *FSI = checkCoroutineContext(*this, Loc, "co_return");
550 if (!FSI)
Richard Smith71d403e2015-11-22 07:33:28 +0000551 return StmtError();
552
553 if (E && E->getType()->isPlaceholderType() &&
554 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
Richard Smith10610f72015-11-20 22:57:24 +0000555 ExprResult R = CheckPlaceholderExpr(E);
556 if (R.isInvalid()) return StmtError();
557 E = R.get();
558 }
559
Richard Smith4ba66602015-11-22 07:05:16 +0000560 // FIXME: If the operand is a reference to a variable that's about to go out
Richard Smith2af65c42015-11-24 02:34:39 +0000561 // of scope, we should treat the operand as an xvalue for this overload
Richard Smith4ba66602015-11-22 07:05:16 +0000562 // resolution.
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000563 VarDecl *Promise = FSI->CoroutinePromise;
Richard Smith4ba66602015-11-22 07:05:16 +0000564 ExprResult PC;
Eric Fiselier98131312016-10-06 21:23:38 +0000565 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000566 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
Richard Smith4ba66602015-11-22 07:05:16 +0000567 } else {
568 E = MakeFullDiscardedValueExpr(E).get();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000569 PC = buildPromiseCall(*this, Promise, Loc, "return_void", None);
Richard Smith4ba66602015-11-22 07:05:16 +0000570 }
571 if (PC.isInvalid())
572 return StmtError();
573
574 Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
575
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000576 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
577 if (!IsImplicit)
578 FSI->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000579 return Res;
580}
581
Eric Fiselier709d1b32016-10-27 07:30:31 +0000582static ExprResult buildStdCurrentExceptionCall(Sema &S, SourceLocation Loc) {
583 NamespaceDecl *Std = S.getStdNamespace();
584 if (!Std) {
585 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
586 return ExprError();
587 }
588 LookupResult Result(S, &S.PP.getIdentifierTable().get("current_exception"),
589 Loc, Sema::LookupOrdinaryName);
590 if (!S.LookupQualifiedName(Result, Std)) {
591 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
592 return ExprError();
593 }
594
595 // FIXME The STL is free to provide more than one overload.
596 FunctionDecl *FD = Result.getAsSingle<FunctionDecl>();
597 if (!FD) {
598 S.Diag(Loc, diag::err_malformed_std_current_exception);
599 return ExprError();
600 }
601 ExprResult Res = S.BuildDeclRefExpr(FD, FD->getType(), VK_LValue, Loc);
602 Res = S.ActOnCallExpr(/*Scope*/ nullptr, Res.get(), Loc, None, Loc);
603 if (Res.isInvalid()) {
604 S.Diag(Loc, diag::err_malformed_std_current_exception);
605 return ExprError();
606 }
607 return Res;
608}
609
Gor Nishanov8df64e92016-10-27 16:28:31 +0000610// Find an appropriate delete for the promise.
611static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
612 QualType PromiseType) {
613 FunctionDecl *OperatorDelete = nullptr;
614
615 DeclarationName DeleteName =
616 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
617
618 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
619 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
620
621 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
622 return nullptr;
623
624 if (!OperatorDelete) {
625 // Look for a global declaration.
626 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
627 const bool Overaligned = false;
628 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
629 Overaligned, DeleteName);
630 }
631 S.MarkFunctionReferenced(Loc, OperatorDelete);
632 return OperatorDelete;
633}
634
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000635namespace {
636class SubStmtBuilder : public CoroutineBodyStmt::CtorArgs {
637 Sema &S;
638 FunctionDecl &FD;
639 FunctionScopeInfo &Fn;
640 bool IsValid;
641 SourceLocation Loc;
642 QualType RetType;
643 SmallVector<Stmt *, 4> ParamMovesVector;
644 const bool IsPromiseDependentType;
645 CXXRecordDecl *PromiseRecordDecl = nullptr;
646
647public:
648 SubStmtBuilder(Sema &S, FunctionDecl &FD, FunctionScopeInfo &Fn, Stmt *Body)
649 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
650 IsPromiseDependentType(
651 !Fn.CoroutinePromise ||
652 Fn.CoroutinePromise->getType()->isDependentType()) {
653 this->Body = Body;
654 if (!IsPromiseDependentType) {
655 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
656 assert(PromiseRecordDecl && "Type should have already been checked");
657 }
658 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend() &&
659 makeOnException() && makeOnFallthrough() &&
660 makeNewAndDeleteExpr() && makeReturnObject() &&
661 makeParamMoves();
662 }
663
664 bool isInvalid() const { return !this->IsValid; }
665
666 bool makePromiseStmt();
667 bool makeInitialAndFinalSuspend();
668 bool makeNewAndDeleteExpr();
669 bool makeOnFallthrough();
670 bool makeOnException();
671 bool makeReturnObject();
672 bool makeParamMoves();
673};
674}
675
676void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
677 FunctionScopeInfo *Fn = getCurFunction();
678 assert(Fn && Fn->CoroutinePromise && "not a coroutine");
679
680 // Coroutines [stmt.return]p1:
681 // A return statement shall not appear in a coroutine.
682 if (Fn->FirstReturnLoc.isValid()) {
683 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
684 auto *First = Fn->CoroutineStmts[0];
685 Diag(First->getLocStart(), diag::note_declared_coroutine_here)
686 << (isa<CoawaitExpr>(First) ? "co_await" :
687 isa<CoyieldExpr>(First) ? "co_yield" : "co_return");
688 }
689 SubStmtBuilder Builder(*this, *FD, *Fn, Body);
690 if (Builder.isInvalid())
691 return FD->setInvalidDecl();
692
693 // Build body for the coroutine wrapper statement.
694 Body = CoroutineBodyStmt::Create(Context, Builder);
695}
696
697bool SubStmtBuilder::makePromiseStmt() {
698 // Form a declaration statement for the promise declaration, so that AST
699 // visitors can more easily find it.
700 StmtResult PromiseStmt =
701 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc);
702 if (PromiseStmt.isInvalid())
703 return false;
704
705 this->Promise = PromiseStmt.get();
706 return true;
707}
708
709bool SubStmtBuilder::makeInitialAndFinalSuspend() {
710 if (Fn.hasInvalidCoroutineSuspends())
711 return false;
712 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first);
713 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
714 return true;
715}
716
717bool SubStmtBuilder::makeNewAndDeleteExpr() {
718 // Form and check allocation and deallocation calls.
719 QualType PromiseType = Fn.CoroutinePromise->getType();
Gor Nishanov8df64e92016-10-27 16:28:31 +0000720 if (PromiseType->isDependentType())
721 return true;
722
723 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
724 return false;
725
726 // FIXME: Add support for get_return_object_on_allocation failure.
727 // FIXME: Add support for stateful allocators.
728
729 FunctionDecl *OperatorNew = nullptr;
730 FunctionDecl *OperatorDelete = nullptr;
731 FunctionDecl *UnusedResult = nullptr;
732 bool PassAlignment = false;
733
734 S.FindAllocationFunctions(Loc, SourceRange(),
735 /*UseGlobal*/ false, PromiseType,
736 /*isArray*/ false, PassAlignment,
737 /*PlacementArgs*/ None, OperatorNew, UnusedResult);
738
739 OperatorDelete = findDeleteForPromise(S, Loc, PromiseType);
740
741 if (!OperatorDelete || !OperatorNew)
742 return false;
743
744 Expr *FramePtr =
745 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
746
747 Expr *FrameSize =
748 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
749
750 // Make new call.
751
752 ExprResult NewRef =
753 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
754 if (NewRef.isInvalid())
755 return false;
756
757 ExprResult NewExpr =
758 S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc);
759 if (NewExpr.isInvalid())
760 return false;
761
Gor Nishanov8df64e92016-10-27 16:28:31 +0000762 // Make delete call.
763
764 QualType OpDeleteQualType = OperatorDelete->getType();
765
766 ExprResult DeleteRef =
767 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
768 if (DeleteRef.isInvalid())
769 return false;
770
771 Expr *CoroFree =
772 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
773
774 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
775
776 // Check if we need to pass the size.
777 const auto *OpDeleteType =
778 OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>();
779 if (OpDeleteType->getNumParams() > 1)
780 DeleteArgs.push_back(FrameSize);
781
782 ExprResult DeleteExpr =
783 S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
784 if (DeleteExpr.isInvalid())
785 return false;
786
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000787 this->Allocate = NewExpr.get();
788 this->Deallocate = DeleteExpr.get();
Gor Nishanov8df64e92016-10-27 16:28:31 +0000789
790 return true;
791}
792
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000793bool SubStmtBuilder::makeOnFallthrough() {
794 if (!PromiseRecordDecl)
795 return true;
796
797 // [dcl.fct.def.coroutine]/4
798 // The unqualified-ids 'return_void' and 'return_value' are looked up in
799 // the scope of class P. If both are found, the program is ill-formed.
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000800 const bool HasRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc);
801 const bool HasRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc);
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000802
Eric Fiselier709d1b32016-10-27 07:30:31 +0000803 StmtResult Fallthrough;
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000804 if (HasRVoid && HasRValue) {
805 // FIXME Improve this diagnostic
806 S.Diag(FD.getLocation(), diag::err_coroutine_promise_return_ill_formed)
807 << PromiseRecordDecl;
808 return false;
809 } else if (HasRVoid) {
810 // If the unqualified-id return_void is found, flowing off the end of a
811 // coroutine is equivalent to a co_return with no operand. Otherwise,
812 // flowing off the end of a coroutine results in undefined behavior.
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000813 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
814 /*IsImplicit*/false);
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000815 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
816 if (Fallthrough.isInvalid())
817 return false;
Eric Fiselier709d1b32016-10-27 07:30:31 +0000818 }
Richard Smith2af65c42015-11-24 02:34:39 +0000819
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000820 this->OnFallthrough = Fallthrough.get();
821 return true;
822}
823
824bool SubStmtBuilder::makeOnException() {
825 // Try to form 'p.set_exception(std::current_exception());' to handle
826 // uncaught exceptions.
827 // TODO: Post WG21 Issaquah 2016 renamed set_exception to unhandled_exception
828 // TODO: and dropped exception_ptr parameter. Make it so.
829
830 if (!PromiseRecordDecl)
831 return true;
832
833 // If exceptions are disabled, don't try to build OnException.
834 if (!S.getLangOpts().CXXExceptions)
835 return true;
836
837 ExprResult SetException;
838
839 // [dcl.fct.def.coroutine]/3
840 // The unqualified-id set_exception is found in the scope of P by class
841 // member access lookup (3.4.5).
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000842 if (lookupMember(S, "set_exception", PromiseRecordDecl, Loc)) {
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000843 // Form the call 'p.set_exception(std::current_exception())'
844 SetException = buildStdCurrentExceptionCall(S, Loc);
845 if (SetException.isInvalid())
846 return false;
847 Expr *E = SetException.get();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000848 SetException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, "set_exception", E);
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000849 SetException = S.ActOnFinishFullExpr(SetException.get(), Loc);
850 if (SetException.isInvalid())
851 return false;
852 }
853
854 this->OnException = SetException.get();
855 return true;
856}
857
858bool SubStmtBuilder::makeReturnObject() {
859
Richard Smith2af65c42015-11-24 02:34:39 +0000860 // Build implicit 'p.get_return_object()' expression and form initialization
861 // of return type from it.
862 ExprResult ReturnObject =
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000863 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
Richard Smith2af65c42015-11-24 02:34:39 +0000864 if (ReturnObject.isInvalid())
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000865 return false;
866 QualType RetType = FD.getReturnType();
Richard Smith2af65c42015-11-24 02:34:39 +0000867 if (!RetType->isDependentType()) {
868 InitializedEntity Entity =
869 InitializedEntity::InitializeResult(Loc, RetType, false);
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000870 ReturnObject = S.PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
Richard Smith2af65c42015-11-24 02:34:39 +0000871 ReturnObject.get());
872 if (ReturnObject.isInvalid())
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000873 return false;
Richard Smith2af65c42015-11-24 02:34:39 +0000874 }
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000875 ReturnObject = S.ActOnFinishFullExpr(ReturnObject.get(), Loc);
Richard Smith2af65c42015-11-24 02:34:39 +0000876 if (ReturnObject.isInvalid())
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000877 return false;
Richard Smith2af65c42015-11-24 02:34:39 +0000878
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000879 this->ReturnValue = ReturnObject.get();
880 return true;
881}
882
883bool SubStmtBuilder::makeParamMoves() {
Richard Smith2af65c42015-11-24 02:34:39 +0000884 // FIXME: Perform move-initialization of parameters into frame-local copies.
Gor Nishanovbbe1c072017-02-13 05:05:02 +0000885 return true;
Richard Smithcfd53b42015-10-22 06:13:50 +0000886}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000887
888StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
889 CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args);
890 if (!Res)
891 return StmtError();
892 return Res;
893}