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 "CoroutineStmtBuilder.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 #include "clang/Sema/SemaInternal.h" 22 23 using namespace clang; 24 using namespace sema; 25 26 static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, 27 SourceLocation Loc) { 28 DeclarationName DN = S.PP.getIdentifierInfo(Name); 29 LookupResult LR(S, DN, Loc, Sema::LookupMemberName); 30 // Suppress diagnostics when a private member is selected. The same warnings 31 // will be produced again when building the call. 32 LR.suppressDiagnostics(); 33 return S.LookupQualifiedName(LR, RD); 34 } 35 36 /// Look up the std::coroutine_traits<...>::promise_type for the given 37 /// function type. 38 static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, 39 SourceLocation KwLoc, 40 SourceLocation FuncLoc) { 41 // FIXME: Cache std::coroutine_traits once we've found it. 42 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); 43 if (!StdExp) { 44 S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) 45 << "std::experimental::coroutine_traits"; 46 return QualType(); 47 } 48 49 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), 50 FuncLoc, Sema::LookupOrdinaryName); 51 if (!S.LookupQualifiedName(Result, StdExp)) { 52 S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) 53 << "std::experimental::coroutine_traits"; 54 return QualType(); 55 } 56 57 ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>(); 58 if (!CoroTraits) { 59 Result.suppressDiagnostics(); 60 // We found something weird. Complain about the first thing we found. 61 NamedDecl *Found = *Result.begin(); 62 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); 63 return QualType(); 64 } 65 66 // Form template argument list for coroutine_traits<R, P1, P2, ...>. 67 TemplateArgumentListInfo Args(KwLoc, KwLoc); 68 Args.addArgument(TemplateArgumentLoc( 69 TemplateArgument(FnType->getReturnType()), 70 S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), KwLoc))); 71 // FIXME: If the function is a non-static member function, add the type 72 // of the implicit object parameter before the formal parameters. 73 for (QualType T : FnType->getParamTypes()) 74 Args.addArgument(TemplateArgumentLoc( 75 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc))); 76 77 // Build the template-id. 78 QualType CoroTrait = 79 S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args); 80 if (CoroTrait.isNull()) 81 return QualType(); 82 if (S.RequireCompleteType(KwLoc, CoroTrait, 83 diag::err_coroutine_type_missing_specialization)) 84 return QualType(); 85 86 auto *RD = CoroTrait->getAsCXXRecordDecl(); 87 assert(RD && "specialization of class template is not a class?"); 88 89 // Look up the ::promise_type member. 90 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc, 91 Sema::LookupOrdinaryName); 92 S.LookupQualifiedName(R, RD); 93 auto *Promise = R.getAsSingle<TypeDecl>(); 94 if (!Promise) { 95 S.Diag(FuncLoc, 96 diag::err_implied_std_coroutine_traits_promise_type_not_found) 97 << RD; 98 return QualType(); 99 } 100 // The promise type is required to be a class type. 101 QualType PromiseType = S.Context.getTypeDeclType(Promise); 102 103 auto buildElaboratedType = [&]() { 104 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp); 105 NNS = NestedNameSpecifier::Create(S.Context, NNS, false, 106 CoroTrait.getTypePtr()); 107 return S.Context.getElaboratedType(ETK_None, NNS, PromiseType); 108 }; 109 110 if (!PromiseType->getAsCXXRecordDecl()) { 111 S.Diag(FuncLoc, 112 diag::err_implied_std_coroutine_traits_promise_type_not_class) 113 << buildElaboratedType(); 114 return QualType(); 115 } 116 if (S.RequireCompleteType(FuncLoc, buildElaboratedType(), 117 diag::err_coroutine_promise_type_incomplete)) 118 return QualType(); 119 120 return PromiseType; 121 } 122 123 /// Look up the std::experimental::coroutine_handle<PromiseType>. 124 static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, 125 SourceLocation Loc) { 126 if (PromiseType.isNull()) 127 return QualType(); 128 129 NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); 130 assert(StdExp && "Should already be diagnosed"); 131 132 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"), 133 Loc, Sema::LookupOrdinaryName); 134 if (!S.LookupQualifiedName(Result, StdExp)) { 135 S.Diag(Loc, diag::err_implied_coroutine_type_not_found) 136 << "std::experimental::coroutine_handle"; 137 return QualType(); 138 } 139 140 ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>(); 141 if (!CoroHandle) { 142 Result.suppressDiagnostics(); 143 // We found something weird. Complain about the first thing we found. 144 NamedDecl *Found = *Result.begin(); 145 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle); 146 return QualType(); 147 } 148 149 // Form template argument list for coroutine_handle<Promise>. 150 TemplateArgumentListInfo Args(Loc, Loc); 151 Args.addArgument(TemplateArgumentLoc( 152 TemplateArgument(PromiseType), 153 S.Context.getTrivialTypeSourceInfo(PromiseType, Loc))); 154 155 // Build the template-id. 156 QualType CoroHandleType = 157 S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args); 158 if (CoroHandleType.isNull()) 159 return QualType(); 160 if (S.RequireCompleteType(Loc, CoroHandleType, 161 diag::err_coroutine_type_missing_specialization)) 162 return QualType(); 163 164 return CoroHandleType; 165 } 166 167 static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, 168 StringRef Keyword) { 169 // 'co_await' and 'co_yield' are not permitted in unevaluated operands. 170 if (S.isUnevaluatedContext()) { 171 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword; 172 return false; 173 } 174 175 // Any other usage must be within a function. 176 auto *FD = dyn_cast<FunctionDecl>(S.CurContext); 177 if (!FD) { 178 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext) 179 ? diag::err_coroutine_objc_method 180 : diag::err_coroutine_outside_function) << Keyword; 181 return false; 182 } 183 184 // An enumeration for mapping the diagnostic type to the correct diagnostic 185 // selection index. 186 enum InvalidFuncDiag { 187 DiagCtor = 0, 188 DiagDtor, 189 DiagCopyAssign, 190 DiagMoveAssign, 191 DiagMain, 192 DiagConstexpr, 193 DiagAutoRet, 194 DiagVarargs, 195 }; 196 bool Diagnosed = false; 197 auto DiagInvalid = [&](InvalidFuncDiag ID) { 198 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword; 199 Diagnosed = true; 200 return false; 201 }; 202 203 // Diagnose when a constructor, destructor, copy/move assignment operator, 204 // or the function 'main' are declared as a coroutine. 205 auto *MD = dyn_cast<CXXMethodDecl>(FD); 206 if (MD && isa<CXXConstructorDecl>(MD)) 207 return DiagInvalid(DiagCtor); 208 else if (MD && isa<CXXDestructorDecl>(MD)) 209 return DiagInvalid(DiagDtor); 210 else if (MD && MD->isCopyAssignmentOperator()) 211 return DiagInvalid(DiagCopyAssign); 212 else if (MD && MD->isMoveAssignmentOperator()) 213 return DiagInvalid(DiagMoveAssign); 214 else if (FD->isMain()) 215 return DiagInvalid(DiagMain); 216 217 // Emit a diagnostics for each of the following conditions which is not met. 218 if (FD->isConstexpr()) 219 DiagInvalid(DiagConstexpr); 220 if (FD->getReturnType()->isUndeducedType()) 221 DiagInvalid(DiagAutoRet); 222 if (FD->isVariadic()) 223 DiagInvalid(DiagVarargs); 224 225 return !Diagnosed; 226 } 227 228 static ExprResult buildOperatorCoawaitLookupExpr(Sema &SemaRef, Scope *S, 229 SourceLocation Loc) { 230 DeclarationName OpName = 231 SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait); 232 LookupResult Operators(SemaRef, OpName, SourceLocation(), 233 Sema::LookupOperatorName); 234 SemaRef.LookupName(Operators, S); 235 236 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); 237 const auto &Functions = Operators.asUnresolvedSet(); 238 bool IsOverloaded = 239 Functions.size() > 1 || 240 (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); 241 Expr *CoawaitOp = UnresolvedLookupExpr::Create( 242 SemaRef.Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), 243 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded, 244 Functions.begin(), Functions.end()); 245 assert(CoawaitOp); 246 return CoawaitOp; 247 } 248 249 /// Build a call to 'operator co_await' if there is a suitable operator for 250 /// the given expression. 251 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, SourceLocation Loc, 252 Expr *E, 253 UnresolvedLookupExpr *Lookup) { 254 UnresolvedSet<16> Functions; 255 Functions.append(Lookup->decls_begin(), Lookup->decls_end()); 256 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E); 257 } 258 259 static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, 260 SourceLocation Loc, Expr *E) { 261 ExprResult R = buildOperatorCoawaitLookupExpr(SemaRef, S, Loc); 262 if (R.isInvalid()) 263 return ExprError(); 264 return buildOperatorCoawaitCall(SemaRef, Loc, E, 265 cast<UnresolvedLookupExpr>(R.get())); 266 } 267 268 static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id, 269 MultiExprArg CallArgs) { 270 StringRef Name = S.Context.BuiltinInfo.getName(Id); 271 LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName); 272 S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true); 273 274 auto *BuiltInDecl = R.getAsSingle<FunctionDecl>(); 275 assert(BuiltInDecl && "failed to find builtin declaration"); 276 277 ExprResult DeclRef = 278 S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc); 279 assert(DeclRef.isUsable() && "Builtin reference cannot fail"); 280 281 ExprResult Call = 282 S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc); 283 284 assert(!Call.isInvalid() && "Call to builtin cannot fail!"); 285 return Call.get(); 286 } 287 288 static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, 289 SourceLocation Loc) { 290 QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc); 291 if (CoroHandleType.isNull()) 292 return ExprError(); 293 294 DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType); 295 LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc, 296 Sema::LookupOrdinaryName); 297 if (!S.LookupQualifiedName(Found, LookupCtx)) { 298 S.Diag(Loc, diag::err_coroutine_handle_missing_member) 299 << "from_address"; 300 return ExprError(); 301 } 302 303 Expr *FramePtr = 304 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {}); 305 306 CXXScopeSpec SS; 307 ExprResult FromAddr = 308 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false); 309 if (FromAddr.isInvalid()) 310 return ExprError(); 311 312 return S.ActOnCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc); 313 } 314 315 struct ReadySuspendResumeResult { 316 Expr *Results[3]; 317 OpaqueValueExpr *OpaqueValue; 318 bool IsInvalid; 319 }; 320 321 static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, 322 StringRef Name, MultiExprArg Args) { 323 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc); 324 325 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&. 326 CXXScopeSpec SS; 327 ExprResult Result = S.BuildMemberReferenceExpr( 328 Base, Base->getType(), Loc, /*IsPtr=*/false, SS, 329 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr, 330 /*Scope=*/nullptr); 331 if (Result.isInvalid()) 332 return ExprError(); 333 334 return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr); 335 } 336 337 /// Build calls to await_ready, await_suspend, and await_resume for a co_await 338 /// expression. 339 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, 340 SourceLocation Loc, Expr *E) { 341 OpaqueValueExpr *Operand = new (S.Context) 342 OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E); 343 344 // Assume invalid until we see otherwise. 345 ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true}; 346 347 ExprResult CoroHandleRes = buildCoroutineHandle(S, CoroPromise->getType(), Loc); 348 if (CoroHandleRes.isInvalid()) 349 return Calls; 350 Expr *CoroHandle = CoroHandleRes.get(); 351 352 const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"}; 353 MultiExprArg Args[] = {None, CoroHandle, None}; 354 for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) { 355 ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], Args[I]); 356 if (Result.isInvalid()) 357 return Calls; 358 Calls.Results[I] = Result.get(); 359 } 360 361 Calls.IsInvalid = false; 362 return Calls; 363 } 364 365 static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, 366 SourceLocation Loc, StringRef Name, 367 MultiExprArg Args) { 368 369 // Form a reference to the promise. 370 ExprResult PromiseRef = S.BuildDeclRefExpr( 371 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc); 372 if (PromiseRef.isInvalid()) 373 return ExprError(); 374 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_suspend_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 /// Look up the std::nothrow object. 662 static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) { 663 NamespaceDecl *Std = S.getStdNamespace(); 664 assert(Std && "Should already be diagnosed"); 665 666 LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc, 667 Sema::LookupOrdinaryName); 668 if (!S.LookupQualifiedName(Result, Std)) { 669 // FIXME: <experimental/coroutine> should have been included already. 670 // If we require it to include <new> then this diagnostic is no longer 671 // needed. 672 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found); 673 return nullptr; 674 } 675 676 // FIXME: Mark the variable as ODR used. This currently does not work 677 // likely due to the scope at in which this function is called. 678 auto *VD = Result.getAsSingle<VarDecl>(); 679 if (!VD) { 680 Result.suppressDiagnostics(); 681 // We found something weird. Complain about the first thing we found. 682 NamedDecl *Found = *Result.begin(); 683 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow); 684 return nullptr; 685 } 686 687 ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc); 688 if (DR.isInvalid()) 689 return nullptr; 690 691 return DR.get(); 692 } 693 694 // Find an appropriate delete for the promise. 695 static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc, 696 QualType PromiseType) { 697 FunctionDecl *OperatorDelete = nullptr; 698 699 DeclarationName DeleteName = 700 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete); 701 702 auto *PointeeRD = PromiseType->getAsCXXRecordDecl(); 703 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type"); 704 705 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete)) 706 return nullptr; 707 708 if (!OperatorDelete) { 709 // Look for a global declaration. 710 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType); 711 const bool Overaligned = false; 712 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize, 713 Overaligned, DeleteName); 714 } 715 S.MarkFunctionReferenced(Loc, OperatorDelete); 716 return OperatorDelete; 717 } 718 719 720 void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) { 721 FunctionScopeInfo *Fn = getCurFunction(); 722 assert(Fn && Fn->isCoroutine() && "not a coroutine"); 723 if (!Body) { 724 assert(FD->isInvalidDecl() && 725 "a null body is only allowed for invalid declarations"); 726 return; 727 } 728 // We have a function that uses coroutine keywords, but we failed to build 729 // the promise type. 730 if (!Fn->CoroutinePromise) 731 return FD->setInvalidDecl(); 732 733 if (isa<CoroutineBodyStmt>(Body)) { 734 // Nothing todo. the body is already a transformed coroutine body statement. 735 return; 736 } 737 738 // Coroutines [stmt.return]p1: 739 // A return statement shall not appear in a coroutine. 740 if (Fn->FirstReturnLoc.isValid()) { 741 assert(Fn->FirstCoroutineStmtLoc.isValid() && 742 "first coroutine location not set"); 743 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine); 744 Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) 745 << Fn->getFirstCoroutineStmtKeyword(); 746 } 747 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body); 748 if (Builder.isInvalid() || !Builder.buildStatements()) 749 return FD->setInvalidDecl(); 750 751 // Build body for the coroutine wrapper statement. 752 Body = CoroutineBodyStmt::Create(Context, Builder); 753 } 754 755 CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, 756 sema::FunctionScopeInfo &Fn, 757 Stmt *Body) 758 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()), 759 IsPromiseDependentType( 760 !Fn.CoroutinePromise || 761 Fn.CoroutinePromise->getType()->isDependentType()) { 762 this->Body = Body; 763 if (!IsPromiseDependentType) { 764 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl(); 765 assert(PromiseRecordDecl && "Type should have already been checked"); 766 } 767 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend(); 768 } 769 770 bool CoroutineStmtBuilder::buildStatements() { 771 assert(this->IsValid && "coroutine already invalid"); 772 this->IsValid = makeReturnObject() && makeParamMoves(); 773 if (this->IsValid && !IsPromiseDependentType) 774 buildDependentStatements(); 775 return this->IsValid; 776 } 777 778 bool CoroutineStmtBuilder::buildDependentStatements() { 779 assert(this->IsValid && "coroutine already invalid"); 780 assert(!this->IsPromiseDependentType && 781 "coroutine cannot have a dependent promise type"); 782 this->IsValid = makeOnException() && makeOnFallthrough() && 783 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() && 784 makeNewAndDeleteExpr(); 785 return this->IsValid; 786 } 787 788 bool CoroutineStmtBuilder::makePromiseStmt() { 789 // Form a declaration statement for the promise declaration, so that AST 790 // visitors can more easily find it. 791 StmtResult PromiseStmt = 792 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc); 793 if (PromiseStmt.isInvalid()) 794 return false; 795 796 this->Promise = PromiseStmt.get(); 797 return true; 798 } 799 800 bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() { 801 if (Fn.hasInvalidCoroutineSuspends()) 802 return false; 803 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first); 804 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second); 805 return true; 806 } 807 808 static bool diagReturnOnAllocFailure(Sema &S, Expr *E, 809 CXXRecordDecl *PromiseRecordDecl, 810 FunctionScopeInfo &Fn) { 811 auto Loc = E->getExprLoc(); 812 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) { 813 auto *Decl = DeclRef->getDecl(); 814 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) { 815 if (Method->isStatic()) 816 return true; 817 else 818 Loc = Decl->getLocation(); 819 } 820 } 821 822 S.Diag( 823 Loc, 824 diag::err_coroutine_promise_get_return_object_on_allocation_failure) 825 << PromiseRecordDecl; 826 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) 827 << Fn.getFirstCoroutineStmtKeyword(); 828 return false; 829 } 830 831 bool CoroutineStmtBuilder::makeReturnOnAllocFailure() { 832 assert(!IsPromiseDependentType && 833 "cannot make statement while the promise type is dependent"); 834 835 // [dcl.fct.def.coroutine]/8 836 // The unqualified-id get_return_object_on_allocation_failure is looked up in 837 // the scope of class P by class member access lookup (3.4.5). ... 838 // If an allocation function returns nullptr, ... the coroutine return value 839 // is obtained by a call to ... get_return_object_on_allocation_failure(). 840 841 DeclarationName DN = 842 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure"); 843 LookupResult Found(S, DN, Loc, Sema::LookupMemberName); 844 if (!S.LookupQualifiedName(Found, PromiseRecordDecl)) 845 return true; 846 847 CXXScopeSpec SS; 848 ExprResult DeclNameExpr = 849 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false); 850 if (DeclNameExpr.isInvalid()) 851 return false; 852 853 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn)) 854 return false; 855 856 ExprResult ReturnObjectOnAllocationFailure = 857 S.ActOnCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc); 858 if (ReturnObjectOnAllocationFailure.isInvalid()) 859 return false; 860 861 StmtResult ReturnStmt = 862 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get()); 863 if (ReturnStmt.isInvalid()) { 864 S.Diag(Found.getFoundDecl()->getLocation(), 865 diag::note_promise_member_declared_here) 866 << DN.getAsString(); 867 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) 868 << Fn.getFirstCoroutineStmtKeyword(); 869 return false; 870 } 871 872 this->ReturnStmtOnAllocFailure = ReturnStmt.get(); 873 return true; 874 } 875 876 bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { 877 // Form and check allocation and deallocation calls. 878 assert(!IsPromiseDependentType && 879 "cannot make statement while the promise type is dependent"); 880 QualType PromiseType = Fn.CoroutinePromise->getType(); 881 882 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type)) 883 return false; 884 885 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr; 886 887 // FIXME: Add support for stateful allocators. 888 889 FunctionDecl *OperatorNew = nullptr; 890 FunctionDecl *OperatorDelete = nullptr; 891 FunctionDecl *UnusedResult = nullptr; 892 bool PassAlignment = false; 893 SmallVector<Expr *, 1> PlacementArgs; 894 895 S.FindAllocationFunctions(Loc, SourceRange(), 896 /*UseGlobal*/ false, PromiseType, 897 /*isArray*/ false, PassAlignment, PlacementArgs, 898 OperatorNew, UnusedResult); 899 900 bool IsGlobalOverload = 901 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext()); 902 // If we didn't find a class-local new declaration and non-throwing new 903 // was is required then we need to lookup the non-throwing global operator 904 // instead. 905 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) { 906 auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc); 907 if (!StdNoThrow) 908 return false; 909 PlacementArgs = {StdNoThrow}; 910 OperatorNew = nullptr; 911 S.FindAllocationFunctions(Loc, SourceRange(), 912 /*UseGlobal*/ true, PromiseType, 913 /*isArray*/ false, PassAlignment, PlacementArgs, 914 OperatorNew, UnusedResult); 915 } 916 917 assert(OperatorNew && "expected definition of operator new to be found"); 918 919 if (RequiresNoThrowAlloc) { 920 const auto *FT = OperatorNew->getType()->getAs<FunctionProtoType>(); 921 if (!FT->isNothrow(S.Context, /*ResultIfDependent*/ false)) { 922 S.Diag(OperatorNew->getLocation(), 923 diag::err_coroutine_promise_new_requires_nothrow) 924 << OperatorNew; 925 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) 926 << OperatorNew; 927 return false; 928 } 929 } 930 931 if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr) 932 return false; 933 934 Expr *FramePtr = 935 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {}); 936 937 Expr *FrameSize = 938 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {}); 939 940 // Make new call. 941 942 ExprResult NewRef = 943 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc); 944 if (NewRef.isInvalid()) 945 return false; 946 947 SmallVector<Expr *, 2> NewArgs(1, FrameSize); 948 for (auto Arg : PlacementArgs) 949 NewArgs.push_back(Arg); 950 951 ExprResult NewExpr = 952 S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); 953 NewExpr = S.ActOnFinishFullExpr(NewExpr.get()); 954 if (NewExpr.isInvalid()) 955 return false; 956 957 // Make delete call. 958 959 QualType OpDeleteQualType = OperatorDelete->getType(); 960 961 ExprResult DeleteRef = 962 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc); 963 if (DeleteRef.isInvalid()) 964 return false; 965 966 Expr *CoroFree = 967 buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr}); 968 969 SmallVector<Expr *, 2> DeleteArgs{CoroFree}; 970 971 // Check if we need to pass the size. 972 const auto *OpDeleteType = 973 OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>(); 974 if (OpDeleteType->getNumParams() > 1) 975 DeleteArgs.push_back(FrameSize); 976 977 ExprResult DeleteExpr = 978 S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); 979 DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get()); 980 if (DeleteExpr.isInvalid()) 981 return false; 982 983 this->Allocate = NewExpr.get(); 984 this->Deallocate = DeleteExpr.get(); 985 986 return true; 987 } 988 989 bool CoroutineStmtBuilder::makeOnFallthrough() { 990 assert(!IsPromiseDependentType && 991 "cannot make statement while the promise type is dependent"); 992 993 // [dcl.fct.def.coroutine]/4 994 // The unqualified-ids 'return_void' and 'return_value' are looked up in 995 // the scope of class P. If both are found, the program is ill-formed. 996 const bool HasRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc); 997 const bool HasRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc); 998 999 StmtResult Fallthrough; 1000 if (HasRVoid && HasRValue) { 1001 // FIXME Improve this diagnostic 1002 S.Diag(FD.getLocation(), diag::err_coroutine_promise_return_ill_formed) 1003 << PromiseRecordDecl; 1004 return false; 1005 } else if (HasRVoid) { 1006 // If the unqualified-id return_void is found, flowing off the end of a 1007 // coroutine is equivalent to a co_return with no operand. Otherwise, 1008 // flowing off the end of a coroutine results in undefined behavior. 1009 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr, 1010 /*IsImplicit*/false); 1011 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get()); 1012 if (Fallthrough.isInvalid()) 1013 return false; 1014 } 1015 1016 this->OnFallthrough = Fallthrough.get(); 1017 return true; 1018 } 1019 1020 bool CoroutineStmtBuilder::makeOnException() { 1021 // Try to form 'p.unhandled_exception();' 1022 assert(!IsPromiseDependentType && 1023 "cannot make statement while the promise type is dependent"); 1024 1025 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions; 1026 1027 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) { 1028 auto DiagID = 1029 RequireUnhandledException 1030 ? diag::err_coroutine_promise_unhandled_exception_required 1031 : diag:: 1032 warn_coroutine_promise_unhandled_exception_required_with_exceptions; 1033 S.Diag(Loc, DiagID) << PromiseRecordDecl; 1034 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here) 1035 << PromiseRecordDecl; 1036 return !RequireUnhandledException; 1037 } 1038 1039 // If exceptions are disabled, don't try to build OnException. 1040 if (!S.getLangOpts().CXXExceptions) 1041 return true; 1042 1043 ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, 1044 "unhandled_exception", None); 1045 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc); 1046 if (UnhandledException.isInvalid()) 1047 return false; 1048 1049 // Since the body of the coroutine will be wrapped in try-catch, it will 1050 // be incompatible with SEH __try if present in a function. 1051 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) { 1052 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions); 1053 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) 1054 << Fn.getFirstCoroutineStmtKeyword(); 1055 return false; 1056 } 1057 1058 this->OnException = UnhandledException.get(); 1059 return true; 1060 } 1061 1062 bool CoroutineStmtBuilder::makeReturnObject() { 1063 // Build implicit 'p.get_return_object()' expression and form initialization 1064 // of return type from it. 1065 ExprResult ReturnObject = 1066 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None); 1067 if (ReturnObject.isInvalid()) 1068 return false; 1069 1070 this->ReturnValue = ReturnObject.get(); 1071 return true; 1072 } 1073 1074 static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn) { 1075 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) { 1076 auto *MethodDecl = MbrRef->getMethodDecl(); 1077 S.Diag(MethodDecl->getLocation(), diag::note_promise_member_declared_here) 1078 << MethodDecl->getName(); 1079 } 1080 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) 1081 << Fn.getFirstCoroutineStmtKeyword(); 1082 } 1083 1084 bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { 1085 assert(!IsPromiseDependentType && 1086 "cannot make statement while the promise type is dependent"); 1087 assert(this->ReturnValue && "ReturnValue must be already formed"); 1088 1089 QualType const GroType = this->ReturnValue->getType(); 1090 assert(!GroType->isDependentType() && 1091 "get_return_object type must no longer be dependent"); 1092 1093 QualType const FnRetType = FD.getReturnType(); 1094 assert(!FnRetType->isDependentType() && 1095 "get_return_object type must no longer be dependent"); 1096 1097 if (FnRetType->isVoidType()) { 1098 ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc); 1099 if (Res.isInvalid()) 1100 return false; 1101 1102 this->ResultDecl = Res.get(); 1103 return true; 1104 } 1105 1106 if (GroType->isVoidType()) { 1107 // Trigger a nice error message. 1108 InitializedEntity Entity = 1109 InitializedEntity::InitializeResult(Loc, FnRetType, false); 1110 S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue); 1111 noteMemberDeclaredHere(S, ReturnValue, Fn); 1112 return false; 1113 } 1114 1115 auto *GroDecl = VarDecl::Create( 1116 S.Context, &FD, FD.getLocation(), FD.getLocation(), 1117 &S.PP.getIdentifierTable().get("__coro_gro"), GroType, 1118 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None); 1119 1120 S.CheckVariableDeclarationType(GroDecl); 1121 if (GroDecl->isInvalidDecl()) 1122 return false; 1123 1124 InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl); 1125 ExprResult Res = S.PerformMoveOrCopyInitialization(Entity, nullptr, GroType, 1126 this->ReturnValue); 1127 if (Res.isInvalid()) 1128 return false; 1129 1130 Res = S.ActOnFinishFullExpr(Res.get()); 1131 if (Res.isInvalid()) 1132 return false; 1133 1134 if (GroType == FnRetType) { 1135 GroDecl->setNRVOVariable(true); 1136 } 1137 1138 S.AddInitializerToDecl(GroDecl, Res.get(), 1139 /*DirectInit=*/false); 1140 1141 S.FinalizeDeclaration(GroDecl); 1142 1143 // Form a declaration statement for the return declaration, so that AST 1144 // visitors can more easily find it. 1145 StmtResult GroDeclStmt = 1146 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc); 1147 if (GroDeclStmt.isInvalid()) 1148 return false; 1149 1150 this->ResultDecl = GroDeclStmt.get(); 1151 1152 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc); 1153 if (declRef.isInvalid()) 1154 return false; 1155 1156 StmtResult ReturnStmt = S.BuildReturnStmt(Loc, declRef.get()); 1157 if (ReturnStmt.isInvalid()) { 1158 noteMemberDeclaredHere(S, ReturnValue, Fn); 1159 return false; 1160 } 1161 1162 this->ReturnStmt = ReturnStmt.get(); 1163 return true; 1164 } 1165 1166 // Create a static_cast\<T&&>(expr). 1167 static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) { 1168 if (T.isNull()) 1169 T = E->getType(); 1170 QualType TargetType = S.BuildReferenceType( 1171 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName()); 1172 SourceLocation ExprLoc = E->getLocStart(); 1173 TypeSourceInfo *TargetLoc = 1174 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc); 1175 1176 return S 1177 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E, 1178 SourceRange(ExprLoc, ExprLoc), E->getSourceRange()) 1179 .get(); 1180 } 1181 1182 /// \brief Build a variable declaration for move parameter. 1183 static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, 1184 StringRef Name) { 1185 DeclContext *DC = S.CurContext; 1186 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name); 1187 TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc); 1188 VarDecl *Decl = 1189 VarDecl::Create(S.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); 1190 Decl->setImplicit(); 1191 return Decl; 1192 } 1193 1194 bool CoroutineStmtBuilder::makeParamMoves() { 1195 for (auto *paramDecl : FD.parameters()) { 1196 auto Ty = paramDecl->getType(); 1197 if (Ty->isDependentType()) 1198 continue; 1199 1200 // No need to copy scalars, llvm will take care of them. 1201 if (Ty->getAsCXXRecordDecl()) { 1202 if (!paramDecl->getIdentifier()) 1203 continue; 1204 1205 ExprResult ParamRef = 1206 S.BuildDeclRefExpr(paramDecl, paramDecl->getType(), 1207 ExprValueKind::VK_LValue, Loc); // FIXME: scope? 1208 if (ParamRef.isInvalid()) 1209 return false; 1210 1211 Expr *RCast = castForMoving(S, ParamRef.get()); 1212 1213 auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName()); 1214 1215 S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true); 1216 1217 // Convert decl to a statement. 1218 StmtResult Stmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(D), Loc, Loc); 1219 if (Stmt.isInvalid()) 1220 return false; 1221 1222 ParamMovesVector.push_back(Stmt.get()); 1223 } 1224 } 1225 1226 // Convert to ArrayRef in CtorArgs structure that builder inherits from. 1227 ParamMoves = ParamMovesVector; 1228 return true; 1229 } 1230 1231 StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) { 1232 CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args); 1233 if (!Res) 1234 return StmtError(); 1235 return Res; 1236 } 1237