blob: 873a830d9757c13257c87c14d7223f3067c4e490 [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)
Gor Nishanov8df64e92016-10-27 16:28:31 +000081 << RD;
Richard Smith9f690bd2015-10-27 06:02:45 +000082 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)
Gor Nishanov8df64e92016-10-27 16:28:31 +000095 << PromiseType;
Richard Smith9f690bd2015-10-27 06:02:45 +000096 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.
Gor Nishanov8df64e92016-10-27 16:28:31 +0000124 S.Diag(Loc, diag::err_coroutine_ctor_dtor)
Richard Smithcfd53b42015-10-22 06:13:50 +0000125 << 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)
Gor Nishanov8df64e92016-10-27 16:28:31 +0000133 << (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
Gor Nishanov8df64e92016-10-27 16:28:31 +0000165static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
166 MutableArrayRef<Expr *> CallArgs) {
167 StringRef Name = S.Context.BuiltinInfo.getName(Id);
168 LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
169 S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
170
171 auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
172 assert(BuiltInDecl && "failed to find builtin declaration");
173
174 ExprResult DeclRef =
175 S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
176 assert(DeclRef.isUsable() && "Builtin reference cannot fail");
177
178 ExprResult Call =
179 S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
180
181 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
182 return Call.get();
183}
184
Richard Smith9f690bd2015-10-27 06:02:45 +0000185/// Build a call to 'operator co_await' if there is a suitable operator for
186/// the given expression.
187static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
188 SourceLocation Loc, Expr *E) {
189 UnresolvedSet<16> Functions;
190 SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
191 Functions);
192 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
193}
Richard Smithcfd53b42015-10-22 06:13:50 +0000194
Richard Smith9f690bd2015-10-27 06:02:45 +0000195struct ReadySuspendResumeResult {
196 bool IsInvalid;
197 Expr *Results[3];
198};
199
Richard Smith23da82c2015-11-20 22:40:06 +0000200static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
201 StringRef Name,
202 MutableArrayRef<Expr *> Args) {
203 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
204
205 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
206 CXXScopeSpec SS;
207 ExprResult Result = S.BuildMemberReferenceExpr(
208 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
209 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
210 /*Scope=*/nullptr);
211 if (Result.isInvalid())
212 return ExprError();
213
214 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
215}
216
Richard Smith9f690bd2015-10-27 06:02:45 +0000217/// Build calls to await_ready, await_suspend, and await_resume for a co_await
218/// expression.
219static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
220 Expr *E) {
221 // Assume invalid until we see otherwise.
222 ReadySuspendResumeResult Calls = {true, {}};
223
224 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
225 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000226 Expr *Operand = new (S.Context) OpaqueValueExpr(
Gor Nishanov8df64e92016-10-27 16:28:31 +0000227 Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000228
Richard Smith9f690bd2015-10-27 06:02:45 +0000229 // FIXME: Pass coroutine handle to await_suspend.
Richard Smith23da82c2015-11-20 22:40:06 +0000230 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
Richard Smith9f690bd2015-10-27 06:02:45 +0000231 if (Result.isInvalid())
232 return Calls;
233 Calls.Results[I] = Result.get();
234 }
235
236 Calls.IsInvalid = false;
237 return Calls;
238}
239
240ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000241 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
242 if (!Coroutine) {
243 CorrectDelayedTyposInExpr(E);
244 return ExprError();
245 }
Richard Smith10610f72015-11-20 22:57:24 +0000246 if (E->getType()->isPlaceholderType()) {
247 ExprResult R = CheckPlaceholderExpr(E);
248 if (R.isInvalid()) return ExprError();
249 E = R.get();
250 }
251
Richard Smith9f690bd2015-10-27 06:02:45 +0000252 ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
253 if (Awaitable.isInvalid())
254 return ExprError();
Eric Fiseliera5465282016-09-29 21:47:39 +0000255
Richard Smith9f690bd2015-10-27 06:02:45 +0000256 return BuildCoawaitExpr(Loc, Awaitable.get());
257}
258ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
259 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
Richard Smith744b2242015-11-20 02:54:01 +0000260 if (!Coroutine)
261 return ExprError();
Richard Smith9f690bd2015-10-27 06:02:45 +0000262
Richard Smith9f690bd2015-10-27 06:02:45 +0000263 if (E->getType()->isPlaceholderType()) {
264 ExprResult R = CheckPlaceholderExpr(E);
265 if (R.isInvalid()) return ExprError();
266 E = R.get();
267 }
268
Richard Smith10610f72015-11-20 22:57:24 +0000269 if (E->getType()->isDependentType()) {
270 Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
271 Coroutine->CoroutineStmts.push_back(Res);
272 return Res;
273 }
274
Richard Smith1f38edd2015-11-22 03:13:02 +0000275 // If the expression is a temporary, materialize it as an lvalue so that we
276 // can use it multiple times.
277 if (E->getValueKind() == VK_RValue)
Tim Shen4a05bb82016-06-21 20:29:17 +0000278 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
Richard Smith9f690bd2015-10-27 06:02:45 +0000279
280 // Build the await_ready, await_suspend, await_resume calls.
281 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
282 if (RSS.IsInvalid)
283 return ExprError();
284
285 Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
286 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000287 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000288 return Res;
289}
290
Richard Smith4ba66602015-11-22 07:05:16 +0000291static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
292 SourceLocation Loc, StringRef Name,
293 MutableArrayRef<Expr *> Args) {
Richard Smith23da82c2015-11-20 22:40:06 +0000294 assert(Coroutine->CoroutinePromise && "no promise for coroutine");
295
296 // Form a reference to the promise.
297 auto *Promise = Coroutine->CoroutinePromise;
298 ExprResult PromiseRef = S.BuildDeclRefExpr(
299 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
300 if (PromiseRef.isInvalid())
301 return ExprError();
302
303 // Call 'yield_value', passing in E.
Richard Smith4ba66602015-11-22 07:05:16 +0000304 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
Richard Smith23da82c2015-11-20 22:40:06 +0000305}
306
Richard Smith9f690bd2015-10-27 06:02:45 +0000307ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
Richard Smith23da82c2015-11-20 22:40:06 +0000308 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
Eric Fiseliera5465282016-09-29 21:47:39 +0000309 if (!Coroutine) {
310 CorrectDelayedTyposInExpr(E);
Richard Smith23da82c2015-11-20 22:40:06 +0000311 return ExprError();
Eric Fiseliera5465282016-09-29 21:47:39 +0000312 }
Richard Smith23da82c2015-11-20 22:40:06 +0000313
314 // Build yield_value call.
Richard Smith4ba66602015-11-22 07:05:16 +0000315 ExprResult Awaitable =
316 buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000317 if (Awaitable.isInvalid())
318 return ExprError();
Richard Smith23da82c2015-11-20 22:40:06 +0000319
320 // Build 'operator co_await' call.
321 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
322 if (Awaitable.isInvalid())
323 return ExprError();
324
Richard Smith9f690bd2015-10-27 06:02:45 +0000325 return BuildCoyieldExpr(Loc, Awaitable.get());
326}
327ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
328 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
Richard Smith744b2242015-11-20 02:54:01 +0000329 if (!Coroutine)
330 return ExprError();
Richard Smithcfd53b42015-10-22 06:13:50 +0000331
Richard Smith10610f72015-11-20 22:57:24 +0000332 if (E->getType()->isPlaceholderType()) {
333 ExprResult R = CheckPlaceholderExpr(E);
334 if (R.isInvalid()) return ExprError();
335 E = R.get();
336 }
337
Richard Smithd7bed4d2015-11-22 02:57:17 +0000338 if (E->getType()->isDependentType()) {
339 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
340 Coroutine->CoroutineStmts.push_back(Res);
341 return Res;
342 }
343
Richard Smith1f38edd2015-11-22 03:13:02 +0000344 // If the expression is a temporary, materialize it as an lvalue so that we
345 // can use it multiple times.
346 if (E->getValueKind() == VK_RValue)
Tim Shen4a05bb82016-06-21 20:29:17 +0000347 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
Richard Smithd7bed4d2015-11-22 02:57:17 +0000348
349 // Build the await_ready, await_suspend, await_resume calls.
350 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
351 if (RSS.IsInvalid)
352 return ExprError();
353
354 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
355 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000356 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000357 return Res;
358}
359
360StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
Eric Fiseliera5465282016-09-29 21:47:39 +0000361 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
362 if (!Coroutine) {
363 CorrectDelayedTyposInExpr(E);
364 return StmtError();
365 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000366 return BuildCoreturnStmt(Loc, E);
367}
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000368
Richard Smith9f690bd2015-10-27 06:02:45 +0000369StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
Richard Smith71d403e2015-11-22 07:33:28 +0000370 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
371 if (!Coroutine)
372 return StmtError();
373
374 if (E && E->getType()->isPlaceholderType() &&
375 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
Richard Smith10610f72015-11-20 22:57:24 +0000376 ExprResult R = CheckPlaceholderExpr(E);
377 if (R.isInvalid()) return StmtError();
378 E = R.get();
379 }
380
Richard Smith4ba66602015-11-22 07:05:16 +0000381 // FIXME: If the operand is a reference to a variable that's about to go out
Richard Smith2af65c42015-11-24 02:34:39 +0000382 // of scope, we should treat the operand as an xvalue for this overload
Richard Smith4ba66602015-11-22 07:05:16 +0000383 // resolution.
384 ExprResult PC;
Eric Fiselier98131312016-10-06 21:23:38 +0000385 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
Richard Smith4ba66602015-11-22 07:05:16 +0000386 PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
387 } else {
388 E = MakeFullDiscardedValueExpr(E).get();
389 PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
390 }
391 if (PC.isInvalid())
392 return StmtError();
393
394 Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
395
396 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
Richard Smith744b2242015-11-20 02:54:01 +0000397 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000398 return Res;
399}
400
Eric Fiselier709d1b32016-10-27 07:30:31 +0000401static ExprResult buildStdCurrentExceptionCall(Sema &S, SourceLocation Loc) {
402 NamespaceDecl *Std = S.getStdNamespace();
403 if (!Std) {
404 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
405 return ExprError();
406 }
407 LookupResult Result(S, &S.PP.getIdentifierTable().get("current_exception"),
408 Loc, Sema::LookupOrdinaryName);
409 if (!S.LookupQualifiedName(Result, Std)) {
410 S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
411 return ExprError();
412 }
413
414 // FIXME The STL is free to provide more than one overload.
415 FunctionDecl *FD = Result.getAsSingle<FunctionDecl>();
416 if (!FD) {
417 S.Diag(Loc, diag::err_malformed_std_current_exception);
418 return ExprError();
419 }
420 ExprResult Res = S.BuildDeclRefExpr(FD, FD->getType(), VK_LValue, Loc);
421 Res = S.ActOnCallExpr(/*Scope*/ nullptr, Res.get(), Loc, None, Loc);
422 if (Res.isInvalid()) {
423 S.Diag(Loc, diag::err_malformed_std_current_exception);
424 return ExprError();
425 }
426 return Res;
427}
428
Gor Nishanov8df64e92016-10-27 16:28:31 +0000429// Find an appropriate delete for the promise.
430static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
431 QualType PromiseType) {
432 FunctionDecl *OperatorDelete = nullptr;
433
434 DeclarationName DeleteName =
435 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
436
437 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
438 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
439
440 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
441 return nullptr;
442
443 if (!OperatorDelete) {
444 // Look for a global declaration.
445 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
446 const bool Overaligned = false;
447 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
448 Overaligned, DeleteName);
449 }
450 S.MarkFunctionReferenced(Loc, OperatorDelete);
451 return OperatorDelete;
452}
453
454// Builds allocation and deallocation for the coroutine. Returns false on
455// failure.
456static bool buildAllocationAndDeallocation(Sema &S, SourceLocation Loc,
457 FunctionScopeInfo *Fn,
458 Expr *&Allocation,
459 Stmt *&Deallocation) {
460 TypeSourceInfo *TInfo = Fn->CoroutinePromise->getTypeSourceInfo();
461 QualType PromiseType = TInfo->getType();
462 if (PromiseType->isDependentType())
463 return true;
464
465 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
466 return false;
467
468 // FIXME: Add support for get_return_object_on_allocation failure.
469 // FIXME: Add support for stateful allocators.
470
471 FunctionDecl *OperatorNew = nullptr;
472 FunctionDecl *OperatorDelete = nullptr;
473 FunctionDecl *UnusedResult = nullptr;
474 bool PassAlignment = false;
475
476 S.FindAllocationFunctions(Loc, SourceRange(),
477 /*UseGlobal*/ false, PromiseType,
478 /*isArray*/ false, PassAlignment,
479 /*PlacementArgs*/ None, OperatorNew, UnusedResult);
480
481 OperatorDelete = findDeleteForPromise(S, Loc, PromiseType);
482
483 if (!OperatorDelete || !OperatorNew)
484 return false;
485
486 Expr *FramePtr =
487 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
488
489 Expr *FrameSize =
490 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
491
492 // Make new call.
493
494 ExprResult NewRef =
495 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
496 if (NewRef.isInvalid())
497 return false;
498
499 ExprResult NewExpr =
500 S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc);
501 if (NewExpr.isInvalid())
502 return false;
503
504 Allocation = NewExpr.get();
505
506 // Make delete call.
507
508 QualType OpDeleteQualType = OperatorDelete->getType();
509
510 ExprResult DeleteRef =
511 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
512 if (DeleteRef.isInvalid())
513 return false;
514
515 Expr *CoroFree =
516 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
517
518 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
519
520 // Check if we need to pass the size.
521 const auto *OpDeleteType =
522 OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>();
523 if (OpDeleteType->getNumParams() > 1)
524 DeleteArgs.push_back(FrameSize);
525
526 ExprResult DeleteExpr =
527 S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
528 if (DeleteExpr.isInvalid())
529 return false;
530
531 Deallocation = DeleteExpr.get();
532
533 return true;
534}
535
Richard Smith2af65c42015-11-24 02:34:39 +0000536void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000537 FunctionScopeInfo *Fn = getCurFunction();
538 assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
539
540 // Coroutines [stmt.return]p1:
541 // A return statement shall not appear in a coroutine.
Richard Smith9f690bd2015-10-27 06:02:45 +0000542 if (Fn->FirstReturnLoc.isValid()) {
543 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
Richard Smithcfd53b42015-10-22 06:13:50 +0000544 auto *First = Fn->CoroutineStmts[0];
545 Diag(First->getLocStart(), diag::note_declared_coroutine_here)
Gor Nishanov8df64e92016-10-27 16:28:31 +0000546 << (isa<CoawaitExpr>(First) ? 0 :
547 isa<CoyieldExpr>(First) ? 1 : 2);
Richard Smithcfd53b42015-10-22 06:13:50 +0000548 }
549
550 bool AnyCoawaits = false;
551 bool AnyCoyields = false;
552 for (auto *CoroutineStmt : Fn->CoroutineStmts) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000553 AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
554 AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
Richard Smithcfd53b42015-10-22 06:13:50 +0000555 }
556
557 if (!AnyCoawaits && !AnyCoyields)
558 Diag(Fn->CoroutineStmts.front()->getLocStart(),
Richard Smith9f690bd2015-10-27 06:02:45 +0000559 diag::ext_coroutine_without_co_await_co_yield);
Richard Smithcfd53b42015-10-22 06:13:50 +0000560
Richard Smith2af65c42015-11-24 02:34:39 +0000561 SourceLocation Loc = FD->getLocation();
562
563 // Form a declaration statement for the promise declaration, so that AST
564 // visitors can more easily find it.
565 StmtResult PromiseStmt =
566 ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
567 if (PromiseStmt.isInvalid())
568 return FD->setInvalidDecl();
569
570 // Form and check implicit 'co_await p.initial_suspend();' statement.
571 ExprResult InitialSuspend =
572 buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
573 // FIXME: Support operator co_await here.
574 if (!InitialSuspend.isInvalid())
575 InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
576 InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
577 if (InitialSuspend.isInvalid())
578 return FD->setInvalidDecl();
579
580 // Form and check implicit 'co_await p.final_suspend();' statement.
581 ExprResult FinalSuspend =
582 buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
583 // FIXME: Support operator co_await here.
584 if (!FinalSuspend.isInvalid())
585 FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
586 FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
587 if (FinalSuspend.isInvalid())
588 return FD->setInvalidDecl();
589
Gor Nishanov8df64e92016-10-27 16:28:31 +0000590 // Form and check allocation and deallocation calls.
591 Expr *Allocation = nullptr;
592 Stmt *Deallocation = nullptr;
593 if (!buildAllocationAndDeallocation(*this, Loc, Fn, Allocation, Deallocation))
594 return FD->setInvalidDecl();
595
Richard Smith2af65c42015-11-24 02:34:39 +0000596 // control flowing off the end of the coroutine.
Eric Fiselier709d1b32016-10-27 07:30:31 +0000597 // Also try to form 'p.set_exception(std::current_exception());' to handle
598 // uncaught exceptions.
599 ExprResult SetException;
600 StmtResult Fallthrough;
601 if (Fn->CoroutinePromise &&
602 !Fn->CoroutinePromise->getType()->isDependentType()) {
603 CXXRecordDecl *RD = Fn->CoroutinePromise->getType()->getAsCXXRecordDecl();
604 assert(RD && "Type should have already been checked");
605 // [dcl.fct.def.coroutine]/4
606 // The unqualified-ids 'return_void' and 'return_value' are looked up in
607 // the scope of class P. If both are found, the program is ill-formed.
608 DeclarationName RVoidDN = PP.getIdentifierInfo("return_void");
609 LookupResult RVoidResult(*this, RVoidDN, Loc, Sema::LookupMemberName);
610 const bool HasRVoid = LookupQualifiedName(RVoidResult, RD);
611
612 DeclarationName RValueDN = PP.getIdentifierInfo("return_value");
613 LookupResult RValueResult(*this, RValueDN, Loc, Sema::LookupMemberName);
614 const bool HasRValue = LookupQualifiedName(RValueResult, RD);
615
616 if (HasRVoid && HasRValue) {
617 // FIXME Improve this diagnostic
618 Diag(FD->getLocation(), diag::err_coroutine_promise_return_ill_formed)
619 << RD;
620 return FD->setInvalidDecl();
621 } else if (HasRVoid) {
622 // If the unqualified-id return_void is found, flowing off the end of a
623 // coroutine is equivalent to a co_return with no operand. Otherwise,
624 // flowing off the end of a coroutine results in undefined behavior.
625 Fallthrough = BuildCoreturnStmt(FD->getLocation(), nullptr);
626 Fallthrough = ActOnFinishFullStmt(Fallthrough.get());
627 if (Fallthrough.isInvalid())
628 return FD->setInvalidDecl();
629 }
630
631 // [dcl.fct.def.coroutine]/3
632 // The unqualified-id set_exception is found in the scope of P by class
633 // member access lookup (3.4.5).
634 DeclarationName SetExDN = PP.getIdentifierInfo("set_exception");
635 LookupResult SetExResult(*this, SetExDN, Loc, Sema::LookupMemberName);
636 if (LookupQualifiedName(SetExResult, RD)) {
637 // Form the call 'p.set_exception(std::current_exception())'
638 SetException = buildStdCurrentExceptionCall(*this, Loc);
639 if (SetException.isInvalid())
640 return FD->setInvalidDecl();
641 Expr *E = SetException.get();
642 SetException = buildPromiseCall(*this, Fn, Loc, "set_exception", E);
643 SetException = ActOnFinishFullExpr(SetException.get(), Loc);
644 if (SetException.isInvalid())
645 return FD->setInvalidDecl();
646 }
647 }
Richard Smith2af65c42015-11-24 02:34:39 +0000648
649 // Build implicit 'p.get_return_object()' expression and form initialization
650 // of return type from it.
651 ExprResult ReturnObject =
Gor Nishanov8df64e92016-10-27 16:28:31 +0000652 buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
Richard Smith2af65c42015-11-24 02:34:39 +0000653 if (ReturnObject.isInvalid())
654 return FD->setInvalidDecl();
655 QualType RetType = FD->getReturnType();
656 if (!RetType->isDependentType()) {
657 InitializedEntity Entity =
658 InitializedEntity::InitializeResult(Loc, RetType, false);
659 ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
660 ReturnObject.get());
661 if (ReturnObject.isInvalid())
662 return FD->setInvalidDecl();
663 }
664 ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
665 if (ReturnObject.isInvalid())
666 return FD->setInvalidDecl();
667
668 // FIXME: Perform move-initialization of parameters into frame-local copies.
669 SmallVector<Expr*, 16> ParamMoves;
670
671 // Build body for the coroutine wrapper statement.
672 Body = new (Context) CoroutineBodyStmt(
673 Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
Gor Nishanov8df64e92016-10-27 16:28:31 +0000674 SetException.get(), Fallthrough.get(), Allocation, Deallocation,
675 ReturnObject.get(), ParamMoves);
Richard Smithcfd53b42015-10-22 06:13:50 +0000676}