1 //===--- 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" 15 #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/Initialization.h" 20 #include "clang/Sema/Overload.h" 21 using namespace clang; 22 using namespace sema; 23 24 static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, 25 SourceLocation Loc) { 26 DeclarationName DN = S.PP.getIdentifierInfo(Name); 27 LookupResult LR(S, DN, Loc, Sema::LookupMemberName); 28 // Suppress diagnostics when a private member is selected. The same warnings 29 // will be produced again when building the call. 30 LR.suppressDiagnostics(); 31 return S.LookupQualifiedName(LR, RD); 32 } 33 34 /// Look up the std::coroutine_traits<...>::promise_type for the given 35 /// function type. 36 static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, 37 SourceLocation KwLoc, 38 SourceLocation FuncLoc) { 39 // FIXME: Cache std::coroutine_traits once we've found it. 40 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); 41 if (!StdExp) { 42 S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) 43 << "std::experimental::coroutine_traits"; 44 return QualType(); 45 } 46 47 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), 48 FuncLoc, Sema::LookupOrdinaryName); 49 if (!S.LookupQualifiedName(Result, StdExp)) { 50 S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) 51 << "std::experimental::coroutine_traits"; 52 return QualType(); 53 } 54 55 ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>(); 56 if (!CoroTraits) { 57 Result.suppressDiagnostics(); 58 // We found something weird. Complain about the first thing we found. 59 NamedDecl *Found = *Result.begin(); 60 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); 61 return QualType(); 62 } 63 64 // Form template argument list for coroutine_traits<R, P1, P2, ...>. 65 TemplateArgumentListInfo Args(KwLoc, KwLoc); 66 Args.addArgument(TemplateArgumentLoc( 67 TemplateArgument(FnType->getReturnType()), 68 S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), KwLoc))); 69 // FIXME: If the function is a non-static member function, add the type 70 // of the implicit object parameter before the formal parameters. 71 for (QualType T : FnType->getParamTypes()) 72 Args.addArgument(TemplateArgumentLoc( 73 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc))); 74 75 // Build the template-id. 76 QualType CoroTrait = 77 S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args); 78 if (CoroTrait.isNull()) 79 return QualType(); 80 if (S.RequireCompleteType(KwLoc, CoroTrait, 81 diag::err_coroutine_type_missing_specialization)) 82 return QualType(); 83 84 auto *RD = CoroTrait->getAsCXXRecordDecl(); 85 assert(RD && "specialization of class template is not a class?"); 86 87 // Look up the ::promise_type member. 88 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc, 89 Sema::LookupOrdinaryName); 90 S.LookupQualifiedName(R, RD); 91 auto *Promise = R.getAsSingle<TypeDecl>(); 92 if (!Promise) { 93 S.Diag(FuncLoc, 94 diag::err_implied_std_coroutine_traits_promise_type_not_found) 95 << RD; 96 return QualType(); 97 } 98 // The promise type is required to be a class type. 99 QualType PromiseType = S.Context.getTypeDeclType(Promise); 100 101 auto buildElaboratedType = [&]() { 102 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp); 103 NNS = NestedNameSpecifier::Create(S.Context, NNS, false, 104 CoroTrait.getTypePtr()); 105 return S.Context.getElaboratedType(ETK_None, NNS, PromiseType); 106 }; 107 108 if (!PromiseType->getAsCXXRecordDecl()) { 109 S.Diag(FuncLoc, 110 diag::err_implied_std_coroutine_traits_promise_type_not_class) 111 << buildElaboratedType(); 112 return QualType(); 113 } 114 if (S.RequireCompleteType(FuncLoc, buildElaboratedType(), 115 diag::err_coroutine_promise_type_incomplete)) 116 return QualType(); 117 118 return PromiseType; 119 } 120 121 /// Look up the std::coroutine_traits<...>::promise_type for the given 122 /// function type. 123 static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, 124 SourceLocation Loc) { 125 if (PromiseType.isNull()) 126 return QualType(); 127 128 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); 129 assert(StdExp && "Should already be diagnosed"); 130 131 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"), 132 Loc, Sema::LookupOrdinaryName); 133 if (!S.LookupQualifiedName(Result, StdExp)) { 134 S.Diag(Loc, diag::err_implied_coroutine_type_not_found) 135 << "std::experimental::coroutine_handle"; 136 return QualType(); 137 } 138 139 ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>(); 140 if (!CoroHandle) { 141 Result.suppressDiagnostics(); 142 // We found something weird. Complain about the first thing we found. 143 NamedDecl *Found = *Result.begin(); 144 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle); 145 return QualType(); 146 } 147 148 // Form template argument list for coroutine_handle<Promise>. 149 TemplateArgumentListInfo Args(Loc, Loc); 150 Args.addArgument(TemplateArgumentLoc( 151 TemplateArgument(PromiseType), 152 S.Context.getTrivialTypeSourceInfo(PromiseType, Loc))); 153 154 // Build the template-id. 155 QualType CoroHandleType = 156 S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args); 157 if (CoroHandleType.isNull()) 158 return QualType(); 159 if (S.RequireCompleteType(Loc, CoroHandleType, 160 diag::err_coroutine_type_missing_specialization)) 161 return QualType(); 162 163 return CoroHandleType; 164 } 165 166 static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, 167 StringRef Keyword) { 168 // 'co_await' and 'co_yield' are not permitted in unevaluated operands. 169 if (S.isUnevaluatedContext()) { 170 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword; 171 return false; 172 } 173 174 // Any other usage must be within a function. 175 auto *FD = dyn_cast<FunctionDecl>(S.CurContext); 176 if (!FD) { 177 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext) 178 ? diag::err_coroutine_objc_method 179 : diag::err_coroutine_outside_function) << Keyword; 180 return false; 181 } 182 183 // An enumeration for mapping the diagnostic type to the correct diagnostic 184 // selection index. 185 enum InvalidFuncDiag { 186 DiagCtor = 0, 187 DiagDtor, 188 DiagCopyAssign, 189 DiagMoveAssign, 190 DiagMain, 191 DiagConstexpr, 192 DiagAutoRet, 193 DiagVarargs, 194 }; 195 bool Diagnosed = false; 196 auto DiagInvalid = [&](InvalidFuncDiag ID) { 197 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword; 198 Diagnosed = true; 199 return false; 200 }; 201 202 // Diagnose when a constructor, destructor, copy/move assignment operator, 203 // or the function 'main' are declared as a coroutine. 204 auto *MD = dyn_cast<CXXMethodDecl>(FD); 205 if (MD && isa<CXXConstructorDecl>(MD)) 206 return DiagInvalid(DiagCtor); 207 else if (MD && isa<CXXDestructorDecl>(MD)) 208 return DiagInvalid(DiagDtor); 209 else if (MD && MD->isCopyAssignmentOperator()) 210 return DiagInvalid(DiagCopyAssign); 211 else if (MD && MD->isMoveAssignmentOperator()) 212 return DiagInvalid(DiagMoveAssign); 213 else if (FD->isMain()) 214 return DiagInvalid(DiagMain); 215 216 // Emit a diagnostics for each of the following conditions which is not met. 217 if (FD->isConstexpr()) 218 DiagInvalid(DiagConstexpr); 219 if (FD->getReturnType()->isUndeducedType()) 220 DiagInvalid(DiagAutoRet); 221 if (FD->isVariadic()) 222 DiagInvalid(DiagVarargs); 223 224 return !Diagnosed; 225 } 226 227 static ExprResult buildOperatorCoawaitLookupExpr(Sema &SemaRef, Scope *S, 228 SourceLocation Loc) { 229 DeclarationName OpName = 230 SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait); 231 LookupResult Operators(SemaRef, OpName, SourceLocation(), 232 Sema::LookupOperatorName); 233 SemaRef.LookupName(Operators, S); 234 235 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); 236 const auto &Functions = Operators.asUnresolvedSet(); 237 bool IsOverloaded = 238 Functions.size() > 1 || 239 (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); 240 Expr *CoawaitOp = UnresolvedLookupExpr::Create( 241 SemaRef.Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), 242 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded, 243 Functions.begin(), Functions.end()); 244 assert(CoawaitOp); 245 return CoawaitOp; 246 } 247 248 /// Build a call to 'operator co_await' if there is a suitable operator for 249 /// the given expression. 250 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, SourceLocation Loc, 251 Expr *E, 252 UnresolvedLookupExpr *Lookup) { 253 UnresolvedSet<16> Functions; 254 Functions.append(Lookup->decls_begin(), Lookup->decls_end()); 255 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E); 256 } 257 258 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, 259 SourceLocation Loc, Expr *E) { 260 ExprResult R = buildOperatorCoawaitLookupExpr(SemaRef, S, Loc); 261 if (R.isInvalid()) 262 return ExprError(); 263 return buildOperatorCoawaitCall(SemaRef, Loc, E, 264 cast<UnresolvedLookupExpr>(R.get())); 265 } 266 267 static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id, 268 MultiExprArg CallArgs) { 269 StringRef Name = S.Context.BuiltinInfo.getName(Id); 270 LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName); 271 S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true); 272 273 auto *BuiltInDecl = R.getAsSingle<FunctionDecl>(); 274 assert(BuiltInDecl && "failed to find builtin declaration"); 275 276 ExprResult DeclRef = 277 S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc); 278 assert(DeclRef.isUsable() && "Builtin reference cannot fail"); 279 280 ExprResult Call = 281 S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc); 282 283 assert(!Call.isInvalid() && "Call to builtin cannot fail!"); 284 return Call.get(); 285 } 286 287 static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, 288 SourceLocation Loc) { 289 QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc); 290 if (CoroHandleType.isNull()) 291 return ExprError(); 292 293 DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType); 294 LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc, 295 Sema::LookupOrdinaryName); 296 if (!S.LookupQualifiedName(Found, LookupCtx)) { 297 S.Diag(Loc, diag::err_coroutine_handle_missing_member) 298 << "from_address"; 299 return ExprError(); 300 } 301 302 Expr *FramePtr = 303 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {}); 304 305 CXXScopeSpec SS; 306 ExprResult FromAddr = 307 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false); 308 if (FromAddr.isInvalid()) 309 return ExprError(); 310 311 return S.ActOnCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc); 312 } 313 314 struct ReadySuspendResumeResult { 315 Expr *Results[3]; 316 OpaqueValueExpr *OpaqueValue; 317 bool IsInvalid; 318 }; 319 320 static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, 321 StringRef Name, MultiExprArg Args) { 322 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc); 323 324 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&. 325 CXXScopeSpec SS; 326 ExprResult Result = S.BuildMemberReferenceExpr( 327 Base, Base->getType(), Loc, /*IsPtr=*/false, SS, 328 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr, 329 /*Scope=*/nullptr); 330 if (Result.isInvalid()) 331 return ExprError(); 332 333 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr); 334 } 335 336 /// Build calls to await_ready, await_suspend, and await_resume for a co_await 337 /// expression. 338 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, 339 SourceLocation Loc, Expr *E) { 340 OpaqueValueExpr *Operand = new (S.Context) 341 OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E); 342 343 // Assume invalid until we see otherwise. 344 ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true}; 345 346 ExprResult CoroHandleRes = buildCoroutineHandle(S, CoroPromise->getType(), Loc); 347 if (CoroHandleRes.isInvalid()) 348 return Calls; 349 Expr *CoroHandle = CoroHandleRes.get(); 350 351 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"}; 352 MultiExprArg Args[] = {None, CoroHandle, None}; 353 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) { 354 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], Args[I]); 355 if (Result.isInvalid()) 356 return Calls; 357 Calls.Results[I] = Result.get(); 358 } 359 360 Calls.IsInvalid = false; 361 return Calls; 362 } 363 364 static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, 365 SourceLocation Loc, StringRef Name, 366 MultiExprArg Args) { 367 368 // Form a reference to the promise. 369 ExprResult PromiseRef = S.BuildDeclRefExpr( 370 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc); 371 if (PromiseRef.isInvalid()) 372 return ExprError(); 373 374 // Call 'yield_value', passing in E. 375 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args); 376 } 377 378 VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { 379 assert(isa<FunctionDecl>(CurContext) && "not in a function scope"); 380 auto *FD = cast<FunctionDecl>(CurContext); 381 382 QualType T = 383 FD->getType()->isDependentType() 384 ? Context.DependentTy 385 : lookupPromiseType(*this, FD->getType()->castAs<FunctionProtoType>(), 386 Loc, FD->getLocation()); 387 if (T.isNull()) 388 return nullptr; 389 390 auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(), 391 &PP.getIdentifierTable().get("__promise"), T, 392 Context.getTrivialTypeSourceInfo(T, Loc), SC_None); 393 CheckVariableDeclarationType(VD); 394 if (VD->isInvalidDecl()) 395 return nullptr; 396 ActOnUninitializedDecl(VD); 397 assert(!VD->isInvalidDecl()); 398 return VD; 399 } 400 401 /// Check that this is a context in which a coroutine suspension can appear. 402 static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc, 403 StringRef Keyword, 404 bool IsImplicit = false) { 405 if (!isValidCoroutineContext(S, Loc, Keyword)) 406 return nullptr; 407 408 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope"); 409 410 auto *ScopeInfo = S.getCurFunction(); 411 assert(ScopeInfo && "missing function scope for function"); 412 413 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit) 414 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword); 415 416 if (ScopeInfo->CoroutinePromise) 417 return ScopeInfo; 418 419 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc); 420 if (!ScopeInfo->CoroutinePromise) 421 return nullptr; 422 423 return ScopeInfo; 424 } 425 426 static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, 427 StringRef Keyword) { 428 if (!checkCoroutineContext(S, KWLoc, Keyword)) 429 return false; 430 auto *ScopeInfo = S.getCurFunction(); 431 assert(ScopeInfo->CoroutinePromise); 432 433 // If we have existing coroutine statements then we have already built 434 // the initial and final suspend points. 435 if (!ScopeInfo->NeedsCoroutineSuspends) 436 return true; 437 438 ScopeInfo->setNeedsCoroutineSuspends(false); 439 440 auto *Fn = cast<FunctionDecl>(S.CurContext); 441 SourceLocation Loc = Fn->getLocation(); 442 // Build the initial suspend point 443 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult { 444 ExprResult Suspend = 445 buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None); 446 if (Suspend.isInvalid()) 447 return StmtError(); 448 Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get()); 449 if (Suspend.isInvalid()) 450 return StmtError(); 451 Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(), 452 /*IsImplicit*/ true); 453 Suspend = S.ActOnFinishFullExpr(Suspend.get()); 454 if (Suspend.isInvalid()) { 455 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) 456 << ((Name == "initial_suspend") ? 0 : 1); 457 S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword; 458 return StmtError(); 459 } 460 return cast<Stmt>(Suspend.get()); 461 }; 462 463 StmtResult InitSuspend = buildSuspends("initial_suspend"); 464 if (InitSuspend.isInvalid()) 465 return true; 466 467 StmtResult FinalSuspend = buildSuspends("final_suspend"); 468 if (FinalSuspend.isInvalid()) 469 return true; 470 471 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get()); 472 473 return true; 474 } 475 476 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) { 477 if (!actOnCoroutineBodyStart(*this, S, Loc, "co_await")) { 478 CorrectDelayedTyposInExpr(E); 479 return ExprError(); 480 } 481 482 if (E->getType()->isPlaceholderType()) { 483 ExprResult R = CheckPlaceholderExpr(E); 484 if (R.isInvalid()) return ExprError(); 485 E = R.get(); 486 } 487 ExprResult Lookup = buildOperatorCoawaitLookupExpr(*this, S, Loc); 488 if (Lookup.isInvalid()) 489 return ExprError(); 490 return BuildUnresolvedCoawaitExpr(Loc, E, 491 cast<UnresolvedLookupExpr>(Lookup.get())); 492 } 493 494 ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E, 495 UnresolvedLookupExpr *Lookup) { 496 auto *FSI = checkCoroutineContext(*this, Loc, "co_await"); 497 if (!FSI) 498 return ExprError(); 499 500 if (E->getType()->isPlaceholderType()) { 501 ExprResult R = CheckPlaceholderExpr(E); 502 if (R.isInvalid()) 503 return ExprError(); 504 E = R.get(); 505 } 506 507 auto *Promise = FSI->CoroutinePromise; 508 if (Promise->getType()->isDependentType()) { 509 Expr *Res = 510 new (Context) DependentCoawaitExpr(Loc, Context.DependentTy, E, Lookup); 511 return Res; 512 } 513 514 auto *RD = Promise->getType()->getAsCXXRecordDecl(); 515 if (lookupMember(*this, "await_transform", RD, Loc)) { 516 ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E); 517 if (R.isInvalid()) { 518 Diag(Loc, 519 diag::note_coroutine_promise_implicit_await_transform_required_here) 520 << E->getSourceRange(); 521 return ExprError(); 522 } 523 E = R.get(); 524 } 525 ExprResult Awaitable = buildOperatorCoawaitCall(*this, Loc, E, Lookup); 526 if (Awaitable.isInvalid()) 527 return ExprError(); 528 529 return BuildResolvedCoawaitExpr(Loc, Awaitable.get()); 530 } 531 532 ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E, 533 bool IsImplicit) { 534 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit); 535 if (!Coroutine) 536 return ExprError(); 537 538 if (E->getType()->isPlaceholderType()) { 539 ExprResult R = CheckPlaceholderExpr(E); 540 if (R.isInvalid()) return ExprError(); 541 E = R.get(); 542 } 543 544 if (E->getType()->isDependentType()) { 545 Expr *Res = new (Context) 546 CoawaitExpr(Loc, Context.DependentTy, E, IsImplicit); 547 return Res; 548 } 549 550 // If the expression is a temporary, materialize it as an lvalue so that we 551 // can use it multiple times. 552 if (E->getValueKind() == VK_RValue) 553 E = CreateMaterializeTemporaryExpr(E->getType(), E, true); 554 555 // Build the await_ready, await_suspend, await_resume calls. 556 ReadySuspendResumeResult RSS = 557 buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E); 558 if (RSS.IsInvalid) 559 return ExprError(); 560 561 Expr *Res = 562 new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1], 563 RSS.Results[2], RSS.OpaqueValue, IsImplicit); 564 565 return Res; 566 } 567 568 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) { 569 if (!actOnCoroutineBodyStart(*this, S, Loc, "co_yield")) { 570 CorrectDelayedTyposInExpr(E); 571 return ExprError(); 572 } 573 574 // Build yield_value call. 575 ExprResult Awaitable = buildPromiseCall( 576 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E); 577 if (Awaitable.isInvalid()) 578 return ExprError(); 579 580 // Build 'operator co_await' call. 581 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get()); 582 if (Awaitable.isInvalid()) 583 return ExprError(); 584 585 return BuildCoyieldExpr(Loc, Awaitable.get()); 586 } 587 ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { 588 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); 589 if (!Coroutine) 590 return ExprError(); 591 592 if (E->getType()->isPlaceholderType()) { 593 ExprResult R = CheckPlaceholderExpr(E); 594 if (R.isInvalid()) return ExprError(); 595 E = R.get(); 596 } 597 598 if (E->getType()->isDependentType()) { 599 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E); 600 return Res; 601 } 602 603 // If the expression is a temporary, materialize it as an lvalue so that we 604 // can use it multiple times. 605 if (E->getValueKind() == VK_RValue) 606 E = CreateMaterializeTemporaryExpr(E->getType(), E, true); 607 608 // Build the await_ready, await_suspend, await_resume calls. 609 ReadySuspendResumeResult RSS = 610 buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E); 611 if (RSS.IsInvalid) 612 return ExprError(); 613 614 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1], 615 RSS.Results[2], RSS.OpaqueValue); 616 617 return Res; 618 } 619 620 StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) { 621 if (!actOnCoroutineBodyStart(*this, S, Loc, "co_return")) { 622 CorrectDelayedTyposInExpr(E); 623 return StmtError(); 624 } 625 return BuildCoreturnStmt(Loc, E); 626 } 627 628 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, 629 bool IsImplicit) { 630 auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit); 631 if (!FSI) 632 return StmtError(); 633 634 if (E && E->getType()->isPlaceholderType() && 635 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) { 636 ExprResult R = CheckPlaceholderExpr(E); 637 if (R.isInvalid()) return StmtError(); 638 E = R.get(); 639 } 640 641 // FIXME: If the operand is a reference to a variable that's about to go out 642 // of scope, we should treat the operand as an xvalue for this overload 643 // resolution. 644 VarDecl *Promise = FSI->CoroutinePromise; 645 ExprResult PC; 646 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) { 647 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E); 648 } else { 649 E = MakeFullDiscardedValueExpr(E).get(); 650 PC = buildPromiseCall(*this, Promise, Loc, "return_void", None); 651 } 652 if (PC.isInvalid()) 653 return StmtError(); 654 655 Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); 656 657 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); 658 return Res; 659 } 660 661 // Find an appropriate delete for the promise. 662 static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc, 663 QualType PromiseType) { 664 FunctionDecl *OperatorDelete = nullptr; 665 666 DeclarationName DeleteName = 667 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete); 668 669 auto *PointeeRD = PromiseType->getAsCXXRecordDecl(); 670 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type"); 671 672 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete)) 673 return nullptr; 674 675 if (!OperatorDelete) { 676 // Look for a global declaration. 677 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType); 678 const bool Overaligned = false; 679 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize, 680 Overaligned, DeleteName); 681 } 682 S.MarkFunctionReferenced(Loc, OperatorDelete); 683 return OperatorDelete; 684 } 685 686 namespace { 687 class SubStmtBuilder : public CoroutineBodyStmt::CtorArgs { 688 Sema &S; 689 FunctionDecl &FD; 690 FunctionScopeInfo &Fn; 691 bool IsValid; 692 SourceLocation Loc; 693 QualType RetType; 694 SmallVector<Stmt *, 4> ParamMovesVector; 695 const bool IsPromiseDependentType; 696 CXXRecordDecl *PromiseRecordDecl = nullptr; 697 698 public: 699 SubStmtBuilder(Sema &S, FunctionDecl &FD, FunctionScopeInfo &Fn, Stmt *Body) 700 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()), 701 IsPromiseDependentType( 702 !Fn.CoroutinePromise || 703 Fn.CoroutinePromise->getType()->isDependentType()) { 704 this->Body = Body; 705 if (!IsPromiseDependentType) { 706 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl(); 707 assert(PromiseRecordDecl && "Type should have already been checked"); 708 } 709 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend() && 710 makeOnException() && makeOnFallthrough() && 711 makeNewAndDeleteExpr() && makeReturnObject() && 712 makeParamMoves(); 713 } 714 715 bool isInvalid() const { return !this->IsValid; } 716 717 bool makePromiseStmt(); 718 bool makeInitialAndFinalSuspend(); 719 bool makeNewAndDeleteExpr(); 720 bool makeOnFallthrough(); 721 bool makeOnException(); 722 bool makeReturnObject(); 723 bool makeParamMoves(); 724 }; 725 } 726 727 void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) { 728 FunctionScopeInfo *Fn = getCurFunction(); 729 assert(Fn && Fn->CoroutinePromise && "not a coroutine"); 730 731 if (!Body) { 732 assert(FD->isInvalidDecl() && 733 "a null body is only allowed for invalid declarations"); 734 return; 735 } 736 737 if (isa<CoroutineBodyStmt>(Body)) { 738 // FIXME(EricWF): Nothing todo. the body is already a transformed coroutine 739 // body statement. 740 return; 741 } 742 743 // Coroutines [stmt.return]p1: 744 // A return statement shall not appear in a coroutine. 745 if (Fn->FirstReturnLoc.isValid()) { 746 assert(Fn->FirstCoroutineStmtLoc.isValid() && 747 "first coroutine location not set"); 748 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine); 749 Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) 750 << Fn->getFirstCoroutineStmtKeyword(); 751 } 752 SubStmtBuilder Builder(*this, *FD, *Fn, Body); 753 if (Builder.isInvalid()) 754 return FD->setInvalidDecl(); 755 756 // Build body for the coroutine wrapper statement. 757 Body = CoroutineBodyStmt::Create(Context, Builder); 758 } 759 760 bool SubStmtBuilder::makePromiseStmt() { 761 // Form a declaration statement for the promise declaration, so that AST 762 // visitors can more easily find it. 763 StmtResult PromiseStmt = 764 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc); 765 if (PromiseStmt.isInvalid()) 766 return false; 767 768 this->Promise = PromiseStmt.get(); 769 return true; 770 } 771 772 bool SubStmtBuilder::makeInitialAndFinalSuspend() { 773 if (Fn.hasInvalidCoroutineSuspends()) 774 return false; 775 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first); 776 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second); 777 return true; 778 } 779 780 bool SubStmtBuilder::makeNewAndDeleteExpr() { 781 // Form and check allocation and deallocation calls. 782 QualType PromiseType = Fn.CoroutinePromise->getType(); 783 if (PromiseType->isDependentType()) 784 return true; 785 786 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type)) 787 return false; 788 789 // FIXME: Add support for get_return_object_on_allocation failure. 790 // FIXME: Add support for stateful allocators. 791 792 FunctionDecl *OperatorNew = nullptr; 793 FunctionDecl *OperatorDelete = nullptr; 794 FunctionDecl *UnusedResult = nullptr; 795 bool PassAlignment = false; 796 797 S.FindAllocationFunctions(Loc, SourceRange(), 798 /*UseGlobal*/ false, PromiseType, 799 /*isArray*/ false, PassAlignment, 800 /*PlacementArgs*/ None, OperatorNew, UnusedResult); 801 802 OperatorDelete = findDeleteForPromise(S, Loc, PromiseType); 803 804 if (!OperatorDelete || !OperatorNew) 805 return false; 806 807 Expr *FramePtr = 808 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {}); 809 810 Expr *FrameSize = 811 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {}); 812 813 // Make new call. 814 815 ExprResult NewRef = 816 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc); 817 if (NewRef.isInvalid()) 818 return false; 819 820 ExprResult NewExpr = 821 S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc); 822 if (NewExpr.isInvalid()) 823 return false; 824 825 // Make delete call. 826 827 QualType OpDeleteQualType = OperatorDelete->getType(); 828 829 ExprResult DeleteRef = 830 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc); 831 if (DeleteRef.isInvalid()) 832 return false; 833 834 Expr *CoroFree = 835 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr}); 836 837 SmallVector<Expr *, 2> DeleteArgs{CoroFree}; 838 839 // Check if we need to pass the size. 840 const auto *OpDeleteType = 841 OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>(); 842 if (OpDeleteType->getNumParams() > 1) 843 DeleteArgs.push_back(FrameSize); 844 845 ExprResult DeleteExpr = 846 S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); 847 if (DeleteExpr.isInvalid()) 848 return false; 849 850 this->Allocate = NewExpr.get(); 851 this->Deallocate = DeleteExpr.get(); 852 853 return true; 854 } 855 856 bool SubStmtBuilder::makeOnFallthrough() { 857 if (!PromiseRecordDecl) 858 return true; 859 860 // [dcl.fct.def.coroutine]/4 861 // The unqualified-ids 'return_void' and 'return_value' are looked up in 862 // the scope of class P. If both are found, the program is ill-formed. 863 const bool HasRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc); 864 const bool HasRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc); 865 866 StmtResult Fallthrough; 867 if (HasRVoid && HasRValue) { 868 // FIXME Improve this diagnostic 869 S.Diag(FD.getLocation(), diag::err_coroutine_promise_return_ill_formed) 870 << PromiseRecordDecl; 871 return false; 872 } else if (HasRVoid) { 873 // If the unqualified-id return_void is found, flowing off the end of a 874 // coroutine is equivalent to a co_return with no operand. Otherwise, 875 // flowing off the end of a coroutine results in undefined behavior. 876 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr, 877 /*IsImplicit*/false); 878 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get()); 879 if (Fallthrough.isInvalid()) 880 return false; 881 } 882 883 this->OnFallthrough = Fallthrough.get(); 884 return true; 885 } 886 887 bool SubStmtBuilder::makeOnException() { 888 // Try to form 'p.unhandled_exception();' 889 890 if (!PromiseRecordDecl) 891 return true; 892 893 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions; 894 895 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) { 896 auto DiagID = 897 RequireUnhandledException 898 ? diag::err_coroutine_promise_unhandled_exception_required 899 : diag:: 900 warn_coroutine_promise_unhandled_exception_required_with_exceptions; 901 S.Diag(Loc, DiagID) << PromiseRecordDecl; 902 return !RequireUnhandledException; 903 } 904 905 // If exceptions are disabled, don't try to build OnException. 906 if (!S.getLangOpts().CXXExceptions) 907 return true; 908 909 ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, 910 "unhandled_exception", None); 911 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc); 912 if (UnhandledException.isInvalid()) 913 return false; 914 915 this->OnException = UnhandledException.get(); 916 return true; 917 } 918 919 bool SubStmtBuilder::makeReturnObject() { 920 921 // Build implicit 'p.get_return_object()' expression and form initialization 922 // of return type from it. 923 ExprResult ReturnObject = 924 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None); 925 if (ReturnObject.isInvalid()) 926 return false; 927 QualType RetType = FD.getReturnType(); 928 if (!RetType->isDependentType()) { 929 InitializedEntity Entity = 930 InitializedEntity::InitializeResult(Loc, RetType, false); 931 ReturnObject = S.PerformMoveOrCopyInitialization(Entity, nullptr, RetType, 932 ReturnObject.get()); 933 if (ReturnObject.isInvalid()) 934 return false; 935 } 936 ReturnObject = S.ActOnFinishFullExpr(ReturnObject.get(), Loc); 937 if (ReturnObject.isInvalid()) 938 return false; 939 940 this->ReturnValue = ReturnObject.get(); 941 return true; 942 } 943 944 bool SubStmtBuilder::makeParamMoves() { 945 // FIXME: Perform move-initialization of parameters into frame-local copies. 946 return true; 947 } 948 949 StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) { 950 CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args); 951 if (!Res) 952 return StmtError(); 953 return Res; 954 } 955