blob: 323878e2d57db02557a79b4194dc6e6c2b288a57 [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
Richard Smith9f690bd2015-10-27 06:02:45 +000024/// Look up the std::coroutine_traits<...>::promise_type for the given
25/// function type.
26static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
27 SourceLocation Loc) {
28 // FIXME: Cache std::coroutine_traits once we've found it.
Gor Nishanov3e048bb2016-10-04 00:31:16 +000029 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
30 if (!StdExp) {
Richard Smith9f690bd2015-10-27 06:02:45 +000031 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
32 return QualType();
33 }
34
35 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
36 Loc, Sema::LookupOrdinaryName);
Gor Nishanov3e048bb2016-10-04 00:31:16 +000037 if (!S.LookupQualifiedName(Result, StdExp)) {
Richard Smith9f690bd2015-10-27 06:02:45 +000038 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
39 return QualType();
40 }
41
42 ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
43 if (!CoroTraits) {
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);
48 return QualType();
49 }
50
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)));
Richard Smith71d403e2015-11-22 07:33:28 +000056 // FIXME: If the function is a non-static member function, add the type
57 // of the implicit object parameter before the formal parameters.
Richard Smith9f690bd2015-10-27 06:02:45 +000058 for (QualType T : FnType->getParamTypes())
59 Args.addArgument(TemplateArgumentLoc(
60 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc)));
61
62 // Build the template-id.
63 QualType CoroTrait =
64 S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args);
65 if (CoroTrait.isNull())
66 return QualType();
67 if (S.RequireCompleteType(Loc, CoroTrait,
68 diag::err_coroutine_traits_missing_specialization))
69 return QualType();
70
71 CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl();
72 assert(RD && "specialization of class template is not a class?");
73
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>();
79 if (!Promise) {
80 S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
81 << RD;
82 return QualType();
83 }
84
85 // The promise type is required to be a class type.
86 QualType PromiseType = S.Context.getTypeDeclType(Promise);
87 if (!PromiseType->getAsCXXRecordDecl()) {
Richard Smith9b2f53e2015-11-19 02:36:35 +000088 // Use the fully-qualified name of the type.
Gor Nishanov3e048bb2016-10-04 00:31:16 +000089 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp);
Richard Smith9b2f53e2015-11-19 02:36:35 +000090 NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
91 CoroTrait.getTypePtr());
92 PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
93
Richard Smith9f690bd2015-10-27 06:02:45 +000094 S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
95 << PromiseType;
96 return QualType();
97 }
98
99 return PromiseType;
100}
101
102/// Check that this is a context in which a coroutine suspension can appear.
Richard Smithcfd53b42015-10-22 06:13:50 +0000103static FunctionScopeInfo *
104checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
Richard Smith744b2242015-11-20 02:54:01 +0000105 // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
106 if (S.isUnevaluatedContext()) {
107 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
Richard Smithcfd53b42015-10-22 06:13:50 +0000108 return nullptr;
Richard Smith744b2242015-11-20 02:54:01 +0000109 }
Richard Smithcfd53b42015-10-22 06:13:50 +0000110
111 // Any other usage must be within a function.
Richard Smith2af65c42015-11-24 02:34:39 +0000112 // FIXME: Reject a coroutine with a deduced return type.
Richard Smithcfd53b42015-10-22 06:13:50 +0000113 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
114 if (!FD) {
115 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
116 ? diag::err_coroutine_objc_method
117 : diag::err_coroutine_outside_function) << Keyword;
118 } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
119 // Coroutines TS [special]/6:
120 // A special member function shall not be a coroutine.
121 //
122 // FIXME: We assume that this really means that a coroutine cannot
123 // be a constructor or destructor.
124 S.Diag(Loc, diag::err_coroutine_ctor_dtor)
125 << isa<CXXDestructorDecl>(FD) << Keyword;
126 } else if (FD->isConstexpr()) {
127 S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
128 } else if (FD->isVariadic()) {
129 S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000130 } else if (FD->isMain()) {
131 S.Diag(FD->getLocStart(), diag::err_coroutine_main);
132 S.Diag(Loc, diag::note_declared_coroutine_here)
133 << (Keyword == "co_await" ? 0 :
134 Keyword == "co_yield" ? 1 : 2);
Richard Smithcfd53b42015-10-22 06:13:50 +0000135 } else {
136 auto *ScopeInfo = S.getCurFunction();
137 assert(ScopeInfo && "missing function scope for function");
Richard Smith9f690bd2015-10-27 06:02:45 +0000138
139 // If we don't have a promise variable, build one now.
Richard Smith23da82c2015-11-20 22:40:06 +0000140 if (!ScopeInfo->CoroutinePromise) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000141 QualType T =
Richard Smith23da82c2015-11-20 22:40:06 +0000142 FD->getType()->isDependentType()
143 ? S.Context.DependentTy
144 : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(),
145 Loc);
Richard Smith9f690bd2015-10-27 06:02:45 +0000146 if (T.isNull())
147 return nullptr;
148
149 // Create and default-initialize the promise.
150 ScopeInfo->CoroutinePromise =
151 VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
152 &S.PP.getIdentifierTable().get("__promise"), T,
153 S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
154 S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
155 if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
156 S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
157 }
158
Richard Smithcfd53b42015-10-22 06:13:50 +0000159 return ScopeInfo;
160 }
161
162 return nullptr;
163}
164
Richard Smith9f690bd2015-10-27 06:02:45 +0000165/// Build a call to 'operator co_await' if there is a suitable operator for
166/// the given expression.
167static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
168 SourceLocation Loc, Expr *E) {
169 UnresolvedSet<16> Functions;
170 SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
171 Functions);
172 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
173}
Richard Smithcfd53b42015-10-22 06:13:50 +0000174
Richard Smith9f690bd2015-10-27 06:02:45 +0000175struct ReadySuspendResumeResult {
176 bool IsInvalid;
177 Expr *Results[3];
178};
179
Richard Smith23da82c2015-11-20 22:40:06 +0000180static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
181 StringRef Name,
182 MutableArrayRef<Expr *> Args) {
183 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
184
185 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
186 CXXScopeSpec SS;
187 ExprResult Result = S.BuildMemberReferenceExpr(
188 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
189 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
190 /*Scope=*/nullptr);
191 if (Result.isInvalid())
192 return ExprError();
193
194 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
195}
196
Richard Smith9f690bd2015-10-27 06:02:45 +0000197/// Build calls to await_ready, await_suspend, and await_resume for a co_await
198/// expression.
199static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
200 Expr *E) {
201 // Assume invalid until we see otherwise.
202 ReadySuspendResumeResult Calls = {true, {}};
203
204 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
205 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000206 Expr *Operand = new (S.Context) OpaqueValueExpr(
Richard Smith1f38edd2015-11-22 03:13:02 +0000207 Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000208
Richard Smith9f690bd2015-10-27 06:02:45 +0000209 // FIXME: Pass coroutine handle to await_suspend.
Richard Smith23da82c2015-11-20 22:40:06 +0000210 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
Richard Smith9f690bd2015-10-27 06:02:45 +0000211 if (Result.isInvalid())
212 return Calls;
213 Calls.Results[I] = Result.get();
214 }
215
216 Calls.IsInvalid = false;
217 return Calls;
218}
219
220ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000221 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
222 if (!Coroutine) {
223 CorrectDelayedTyposInExpr(E);
224 return ExprError();
225 }
Richard Smith10610f72015-11-20 22:57:24 +0000226 if (E->getType()->isPlaceholderType()) {
227 ExprResult R = CheckPlaceholderExpr(E);
228 if (R.isInvalid()) return ExprError();
229 E = R.get();
230 }
231
Richard Smith9f690bd2015-10-27 06:02:45 +0000232 ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
233 if (Awaitable.isInvalid())
234 return ExprError();
Eric Fiseliera5465282016-09-29 21:47:39 +0000235
Richard Smith9f690bd2015-10-27 06:02:45 +0000236 return BuildCoawaitExpr(Loc, Awaitable.get());
237}
238ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
239 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
Richard Smith744b2242015-11-20 02:54:01 +0000240 if (!Coroutine)
241 return ExprError();
Richard Smith9f690bd2015-10-27 06:02:45 +0000242
Richard Smith9f690bd2015-10-27 06:02:45 +0000243 if (E->getType()->isPlaceholderType()) {
244 ExprResult R = CheckPlaceholderExpr(E);
245 if (R.isInvalid()) return ExprError();
246 E = R.get();
247 }
248
Richard Smith10610f72015-11-20 22:57:24 +0000249 if (E->getType()->isDependentType()) {
250 Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
251 Coroutine->CoroutineStmts.push_back(Res);
252 return Res;
253 }
254
Richard Smith1f38edd2015-11-22 03:13:02 +0000255 // If the expression is a temporary, materialize it as an lvalue so that we
256 // can use it multiple times.
257 if (E->getValueKind() == VK_RValue)
Tim Shen4a05bb82016-06-21 20:29:17 +0000258 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
Richard Smith9f690bd2015-10-27 06:02:45 +0000259
260 // Build the await_ready, await_suspend, await_resume calls.
261 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
262 if (RSS.IsInvalid)
263 return ExprError();
264
265 Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
266 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000267 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000268 return Res;
269}
270
Richard Smith4ba66602015-11-22 07:05:16 +0000271static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
272 SourceLocation Loc, StringRef Name,
273 MutableArrayRef<Expr *> Args) {
Richard Smith23da82c2015-11-20 22:40:06 +0000274 assert(Coroutine->CoroutinePromise && "no promise for coroutine");
275
276 // Form a reference to the promise.
277 auto *Promise = Coroutine->CoroutinePromise;
278 ExprResult PromiseRef = S.BuildDeclRefExpr(
279 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
280 if (PromiseRef.isInvalid())
281 return ExprError();
282
283 // Call 'yield_value', passing in E.
Richard Smith4ba66602015-11-22 07:05:16 +0000284 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
Richard Smith23da82c2015-11-20 22:40:06 +0000285}
286
Richard Smith9f690bd2015-10-27 06:02:45 +0000287ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
Richard Smith23da82c2015-11-20 22:40:06 +0000288 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
Eric Fiseliera5465282016-09-29 21:47:39 +0000289 if (!Coroutine) {
290 CorrectDelayedTyposInExpr(E);
Richard Smith23da82c2015-11-20 22:40:06 +0000291 return ExprError();
Eric Fiseliera5465282016-09-29 21:47:39 +0000292 }
Richard Smith23da82c2015-11-20 22:40:06 +0000293
294 // Build yield_value call.
Richard Smith4ba66602015-11-22 07:05:16 +0000295 ExprResult Awaitable =
296 buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000297 if (Awaitable.isInvalid())
298 return ExprError();
Richard Smith23da82c2015-11-20 22:40:06 +0000299
300 // Build 'operator co_await' call.
301 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
302 if (Awaitable.isInvalid())
303 return ExprError();
304
Richard Smith9f690bd2015-10-27 06:02:45 +0000305 return BuildCoyieldExpr(Loc, Awaitable.get());
306}
307ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
308 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
Richard Smith744b2242015-11-20 02:54:01 +0000309 if (!Coroutine)
310 return ExprError();
Richard Smithcfd53b42015-10-22 06:13:50 +0000311
Richard Smith10610f72015-11-20 22:57:24 +0000312 if (E->getType()->isPlaceholderType()) {
313 ExprResult R = CheckPlaceholderExpr(E);
314 if (R.isInvalid()) return ExprError();
315 E = R.get();
316 }
317
Richard Smithd7bed4d2015-11-22 02:57:17 +0000318 if (E->getType()->isDependentType()) {
319 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
320 Coroutine->CoroutineStmts.push_back(Res);
321 return Res;
322 }
323
Richard Smith1f38edd2015-11-22 03:13:02 +0000324 // If the expression is a temporary, materialize it as an lvalue so that we
325 // can use it multiple times.
326 if (E->getValueKind() == VK_RValue)
Tim Shen4a05bb82016-06-21 20:29:17 +0000327 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
Richard Smithd7bed4d2015-11-22 02:57:17 +0000328
329 // Build the await_ready, await_suspend, await_resume calls.
330 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
331 if (RSS.IsInvalid)
332 return ExprError();
333
334 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
335 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000336 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000337 return Res;
338}
339
340StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000341 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
342 if (!Coroutine) {
343 CorrectDelayedTyposInExpr(E);
344 return StmtError();
345 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000346 return BuildCoreturnStmt(Loc, E);
347}
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000348
Richard Smith9f690bd2015-10-27 06:02:45 +0000349StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
Richard Smith71d403e2015-11-22 07:33:28 +0000350 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
351 if (!Coroutine)
352 return StmtError();
353
354 if (E && E->getType()->isPlaceholderType() &&
355 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
Richard Smith10610f72015-11-20 22:57:24 +0000356 ExprResult R = CheckPlaceholderExpr(E);
357 if (R.isInvalid()) return StmtError();
358 E = R.get();
359 }
360
Richard Smith4ba66602015-11-22 07:05:16 +0000361 // FIXME: If the operand is a reference to a variable that's about to go out
Richard Smith2af65c42015-11-24 02:34:39 +0000362 // of scope, we should treat the operand as an xvalue for this overload
Richard Smith4ba66602015-11-22 07:05:16 +0000363 // resolution.
364 ExprResult PC;
Eric Fiselier98131312016-10-06 21:23:38 +0000365 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
Richard Smith4ba66602015-11-22 07:05:16 +0000366 PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
367 } else {
368 E = MakeFullDiscardedValueExpr(E).get();
369 PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
370 }
371 if (PC.isInvalid())
372 return StmtError();
373
374 Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
375
376 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
Richard Smith744b2242015-11-20 02:54:01 +0000377 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000378 return Res;
379}
380
Richard Smith2af65c42015-11-24 02:34:39 +0000381void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000382 FunctionScopeInfo *Fn = getCurFunction();
383 assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
384
385 // Coroutines [stmt.return]p1:
386 // A return statement shall not appear in a coroutine.
Richard Smith9f690bd2015-10-27 06:02:45 +0000387 if (Fn->FirstReturnLoc.isValid()) {
388 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
Richard Smithcfd53b42015-10-22 06:13:50 +0000389 auto *First = Fn->CoroutineStmts[0];
390 Diag(First->getLocStart(), diag::note_declared_coroutine_here)
Richard Smith9f690bd2015-10-27 06:02:45 +0000391 << (isa<CoawaitExpr>(First) ? 0 :
392 isa<CoyieldExpr>(First) ? 1 : 2);
Richard Smithcfd53b42015-10-22 06:13:50 +0000393 }
394
395 bool AnyCoawaits = false;
396 bool AnyCoyields = false;
397 for (auto *CoroutineStmt : Fn->CoroutineStmts) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000398 AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
399 AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
Richard Smithcfd53b42015-10-22 06:13:50 +0000400 }
401
402 if (!AnyCoawaits && !AnyCoyields)
403 Diag(Fn->CoroutineStmts.front()->getLocStart(),
Richard Smith9f690bd2015-10-27 06:02:45 +0000404 diag::ext_coroutine_without_co_await_co_yield);
Richard Smithcfd53b42015-10-22 06:13:50 +0000405
Richard Smith2af65c42015-11-24 02:34:39 +0000406 SourceLocation Loc = FD->getLocation();
407
408 // Form a declaration statement for the promise declaration, so that AST
409 // visitors can more easily find it.
410 StmtResult PromiseStmt =
411 ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
412 if (PromiseStmt.isInvalid())
413 return FD->setInvalidDecl();
414
415 // Form and check implicit 'co_await p.initial_suspend();' statement.
416 ExprResult InitialSuspend =
417 buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
418 // FIXME: Support operator co_await here.
419 if (!InitialSuspend.isInvalid())
420 InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
421 InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
422 if (InitialSuspend.isInvalid())
423 return FD->setInvalidDecl();
424
425 // Form and check implicit 'co_await p.final_suspend();' statement.
426 ExprResult FinalSuspend =
427 buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
428 // FIXME: Support operator co_await here.
429 if (!FinalSuspend.isInvalid())
430 FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
431 FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
432 if (FinalSuspend.isInvalid())
433 return FD->setInvalidDecl();
434
435 // FIXME: Perform analysis of set_exception call.
436
437 // FIXME: Try to form 'p.return_void();' expression statement to handle
438 // control flowing off the end of the coroutine.
439
440 // Build implicit 'p.get_return_object()' expression and form initialization
441 // of return type from it.
442 ExprResult ReturnObject =
443 buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
444 if (ReturnObject.isInvalid())
445 return FD->setInvalidDecl();
446 QualType RetType = FD->getReturnType();
447 if (!RetType->isDependentType()) {
448 InitializedEntity Entity =
449 InitializedEntity::InitializeResult(Loc, RetType, false);
450 ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
451 ReturnObject.get());
452 if (ReturnObject.isInvalid())
453 return FD->setInvalidDecl();
454 }
455 ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
456 if (ReturnObject.isInvalid())
457 return FD->setInvalidDecl();
458
459 // FIXME: Perform move-initialization of parameters into frame-local copies.
460 SmallVector<Expr*, 16> ParamMoves;
461
462 // Build body for the coroutine wrapper statement.
463 Body = new (Context) CoroutineBodyStmt(
464 Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
465 /*SetException*/nullptr, /*Fallthrough*/nullptr,
466 ReturnObject.get(), ParamMoves);
Richard Smithcfd53b42015-10-22 06:13:50 +0000467}