blob: 2e56938c31cfcc24ea269ee9749081fe4923424a [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"
19#include "clang/Sema/Overload.h"
Richard Smithcfd53b42015-10-22 06:13:50 +000020using namespace clang;
21using namespace sema;
22
Richard Smith9f690bd2015-10-27 06:02:45 +000023/// Look up the std::coroutine_traits<...>::promise_type for the given
24/// function type.
25static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
26 SourceLocation Loc) {
27 // FIXME: Cache std::coroutine_traits once we've found it.
28 NamespaceDecl *Std = S.getStdNamespace();
29 if (!Std) {
30 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
31 return QualType();
32 }
33
34 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
35 Loc, Sema::LookupOrdinaryName);
36 if (!S.LookupQualifiedName(Result, Std)) {
37 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
38 return QualType();
39 }
40
41 ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
42 if (!CoroTraits) {
43 Result.suppressDiagnostics();
44 // We found something weird. Complain about the first thing we found.
45 NamedDecl *Found = *Result.begin();
46 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
47 return QualType();
48 }
49
50 // Form template argument list for coroutine_traits<R, P1, P2, ...>.
51 TemplateArgumentListInfo Args(Loc, Loc);
52 Args.addArgument(TemplateArgumentLoc(
53 TemplateArgument(FnType->getReturnType()),
54 S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc)));
Richard Smith71d403e2015-11-22 07:33:28 +000055 // FIXME: If the function is a non-static member function, add the type
56 // of the implicit object parameter before the formal parameters.
Richard Smith9f690bd2015-10-27 06:02:45 +000057 for (QualType T : FnType->getParamTypes())
58 Args.addArgument(TemplateArgumentLoc(
59 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc)));
60
61 // Build the template-id.
62 QualType CoroTrait =
63 S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args);
64 if (CoroTrait.isNull())
65 return QualType();
66 if (S.RequireCompleteType(Loc, CoroTrait,
67 diag::err_coroutine_traits_missing_specialization))
68 return QualType();
69
70 CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl();
71 assert(RD && "specialization of class template is not a class?");
72
73 // Look up the ::promise_type member.
74 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc,
75 Sema::LookupOrdinaryName);
76 S.LookupQualifiedName(R, RD);
77 auto *Promise = R.getAsSingle<TypeDecl>();
78 if (!Promise) {
79 S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
80 << RD;
81 return QualType();
82 }
83
84 // The promise type is required to be a class type.
85 QualType PromiseType = S.Context.getTypeDeclType(Promise);
86 if (!PromiseType->getAsCXXRecordDecl()) {
Richard Smith9b2f53e2015-11-19 02:36:35 +000087 // Use the fully-qualified name of the type.
88 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std);
89 NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
90 CoroTrait.getTypePtr());
91 PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
92
Richard Smith9f690bd2015-10-27 06:02:45 +000093 S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
94 << PromiseType;
95 return QualType();
96 }
97
98 return PromiseType;
99}
100
101/// Check that this is a context in which a coroutine suspension can appear.
Richard Smithcfd53b42015-10-22 06:13:50 +0000102static FunctionScopeInfo *
103checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
Richard Smith744b2242015-11-20 02:54:01 +0000104 // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
105 if (S.isUnevaluatedContext()) {
106 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
Richard Smithcfd53b42015-10-22 06:13:50 +0000107 return nullptr;
Richard Smith744b2242015-11-20 02:54:01 +0000108 }
Richard Smithcfd53b42015-10-22 06:13:50 +0000109
110 // Any other usage must be within a function.
111 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
112 if (!FD) {
113 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
114 ? diag::err_coroutine_objc_method
115 : diag::err_coroutine_outside_function) << Keyword;
116 } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
117 // Coroutines TS [special]/6:
118 // A special member function shall not be a coroutine.
119 //
120 // FIXME: We assume that this really means that a coroutine cannot
121 // be a constructor or destructor.
122 S.Diag(Loc, diag::err_coroutine_ctor_dtor)
123 << isa<CXXDestructorDecl>(FD) << Keyword;
124 } else if (FD->isConstexpr()) {
125 S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
126 } else if (FD->isVariadic()) {
127 S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
128 } else {
129 auto *ScopeInfo = S.getCurFunction();
130 assert(ScopeInfo && "missing function scope for function");
Richard Smith9f690bd2015-10-27 06:02:45 +0000131
132 // If we don't have a promise variable, build one now.
Richard Smith23da82c2015-11-20 22:40:06 +0000133 if (!ScopeInfo->CoroutinePromise) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000134 QualType T =
Richard Smith23da82c2015-11-20 22:40:06 +0000135 FD->getType()->isDependentType()
136 ? S.Context.DependentTy
137 : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(),
138 Loc);
Richard Smith9f690bd2015-10-27 06:02:45 +0000139 if (T.isNull())
140 return nullptr;
141
142 // Create and default-initialize the promise.
143 ScopeInfo->CoroutinePromise =
144 VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
145 &S.PP.getIdentifierTable().get("__promise"), T,
146 S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
147 S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
148 if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
149 S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
150 }
151
Richard Smithcfd53b42015-10-22 06:13:50 +0000152 return ScopeInfo;
153 }
154
155 return nullptr;
156}
157
Richard Smith9f690bd2015-10-27 06:02:45 +0000158/// Build a call to 'operator co_await' if there is a suitable operator for
159/// the given expression.
160static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
161 SourceLocation Loc, Expr *E) {
162 UnresolvedSet<16> Functions;
163 SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
164 Functions);
165 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
166}
Richard Smithcfd53b42015-10-22 06:13:50 +0000167
Richard Smith9f690bd2015-10-27 06:02:45 +0000168struct ReadySuspendResumeResult {
169 bool IsInvalid;
170 Expr *Results[3];
171};
172
Richard Smith23da82c2015-11-20 22:40:06 +0000173static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
174 StringRef Name,
175 MutableArrayRef<Expr *> Args) {
176 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
177
178 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
179 CXXScopeSpec SS;
180 ExprResult Result = S.BuildMemberReferenceExpr(
181 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
182 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
183 /*Scope=*/nullptr);
184 if (Result.isInvalid())
185 return ExprError();
186
187 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
188}
189
Richard Smith9f690bd2015-10-27 06:02:45 +0000190/// Build calls to await_ready, await_suspend, and await_resume for a co_await
191/// expression.
192static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
193 Expr *E) {
194 // Assume invalid until we see otherwise.
195 ReadySuspendResumeResult Calls = {true, {}};
196
197 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
198 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000199 Expr *Operand = new (S.Context) OpaqueValueExpr(
Richard Smith1f38edd2015-11-22 03:13:02 +0000200 Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000201
Richard Smith9f690bd2015-10-27 06:02:45 +0000202 // FIXME: Pass coroutine handle to await_suspend.
Richard Smith23da82c2015-11-20 22:40:06 +0000203 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
Richard Smith9f690bd2015-10-27 06:02:45 +0000204 if (Result.isInvalid())
205 return Calls;
206 Calls.Results[I] = Result.get();
207 }
208
209 Calls.IsInvalid = false;
210 return Calls;
211}
212
213ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
Richard Smith10610f72015-11-20 22:57:24 +0000214 if (E->getType()->isPlaceholderType()) {
215 ExprResult R = CheckPlaceholderExpr(E);
216 if (R.isInvalid()) return ExprError();
217 E = R.get();
218 }
219
Richard Smith9f690bd2015-10-27 06:02:45 +0000220 ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
221 if (Awaitable.isInvalid())
222 return ExprError();
223 return BuildCoawaitExpr(Loc, Awaitable.get());
224}
225ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
226 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
Richard Smith744b2242015-11-20 02:54:01 +0000227 if (!Coroutine)
228 return ExprError();
Richard Smith9f690bd2015-10-27 06:02:45 +0000229
Richard Smith9f690bd2015-10-27 06:02:45 +0000230 if (E->getType()->isPlaceholderType()) {
231 ExprResult R = CheckPlaceholderExpr(E);
232 if (R.isInvalid()) return ExprError();
233 E = R.get();
234 }
235
Richard Smith10610f72015-11-20 22:57:24 +0000236 if (E->getType()->isDependentType()) {
237 Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
238 Coroutine->CoroutineStmts.push_back(Res);
239 return Res;
240 }
241
Richard Smith1f38edd2015-11-22 03:13:02 +0000242 // If the expression is a temporary, materialize it as an lvalue so that we
243 // can use it multiple times.
244 if (E->getValueKind() == VK_RValue)
245 E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
Richard Smith9f690bd2015-10-27 06:02:45 +0000246
247 // Build the await_ready, await_suspend, await_resume calls.
248 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
249 if (RSS.IsInvalid)
250 return ExprError();
251
252 Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
253 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000254 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000255 return Res;
256}
257
Richard Smith4ba66602015-11-22 07:05:16 +0000258static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
259 SourceLocation Loc, StringRef Name,
260 MutableArrayRef<Expr *> Args) {
Richard Smith23da82c2015-11-20 22:40:06 +0000261 assert(Coroutine->CoroutinePromise && "no promise for coroutine");
262
263 // Form a reference to the promise.
264 auto *Promise = Coroutine->CoroutinePromise;
265 ExprResult PromiseRef = S.BuildDeclRefExpr(
266 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
267 if (PromiseRef.isInvalid())
268 return ExprError();
269
270 // Call 'yield_value', passing in E.
Richard Smith4ba66602015-11-22 07:05:16 +0000271 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
Richard Smith23da82c2015-11-20 22:40:06 +0000272}
273
Richard Smith9f690bd2015-10-27 06:02:45 +0000274ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
Richard Smith23da82c2015-11-20 22:40:06 +0000275 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
276 if (!Coroutine)
277 return ExprError();
278
279 // Build yield_value call.
Richard Smith4ba66602015-11-22 07:05:16 +0000280 ExprResult Awaitable =
281 buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
Richard Smith9f690bd2015-10-27 06:02:45 +0000282 if (Awaitable.isInvalid())
283 return ExprError();
Richard Smith23da82c2015-11-20 22:40:06 +0000284
285 // Build 'operator co_await' call.
286 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
287 if (Awaitable.isInvalid())
288 return ExprError();
289
Richard Smith9f690bd2015-10-27 06:02:45 +0000290 return BuildCoyieldExpr(Loc, Awaitable.get());
291}
292ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
293 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
Richard Smith744b2242015-11-20 02:54:01 +0000294 if (!Coroutine)
295 return ExprError();
Richard Smithcfd53b42015-10-22 06:13:50 +0000296
Richard Smith10610f72015-11-20 22:57:24 +0000297 if (E->getType()->isPlaceholderType()) {
298 ExprResult R = CheckPlaceholderExpr(E);
299 if (R.isInvalid()) return ExprError();
300 E = R.get();
301 }
302
Richard Smithd7bed4d2015-11-22 02:57:17 +0000303 if (E->getType()->isDependentType()) {
304 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
305 Coroutine->CoroutineStmts.push_back(Res);
306 return Res;
307 }
308
Richard Smith1f38edd2015-11-22 03:13:02 +0000309 // If the expression is a temporary, materialize it as an lvalue so that we
310 // can use it multiple times.
311 if (E->getValueKind() == VK_RValue)
312 E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
Richard Smithd7bed4d2015-11-22 02:57:17 +0000313
314 // Build the await_ready, await_suspend, await_resume calls.
315 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
316 if (RSS.IsInvalid)
317 return ExprError();
318
319 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
320 RSS.Results[2]);
Richard Smith744b2242015-11-20 02:54:01 +0000321 Coroutine->CoroutineStmts.push_back(Res);
Richard Smithcfd53b42015-10-22 06:13:50 +0000322 return Res;
323}
324
325StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000326 return BuildCoreturnStmt(Loc, E);
327}
328StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
Richard Smith71d403e2015-11-22 07:33:28 +0000329 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
330 if (!Coroutine)
331 return StmtError();
332
333 if (E && E->getType()->isPlaceholderType() &&
334 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
Richard Smith10610f72015-11-20 22:57:24 +0000335 ExprResult R = CheckPlaceholderExpr(E);
336 if (R.isInvalid()) return StmtError();
337 E = R.get();
338 }
339
Richard Smith4ba66602015-11-22 07:05:16 +0000340 // FIXME: If the operand is a reference to a variable that's about to go out
341 // ot scope, we should treat the operand as an xvalue for this overload
342 // resolution.
343 ExprResult PC;
344 if (E && !E->getType()->isVoidType()) {
345 PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
346 } else {
347 E = MakeFullDiscardedValueExpr(E).get();
348 PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
349 }
350 if (PC.isInvalid())
351 return StmtError();
352
353 Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
354
355 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
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
360void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *Body) {
361 FunctionScopeInfo *Fn = getCurFunction();
362 assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
363
364 // Coroutines [stmt.return]p1:
365 // A return statement shall not appear in a coroutine.
Richard Smith9f690bd2015-10-27 06:02:45 +0000366 if (Fn->FirstReturnLoc.isValid()) {
367 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
Richard Smithcfd53b42015-10-22 06:13:50 +0000368 auto *First = Fn->CoroutineStmts[0];
369 Diag(First->getLocStart(), diag::note_declared_coroutine_here)
Richard Smith9f690bd2015-10-27 06:02:45 +0000370 << (isa<CoawaitExpr>(First) ? 0 :
371 isa<CoyieldExpr>(First) ? 1 : 2);
Richard Smithcfd53b42015-10-22 06:13:50 +0000372 }
373
374 bool AnyCoawaits = false;
375 bool AnyCoyields = false;
376 for (auto *CoroutineStmt : Fn->CoroutineStmts) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000377 AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
378 AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
Richard Smithcfd53b42015-10-22 06:13:50 +0000379 }
380
381 if (!AnyCoawaits && !AnyCoyields)
382 Diag(Fn->CoroutineStmts.front()->getLocStart(),
Richard Smith9f690bd2015-10-27 06:02:45 +0000383 diag::ext_coroutine_without_co_await_co_yield);
Richard Smithcfd53b42015-10-22 06:13:50 +0000384
Richard Smith9f690bd2015-10-27 06:02:45 +0000385 // FIXME: Perform analysis of initial and final suspend,
386 // and set_exception call.
Richard Smithcfd53b42015-10-22 06:13:50 +0000387}