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 /// Look up the std::coroutine_traits<...>::promise_type for the given 25 /// function type. 26 static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, 27 SourceLocation Loc) { 28 // FIXME: Cache std::coroutine_traits once we've found it. 29 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); 30 if (!StdExp) { 31 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); 37 if (!S.LookupQualifiedName(Result, StdExp)) { 38 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))); 56 // FIXME: If the function is a non-static member function, add the type 57 // of the implicit object parameter before the formal parameters. 58 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()) { 88 // Use the fully-qualified name of the type. 89 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp); 90 NNS = NestedNameSpecifier::Create(S.Context, NNS, false, 91 CoroTrait.getTypePtr()); 92 PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType); 93 94 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 static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, 103 StringRef Keyword) { 104 // '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; 107 return false; 108 } 109 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 return false; 117 } 118 119 // An enumeration for mapping the diagnostic type to the correct diagnostic 120 // selection index. 121 enum InvalidFuncDiag { 122 DiagCtor = 0, 123 DiagDtor, 124 DiagCopyAssign, 125 DiagMoveAssign, 126 DiagMain, 127 DiagConstexpr, 128 DiagAutoRet, 129 DiagVarargs, 130 }; 131 bool Diagnosed = false; 132 auto DiagInvalid = [&](InvalidFuncDiag ID) { 133 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword; 134 Diagnosed = true; 135 return false; 136 }; 137 138 // Diagnose when a constructor, destructor, copy/move assignment operator, 139 // or the function 'main' are declared as a coroutine. 140 auto *MD = dyn_cast<CXXMethodDecl>(FD); 141 if (MD && isa<CXXConstructorDecl>(MD)) 142 return DiagInvalid(DiagCtor); 143 else if (MD && isa<CXXDestructorDecl>(MD)) 144 return DiagInvalid(DiagDtor); 145 else if (MD && MD->isCopyAssignmentOperator()) 146 return DiagInvalid(DiagCopyAssign); 147 else if (MD && MD->isMoveAssignmentOperator()) 148 return DiagInvalid(DiagMoveAssign); 149 else if (FD->isMain()) 150 return DiagInvalid(DiagMain); 151 152 // Emit a diagnostics for each of the following conditions which is not met. 153 if (FD->isConstexpr()) 154 DiagInvalid(DiagConstexpr); 155 if (FD->getReturnType()->isUndeducedType()) 156 DiagInvalid(DiagAutoRet); 157 if (FD->isVariadic()) 158 DiagInvalid(DiagVarargs); 159 160 return !Diagnosed; 161 } 162 163 /// Check that this is a context in which a coroutine suspension can appear. 164 static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc, 165 StringRef Keyword) { 166 if (!isValidCoroutineContext(S, Loc, Keyword)) 167 return nullptr; 168 169 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope"); 170 auto *FD = cast<FunctionDecl>(S.CurContext); 171 auto *ScopeInfo = S.getCurFunction(); 172 assert(ScopeInfo && "missing function scope for function"); 173 174 // If we don't have a promise variable, build one now. 175 if (!ScopeInfo->CoroutinePromise) { 176 QualType T = FD->getType()->isDependentType() 177 ? S.Context.DependentTy 178 : lookupPromiseType( 179 S, FD->getType()->castAs<FunctionProtoType>(), Loc); 180 if (T.isNull()) 181 return nullptr; 182 183 // Create and default-initialize the promise. 184 ScopeInfo->CoroutinePromise = 185 VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(), 186 &S.PP.getIdentifierTable().get("__promise"), T, 187 S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None); 188 S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise); 189 if (!ScopeInfo->CoroutinePromise->isInvalidDecl()) 190 S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise); 191 } 192 193 return ScopeInfo; 194 } 195 196 static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id, 197 MutableArrayRef<Expr *> CallArgs) { 198 StringRef Name = S.Context.BuiltinInfo.getName(Id); 199 LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName); 200 S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true); 201 202 auto *BuiltInDecl = R.getAsSingle<FunctionDecl>(); 203 assert(BuiltInDecl && "failed to find builtin declaration"); 204 205 ExprResult DeclRef = 206 S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc); 207 assert(DeclRef.isUsable() && "Builtin reference cannot fail"); 208 209 ExprResult Call = 210 S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc); 211 212 assert(!Call.isInvalid() && "Call to builtin cannot fail!"); 213 return Call.get(); 214 } 215 216 /// Build a call to 'operator co_await' if there is a suitable operator for 217 /// the given expression. 218 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, 219 SourceLocation Loc, Expr *E) { 220 UnresolvedSet<16> Functions; 221 SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(), 222 Functions); 223 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E); 224 } 225 226 struct ReadySuspendResumeResult { 227 bool IsInvalid; 228 Expr *Results[3]; 229 }; 230 231 static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, 232 StringRef Name, 233 MutableArrayRef<Expr *> Args) { 234 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc); 235 236 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&. 237 CXXScopeSpec SS; 238 ExprResult Result = S.BuildMemberReferenceExpr( 239 Base, Base->getType(), Loc, /*IsPtr=*/false, SS, 240 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr, 241 /*Scope=*/nullptr); 242 if (Result.isInvalid()) 243 return ExprError(); 244 245 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr); 246 } 247 248 /// Build calls to await_ready, await_suspend, and await_resume for a co_await 249 /// expression. 250 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc, 251 Expr *E) { 252 // Assume invalid until we see otherwise. 253 ReadySuspendResumeResult Calls = {true, {}}; 254 255 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"}; 256 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) { 257 Expr *Operand = new (S.Context) OpaqueValueExpr( 258 Loc, E->getType(), VK_LValue, E->getObjectKind(), E); 259 260 // FIXME: Pass coroutine handle to await_suspend. 261 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None); 262 if (Result.isInvalid()) 263 return Calls; 264 Calls.Results[I] = Result.get(); 265 } 266 267 Calls.IsInvalid = false; 268 return Calls; 269 } 270 271 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) { 272 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await"); 273 if (!Coroutine) { 274 CorrectDelayedTyposInExpr(E); 275 return ExprError(); 276 } 277 if (E->getType()->isPlaceholderType()) { 278 ExprResult R = CheckPlaceholderExpr(E); 279 if (R.isInvalid()) return ExprError(); 280 E = R.get(); 281 } 282 283 ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E); 284 if (Awaitable.isInvalid()) 285 return ExprError(); 286 287 return BuildCoawaitExpr(Loc, Awaitable.get()); 288 } 289 ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) { 290 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await"); 291 if (!Coroutine) 292 return ExprError(); 293 294 if (E->getType()->isPlaceholderType()) { 295 ExprResult R = CheckPlaceholderExpr(E); 296 if (R.isInvalid()) return ExprError(); 297 E = R.get(); 298 } 299 300 if (E->getType()->isDependentType()) { 301 Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E); 302 Coroutine->CoroutineStmts.push_back(Res); 303 return Res; 304 } 305 306 // If the expression is a temporary, materialize it as an lvalue so that we 307 // can use it multiple times. 308 if (E->getValueKind() == VK_RValue) 309 E = CreateMaterializeTemporaryExpr(E->getType(), E, true); 310 311 // Build the await_ready, await_suspend, await_resume calls. 312 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); 313 if (RSS.IsInvalid) 314 return ExprError(); 315 316 Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1], 317 RSS.Results[2]); 318 Coroutine->CoroutineStmts.push_back(Res); 319 return Res; 320 } 321 322 static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine, 323 SourceLocation Loc, StringRef Name, 324 MutableArrayRef<Expr *> Args) { 325 assert(Coroutine->CoroutinePromise && "no promise for coroutine"); 326 327 // Form a reference to the promise. 328 auto *Promise = Coroutine->CoroutinePromise; 329 ExprResult PromiseRef = S.BuildDeclRefExpr( 330 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc); 331 if (PromiseRef.isInvalid()) 332 return ExprError(); 333 334 // Call 'yield_value', passing in E. 335 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args); 336 } 337 338 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) { 339 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); 340 if (!Coroutine) { 341 CorrectDelayedTyposInExpr(E); 342 return ExprError(); 343 } 344 345 // Build yield_value call. 346 ExprResult Awaitable = 347 buildPromiseCall(*this, Coroutine, Loc, "yield_value", E); 348 if (Awaitable.isInvalid()) 349 return ExprError(); 350 351 // Build 'operator co_await' call. 352 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get()); 353 if (Awaitable.isInvalid()) 354 return ExprError(); 355 356 return BuildCoyieldExpr(Loc, Awaitable.get()); 357 } 358 ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { 359 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); 360 if (!Coroutine) 361 return ExprError(); 362 363 if (E->getType()->isPlaceholderType()) { 364 ExprResult R = CheckPlaceholderExpr(E); 365 if (R.isInvalid()) return ExprError(); 366 E = R.get(); 367 } 368 369 if (E->getType()->isDependentType()) { 370 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E); 371 Coroutine->CoroutineStmts.push_back(Res); 372 return Res; 373 } 374 375 // If the expression is a temporary, materialize it as an lvalue so that we 376 // can use it multiple times. 377 if (E->getValueKind() == VK_RValue) 378 E = CreateMaterializeTemporaryExpr(E->getType(), E, true); 379 380 // Build the await_ready, await_suspend, await_resume calls. 381 ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); 382 if (RSS.IsInvalid) 383 return ExprError(); 384 385 Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1], 386 RSS.Results[2]); 387 Coroutine->CoroutineStmts.push_back(Res); 388 return Res; 389 } 390 391 StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) { 392 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return"); 393 if (!Coroutine) { 394 CorrectDelayedTyposInExpr(E); 395 return StmtError(); 396 } 397 return BuildCoreturnStmt(Loc, E); 398 } 399 400 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) { 401 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return"); 402 if (!Coroutine) 403 return StmtError(); 404 405 if (E && E->getType()->isPlaceholderType() && 406 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) { 407 ExprResult R = CheckPlaceholderExpr(E); 408 if (R.isInvalid()) return StmtError(); 409 E = R.get(); 410 } 411 412 // FIXME: If the operand is a reference to a variable that's about to go out 413 // of scope, we should treat the operand as an xvalue for this overload 414 // resolution. 415 ExprResult PC; 416 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) { 417 PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E); 418 } else { 419 E = MakeFullDiscardedValueExpr(E).get(); 420 PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None); 421 } 422 if (PC.isInvalid()) 423 return StmtError(); 424 425 Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); 426 427 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE); 428 Coroutine->CoroutineStmts.push_back(Res); 429 return Res; 430 } 431 432 static ExprResult buildStdCurrentExceptionCall(Sema &S, SourceLocation Loc) { 433 NamespaceDecl *Std = S.getStdNamespace(); 434 if (!Std) { 435 S.Diag(Loc, diag::err_implied_std_current_exception_not_found); 436 return ExprError(); 437 } 438 LookupResult Result(S, &S.PP.getIdentifierTable().get("current_exception"), 439 Loc, Sema::LookupOrdinaryName); 440 if (!S.LookupQualifiedName(Result, Std)) { 441 S.Diag(Loc, diag::err_implied_std_current_exception_not_found); 442 return ExprError(); 443 } 444 445 // FIXME The STL is free to provide more than one overload. 446 FunctionDecl *FD = Result.getAsSingle<FunctionDecl>(); 447 if (!FD) { 448 S.Diag(Loc, diag::err_malformed_std_current_exception); 449 return ExprError(); 450 } 451 ExprResult Res = S.BuildDeclRefExpr(FD, FD->getType(), VK_LValue, Loc); 452 Res = S.ActOnCallExpr(/*Scope*/ nullptr, Res.get(), Loc, None, Loc); 453 if (Res.isInvalid()) { 454 S.Diag(Loc, diag::err_malformed_std_current_exception); 455 return ExprError(); 456 } 457 return Res; 458 } 459 460 // Find an appropriate delete for the promise. 461 static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc, 462 QualType PromiseType) { 463 FunctionDecl *OperatorDelete = nullptr; 464 465 DeclarationName DeleteName = 466 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete); 467 468 auto *PointeeRD = PromiseType->getAsCXXRecordDecl(); 469 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type"); 470 471 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete)) 472 return nullptr; 473 474 if (!OperatorDelete) { 475 // Look for a global declaration. 476 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType); 477 const bool Overaligned = false; 478 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize, 479 Overaligned, DeleteName); 480 } 481 S.MarkFunctionReferenced(Loc, OperatorDelete); 482 return OperatorDelete; 483 } 484 485 // Builds allocation and deallocation for the coroutine. Returns false on 486 // failure. 487 static bool buildAllocationAndDeallocation(Sema &S, SourceLocation Loc, 488 FunctionScopeInfo *Fn, 489 Expr *&Allocation, 490 Stmt *&Deallocation) { 491 TypeSourceInfo *TInfo = Fn->CoroutinePromise->getTypeSourceInfo(); 492 QualType PromiseType = TInfo->getType(); 493 if (PromiseType->isDependentType()) 494 return true; 495 496 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type)) 497 return false; 498 499 // FIXME: Add support for get_return_object_on_allocation failure. 500 // FIXME: Add support for stateful allocators. 501 502 FunctionDecl *OperatorNew = nullptr; 503 FunctionDecl *OperatorDelete = nullptr; 504 FunctionDecl *UnusedResult = nullptr; 505 bool PassAlignment = false; 506 507 S.FindAllocationFunctions(Loc, SourceRange(), 508 /*UseGlobal*/ false, PromiseType, 509 /*isArray*/ false, PassAlignment, 510 /*PlacementArgs*/ None, OperatorNew, UnusedResult); 511 512 OperatorDelete = findDeleteForPromise(S, Loc, PromiseType); 513 514 if (!OperatorDelete || !OperatorNew) 515 return false; 516 517 Expr *FramePtr = 518 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {}); 519 520 Expr *FrameSize = 521 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {}); 522 523 // Make new call. 524 525 ExprResult NewRef = 526 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc); 527 if (NewRef.isInvalid()) 528 return false; 529 530 ExprResult NewExpr = 531 S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc); 532 if (NewExpr.isInvalid()) 533 return false; 534 535 Allocation = NewExpr.get(); 536 537 // Make delete call. 538 539 QualType OpDeleteQualType = OperatorDelete->getType(); 540 541 ExprResult DeleteRef = 542 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc); 543 if (DeleteRef.isInvalid()) 544 return false; 545 546 Expr *CoroFree = 547 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr}); 548 549 SmallVector<Expr *, 2> DeleteArgs{CoroFree}; 550 551 // Check if we need to pass the size. 552 const auto *OpDeleteType = 553 OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>(); 554 if (OpDeleteType->getNumParams() > 1) 555 DeleteArgs.push_back(FrameSize); 556 557 ExprResult DeleteExpr = 558 S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); 559 if (DeleteExpr.isInvalid()) 560 return false; 561 562 Deallocation = DeleteExpr.get(); 563 564 return true; 565 } 566 567 void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) { 568 FunctionScopeInfo *Fn = getCurFunction(); 569 assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine"); 570 571 // Coroutines [stmt.return]p1: 572 // A return statement shall not appear in a coroutine. 573 if (Fn->FirstReturnLoc.isValid()) { 574 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine); 575 auto *First = Fn->CoroutineStmts[0]; 576 Diag(First->getLocStart(), diag::note_declared_coroutine_here) 577 << (isa<CoawaitExpr>(First) ? 0 : 578 isa<CoyieldExpr>(First) ? 1 : 2); 579 } 580 581 SourceLocation Loc = FD->getLocation(); 582 583 // Form a declaration statement for the promise declaration, so that AST 584 // visitors can more easily find it. 585 StmtResult PromiseStmt = 586 ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc); 587 if (PromiseStmt.isInvalid()) 588 return FD->setInvalidDecl(); 589 590 // Form and check implicit 'co_await p.initial_suspend();' statement. 591 ExprResult InitialSuspend = 592 buildPromiseCall(*this, Fn, Loc, "initial_suspend", None); 593 // FIXME: Support operator co_await here. 594 if (!InitialSuspend.isInvalid()) 595 InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get()); 596 InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get()); 597 if (InitialSuspend.isInvalid()) 598 return FD->setInvalidDecl(); 599 600 // Form and check implicit 'co_await p.final_suspend();' statement. 601 ExprResult FinalSuspend = 602 buildPromiseCall(*this, Fn, Loc, "final_suspend", None); 603 // FIXME: Support operator co_await here. 604 if (!FinalSuspend.isInvalid()) 605 FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get()); 606 FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get()); 607 if (FinalSuspend.isInvalid()) 608 return FD->setInvalidDecl(); 609 610 // Form and check allocation and deallocation calls. 611 Expr *Allocation = nullptr; 612 Stmt *Deallocation = nullptr; 613 if (!buildAllocationAndDeallocation(*this, Loc, Fn, Allocation, Deallocation)) 614 return FD->setInvalidDecl(); 615 616 // control flowing off the end of the coroutine. 617 // Also try to form 'p.set_exception(std::current_exception());' to handle 618 // uncaught exceptions. 619 ExprResult SetException; 620 StmtResult Fallthrough; 621 if (Fn->CoroutinePromise && 622 !Fn->CoroutinePromise->getType()->isDependentType()) { 623 CXXRecordDecl *RD = Fn->CoroutinePromise->getType()->getAsCXXRecordDecl(); 624 assert(RD && "Type should have already been checked"); 625 // [dcl.fct.def.coroutine]/4 626 // The unqualified-ids 'return_void' and 'return_value' are looked up in 627 // the scope of class P. If both are found, the program is ill-formed. 628 DeclarationName RVoidDN = PP.getIdentifierInfo("return_void"); 629 LookupResult RVoidResult(*this, RVoidDN, Loc, Sema::LookupMemberName); 630 const bool HasRVoid = LookupQualifiedName(RVoidResult, RD); 631 632 DeclarationName RValueDN = PP.getIdentifierInfo("return_value"); 633 LookupResult RValueResult(*this, RValueDN, Loc, Sema::LookupMemberName); 634 const bool HasRValue = LookupQualifiedName(RValueResult, RD); 635 636 if (HasRVoid && HasRValue) { 637 // FIXME Improve this diagnostic 638 Diag(FD->getLocation(), diag::err_coroutine_promise_return_ill_formed) 639 << RD; 640 return FD->setInvalidDecl(); 641 } else if (HasRVoid) { 642 // If the unqualified-id return_void is found, flowing off the end of a 643 // coroutine is equivalent to a co_return with no operand. Otherwise, 644 // flowing off the end of a coroutine results in undefined behavior. 645 Fallthrough = BuildCoreturnStmt(FD->getLocation(), nullptr); 646 Fallthrough = ActOnFinishFullStmt(Fallthrough.get()); 647 if (Fallthrough.isInvalid()) 648 return FD->setInvalidDecl(); 649 } 650 651 // [dcl.fct.def.coroutine]/3 652 // The unqualified-id set_exception is found in the scope of P by class 653 // member access lookup (3.4.5). 654 DeclarationName SetExDN = PP.getIdentifierInfo("set_exception"); 655 LookupResult SetExResult(*this, SetExDN, Loc, Sema::LookupMemberName); 656 if (LookupQualifiedName(SetExResult, RD)) { 657 // Form the call 'p.set_exception(std::current_exception())' 658 SetException = buildStdCurrentExceptionCall(*this, Loc); 659 if (SetException.isInvalid()) 660 return FD->setInvalidDecl(); 661 Expr *E = SetException.get(); 662 SetException = buildPromiseCall(*this, Fn, Loc, "set_exception", E); 663 SetException = ActOnFinishFullExpr(SetException.get(), Loc); 664 if (SetException.isInvalid()) 665 return FD->setInvalidDecl(); 666 } 667 } 668 669 // Build implicit 'p.get_return_object()' expression and form initialization 670 // of return type from it. 671 ExprResult ReturnObject = 672 buildPromiseCall(*this, Fn, Loc, "get_return_object", None); 673 if (ReturnObject.isInvalid()) 674 return FD->setInvalidDecl(); 675 QualType RetType = FD->getReturnType(); 676 if (!RetType->isDependentType()) { 677 InitializedEntity Entity = 678 InitializedEntity::InitializeResult(Loc, RetType, false); 679 ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType, 680 ReturnObject.get()); 681 if (ReturnObject.isInvalid()) 682 return FD->setInvalidDecl(); 683 } 684 ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc); 685 if (ReturnObject.isInvalid()) 686 return FD->setInvalidDecl(); 687 688 // FIXME: Perform move-initialization of parameters into frame-local copies. 689 SmallVector<Expr*, 16> ParamMoves; 690 691 // Build body for the coroutine wrapper statement. 692 Body = new (Context) CoroutineBodyStmt( 693 Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(), 694 SetException.get(), Fallthrough.get(), Allocation, Deallocation, 695 ReturnObject.get(), ParamMoves); 696 } 697