blob: 5231e23c1c1c64f65b985350390911c138d6c18f [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
Eric Fiselier709d1b32016-10-27 07:30:31 +0000381static ExprResult buildStdCurrentExceptionCall(Sema &S, SourceLocation Loc) {
382 NamespaceDecl *Std = S.getStdNamespace();
383 if (!Std) {
384 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
385 return ExprError();
386 }
387 LookupResult Result(S, &S.PP.getIdentifierTable().get("current_exception"),
388 Loc, Sema::LookupOrdinaryName);
389 if (!S.LookupQualifiedName(Result, Std)) {
390 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
391 return ExprError();
392 }
393
394 // FIXME The STL is free to provide more than one overload.
395 FunctionDecl *FD = Result.getAsSingle<FunctionDecl>();
396 if (!FD) {
397 S.Diag(Loc, diag::err_malformed_std_current_exception);
398 return ExprError();
399 }
400 ExprResult Res = S.BuildDeclRefExpr(FD, FD->getType(), VK_LValue, Loc);
401 Res = S.ActOnCallExpr(/*Scope*/ nullptr, Res.get(), Loc, None, Loc);
402 if (Res.isInvalid()) {
403 S.Diag(Loc, diag::err_malformed_std_current_exception);
404 return ExprError();
405 }
406 return Res;
407}
408
Richard Smith2af65c42015-11-24 02:34:39 +0000409void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000410 FunctionScopeInfo *Fn = getCurFunction();
411 assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
412
413 // Coroutines [stmt.return]p1:
414 // A return statement shall not appear in a coroutine.
Richard Smith9f690bd2015-10-27 06:02:45 +0000415 if (Fn->FirstReturnLoc.isValid()) {
416 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
Richard Smithcfd53b42015-10-22 06:13:50 +0000417 auto *First = Fn->CoroutineStmts[0];
418 Diag(First->getLocStart(), diag::note_declared_coroutine_here)
Richard Smith9f690bd2015-10-27 06:02:45 +0000419 << (isa<CoawaitExpr>(First) ? 0 :
420 isa<CoyieldExpr>(First) ? 1 : 2);
Richard Smithcfd53b42015-10-22 06:13:50 +0000421 }
422
423 bool AnyCoawaits = false;
424 bool AnyCoyields = false;
425 for (auto *CoroutineStmt : Fn->CoroutineStmts) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000426 AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
427 AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
Richard Smithcfd53b42015-10-22 06:13:50 +0000428 }
429
430 if (!AnyCoawaits && !AnyCoyields)
431 Diag(Fn->CoroutineStmts.front()->getLocStart(),
Richard Smith9f690bd2015-10-27 06:02:45 +0000432 diag::ext_coroutine_without_co_await_co_yield);
Richard Smithcfd53b42015-10-22 06:13:50 +0000433
Richard Smith2af65c42015-11-24 02:34:39 +0000434 SourceLocation Loc = FD->getLocation();
435
436 // Form a declaration statement for the promise declaration, so that AST
437 // visitors can more easily find it.
438 StmtResult PromiseStmt =
439 ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
440 if (PromiseStmt.isInvalid())
441 return FD->setInvalidDecl();
442
443 // Form and check implicit 'co_await p.initial_suspend();' statement.
444 ExprResult InitialSuspend =
445 buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
446 // FIXME: Support operator co_await here.
447 if (!InitialSuspend.isInvalid())
448 InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
449 InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
450 if (InitialSuspend.isInvalid())
451 return FD->setInvalidDecl();
452
453 // Form and check implicit 'co_await p.final_suspend();' statement.
454 ExprResult FinalSuspend =
455 buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
456 // FIXME: Support operator co_await here.
457 if (!FinalSuspend.isInvalid())
458 FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
459 FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
460 if (FinalSuspend.isInvalid())
461 return FD->setInvalidDecl();
462
Eric Fiselier709d1b32016-10-27 07:30:31 +0000463 // Try to form 'p.return_void();' expression statement to handle
Richard Smith2af65c42015-11-24 02:34:39 +0000464 // control flowing off the end of the coroutine.
Eric Fiselier709d1b32016-10-27 07:30:31 +0000465 // Also try to form 'p.set_exception(std::current_exception());' to handle
466 // uncaught exceptions.
467 ExprResult SetException;
468 StmtResult Fallthrough;
469 if (Fn->CoroutinePromise &&
470 !Fn->CoroutinePromise->getType()->isDependentType()) {
471 CXXRecordDecl *RD = Fn->CoroutinePromise->getType()->getAsCXXRecordDecl();
472 assert(RD && "Type should have already been checked");
473 // [dcl.fct.def.coroutine]/4
474 // The unqualified-ids 'return_void' and 'return_value' are looked up in
475 // the scope of class P. If both are found, the program is ill-formed.
476 DeclarationName RVoidDN = PP.getIdentifierInfo("return_void");
477 LookupResult RVoidResult(*this, RVoidDN, Loc, Sema::LookupMemberName);
478 const bool HasRVoid = LookupQualifiedName(RVoidResult, RD);
479
480 DeclarationName RValueDN = PP.getIdentifierInfo("return_value");
481 LookupResult RValueResult(*this, RValueDN, Loc, Sema::LookupMemberName);
482 const bool HasRValue = LookupQualifiedName(RValueResult, RD);
483
484 if (HasRVoid && HasRValue) {
485 // FIXME Improve this diagnostic
486 Diag(FD->getLocation(), diag::err_coroutine_promise_return_ill_formed)
487 << RD;
488 return FD->setInvalidDecl();
489 } else if (HasRVoid) {
490 // If the unqualified-id return_void is found, flowing off the end of a
491 // coroutine is equivalent to a co_return with no operand. Otherwise,
492 // flowing off the end of a coroutine results in undefined behavior.
493 Fallthrough = BuildCoreturnStmt(FD->getLocation(), nullptr);
494 Fallthrough = ActOnFinishFullStmt(Fallthrough.get());
495 if (Fallthrough.isInvalid())
496 return FD->setInvalidDecl();
497 }
498
499 // [dcl.fct.def.coroutine]/3
500 // The unqualified-id set_exception is found in the scope of P by class
501 // member access lookup (3.4.5).
502 DeclarationName SetExDN = PP.getIdentifierInfo("set_exception");
503 LookupResult SetExResult(*this, SetExDN, Loc, Sema::LookupMemberName);
504 if (LookupQualifiedName(SetExResult, RD)) {
505 // Form the call 'p.set_exception(std::current_exception())'
506 SetException = buildStdCurrentExceptionCall(*this, Loc);
507 if (SetException.isInvalid())
508 return FD->setInvalidDecl();
509 Expr *E = SetException.get();
510 SetException = buildPromiseCall(*this, Fn, Loc, "set_exception", E);
511 SetException = ActOnFinishFullExpr(SetException.get(), Loc);
512 if (SetException.isInvalid())
513 return FD->setInvalidDecl();
514 }
515 }
Richard Smith2af65c42015-11-24 02:34:39 +0000516
517 // Build implicit 'p.get_return_object()' expression and form initialization
518 // of return type from it.
519 ExprResult ReturnObject =
520 buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
521 if (ReturnObject.isInvalid())
522 return FD->setInvalidDecl();
523 QualType RetType = FD->getReturnType();
524 if (!RetType->isDependentType()) {
525 InitializedEntity Entity =
526 InitializedEntity::InitializeResult(Loc, RetType, false);
527 ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
528 ReturnObject.get());
529 if (ReturnObject.isInvalid())
530 return FD->setInvalidDecl();
531 }
532 ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
533 if (ReturnObject.isInvalid())
534 return FD->setInvalidDecl();
535
536 // FIXME: Perform move-initialization of parameters into frame-local copies.
537 SmallVector<Expr*, 16> ParamMoves;
538
539 // Build body for the coroutine wrapper statement.
540 Body = new (Context) CoroutineBodyStmt(
541 Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
Eric Fiselier709d1b32016-10-27 07:30:31 +0000542 SetException.get(), Fallthrough.get(), ReturnObject.get(), ParamMoves);
Richard Smithcfd53b42015-10-22 06:13:50 +0000543}