clang 23.0.0git
SemaCoroutine.cpp
Go to the documentation of this file.
1//===-- SemaCoroutine.cpp - Semantic Analysis for Coroutines --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for C++ Coroutines.
10//
11// This file contains references to sections of the Coroutines TS, which
12// can be found at http://wg21.link/coroutines.
13//
14//===----------------------------------------------------------------------===//
15
17#include "clang/AST/ASTLambda.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExprCXX.h"
22#include "clang/AST/StmtCXX.h"
27#include "clang/Sema/Overload.h"
29
30using namespace clang;
31using namespace sema;
32
33static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
34 SourceLocation Loc, bool &Res) {
37 // Suppress diagnostics when a private member is selected. The same warnings
38 // will be produced again when building the call.
40 Res = S.LookupQualifiedName(LR, RD);
41 return LR;
42}
43
44static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
45 SourceLocation Loc) {
46 bool Res;
47 lookupMember(S, Name, RD, Loc, Res);
48 return Res;
49}
50
51/// Look up the std::coroutine_traits<...>::promise_type for the given
52/// function type.
54 SourceLocation KwLoc) {
55 const FunctionProtoType *FnType = FD->getType()->castAs<FunctionProtoType>();
56 const SourceLocation FuncLoc = FD->getLocation();
57
58 ClassTemplateDecl *CoroTraits =
59 S.lookupCoroutineTraits(KwLoc, FuncLoc);
60 if (!CoroTraits)
61 return QualType();
62
63 // Form template argument list for coroutine_traits<R, P1, P2, ...> according
64 // to [dcl.fct.def.coroutine]3
65 TemplateArgumentListInfo Args(KwLoc, KwLoc);
66 auto AddArg = [&](QualType T) {
69 };
70 AddArg(FnType->getReturnType());
71 // If the function is a non-static member function, add the type
72 // of the implicit object parameter before the formal parameters.
73 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
74 if (MD->isImplicitObjectMemberFunction()) {
75 // [over.match.funcs]4
76 // For non-static member functions, the type of the implicit object
77 // parameter is
78 // -- "lvalue reference to cv X" for functions declared without a
79 // ref-qualifier or with the & ref-qualifier
80 // -- "rvalue reference to cv X" for functions declared with the &&
81 // ref-qualifier
82 QualType T = MD->getFunctionObjectParameterType();
83 T = FnType->getRefQualifier() == RQ_RValue
85 : S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true);
86 AddArg(T);
87 }
88 }
89 for (QualType T : FnType->getParamTypes())
90 AddArg(T);
91
92 // Build the template-id.
93 QualType CoroTrait = S.CheckTemplateIdType(
94 ElaboratedTypeKeyword::None, TemplateName(CoroTraits), KwLoc, Args,
95 /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false);
96 if (CoroTrait.isNull())
97 return QualType();
98 if (S.RequireCompleteType(KwLoc, CoroTrait,
99 diag::err_coroutine_type_missing_specialization))
100 return QualType();
101
102 auto *RD = CoroTrait->getAsCXXRecordDecl();
103 assert(RD && "specialization of class template is not a class?");
104
105 // Look up the ::promise_type member.
106 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc,
108 S.LookupQualifiedName(R, RD);
109 auto *Promise = R.getAsSingle<TypeDecl>();
110 if (!Promise) {
111 S.Diag(FuncLoc,
112 diag::err_implied_std_coroutine_traits_promise_type_not_found)
113 << RD;
114 return QualType();
115 }
116
117 NestedNameSpecifier Qualifier(CoroTrait.getTypePtr());
119 Qualifier, Promise);
120 // The promise type is required to be a class type.
121 if (!PromiseType->getAsCXXRecordDecl()) {
122 S.Diag(FuncLoc,
123 diag::err_implied_std_coroutine_traits_promise_type_not_class)
124 << PromiseType;
125 return QualType();
126 }
127 if (S.RequireCompleteType(FuncLoc, PromiseType,
128 diag::err_coroutine_promise_type_incomplete))
129 return QualType();
130
131 return PromiseType;
132}
133
134/// Look up the std::coroutine_handle<PromiseType>.
136 SourceLocation Loc) {
137 if (PromiseType.isNull())
138 return QualType();
139
140 NamespaceDecl *CoroNamespace = S.getStdNamespace();
141 assert(CoroNamespace && "Should already be diagnosed");
142
143 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
145 if (!S.LookupQualifiedName(Result, CoroNamespace)) {
146 S.Diag(Loc, diag::err_implied_coroutine_type_not_found)
147 << "std::coroutine_handle";
148 return QualType();
149 }
150
151 ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>();
152 if (!CoroHandle) {
153 Result.suppressDiagnostics();
154 // We found something weird. Complain about the first thing we found.
155 NamedDecl *Found = *Result.begin();
156 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle);
157 return QualType();
158 }
159
160 // Form template argument list for coroutine_handle<Promise>.
161 TemplateArgumentListInfo Args(Loc, Loc);
163 TemplateArgument(PromiseType),
164 S.Context.getTrivialTypeSourceInfo(PromiseType, Loc)));
165
166 // Build the template-id.
167 QualType CoroHandleType = S.CheckTemplateIdType(
168 ElaboratedTypeKeyword::None, TemplateName(CoroHandle), Loc, Args,
169 /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false);
170 if (CoroHandleType.isNull())
171 return QualType();
172 if (S.RequireCompleteType(Loc, CoroHandleType,
173 diag::err_coroutine_type_missing_specialization))
174 return QualType();
175
176 return CoroHandleType;
177}
178
180 StringRef Keyword) {
181 // [expr.await]p2 dictates that 'co_await' and 'co_yield' must be used within
182 // a function body.
183 // FIXME: This also covers [expr.await]p2: "An await-expression shall not
184 // appear in a default argument." But the diagnostic QoI here could be
185 // improved to inform the user that default arguments specifically are not
186 // allowed.
187 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
188 if (!FD) {
190 ? diag::err_coroutine_objc_method
191 : diag::err_coroutine_outside_function) << Keyword;
192 return false;
193 }
194
195 // An enumeration for mapping the diagnostic type to the correct diagnostic
196 // selection index.
197 enum InvalidFuncDiag {
198 DiagCtor = 0,
199 DiagDtor,
200 DiagMain,
201 DiagConstexpr,
202 DiagAutoRet,
203 DiagVarargs,
204 DiagConsteval,
205 };
206 bool Diagnosed = false;
207 auto DiagInvalid = [&](InvalidFuncDiag ID) {
208 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
209 Diagnosed = true;
210 return false;
211 };
212
213 // Diagnose when a constructor, destructor
214 // or the function 'main' are declared as a coroutine.
215 auto *MD = dyn_cast<CXXMethodDecl>(FD);
216 // [class.ctor]p11: "A constructor shall not be a coroutine."
217 if (MD && isa<CXXConstructorDecl>(MD))
218 return DiagInvalid(DiagCtor);
219 // [class.dtor]p17: "A destructor shall not be a coroutine."
220 else if (MD && isa<CXXDestructorDecl>(MD))
221 return DiagInvalid(DiagDtor);
222 // [basic.start.main]p3: "The function main shall not be a coroutine."
223 else if (FD->isMain())
224 return DiagInvalid(DiagMain);
225
226 // Emit a diagnostics for each of the following conditions which is not met.
227 // [expr.const]p2: "An expression e is a core constant expression unless the
228 // evaluation of e [...] would evaluate one of the following expressions:
229 // [...] an await-expression [...] a yield-expression."
230 if (FD->isConstexpr())
231 DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);
232 // [dcl.spec.auto]p15: "A function declared with a return type that uses a
233 // placeholder type shall not be a coroutine."
234 if (FD->getReturnType()->isUndeducedType())
235 DiagInvalid(DiagAutoRet);
236 // [dcl.fct.def.coroutine]p1
237 // The parameter-declaration-clause of the coroutine shall not terminate with
238 // an ellipsis that is not part of a parameter-declaration.
239 if (FD->isVariadic())
240 DiagInvalid(DiagVarargs);
241
242 return !Diagnosed;
243}
244
245/// Build a call to 'operator co_await' if there is a suitable operator for
246/// the given expression.
248 UnresolvedLookupExpr *Lookup) {
249 UnresolvedSet<16> Functions;
250 Functions.append(Lookup->decls_begin(), Lookup->decls_end());
251 return CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
252}
253
255 SourceLocation Loc, Expr *E) {
256 ExprResult R = SemaRef.BuildOperatorCoawaitLookupExpr(S, Loc);
257 if (R.isInvalid())
258 return ExprError();
259 return SemaRef.BuildOperatorCoawaitCall(Loc, E,
261}
262
264 SourceLocation Loc) {
265 QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
266 if (CoroHandleType.isNull())
267 return ExprError();
268
269 DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType);
270 LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc,
272 if (!S.LookupQualifiedName(Found, LookupCtx)) {
273 S.Diag(Loc, diag::err_coroutine_handle_missing_member)
274 << "from_address";
275 return ExprError();
276 }
277
278 Expr *FramePtr =
279 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
280
281 CXXScopeSpec SS;
282 ExprResult FromAddr =
283 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
284 if (FromAddr.isInvalid())
285 return ExprError();
286
287 return S.BuildCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc);
288}
289
296
298 StringRef Name, MultiExprArg Args) {
299 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
300
301 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
302 CXXScopeSpec SS;
304 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
305 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
306 /*Scope=*/nullptr);
307 if (Result.isInvalid())
308 return ExprError();
309
310 auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
311 return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
312}
313
314// See if return type is coroutine-handle and if so, invoke builtin coro-resume
315// on its address. This is to enable the support for coroutine-handle
316// returning await_suspend that results in a guaranteed tail call to the target
317// coroutine.
318static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
319 SourceLocation Loc) {
320 if (RetType->isReferenceType())
321 return nullptr;
322 Type const *T = RetType.getTypePtr();
323 if (!T->isClassType() && !T->isStructureType())
324 return nullptr;
325
326 // FIXME: Add convertability check to coroutine_handle<>. Possibly via
327 // EvaluateBinaryTypeTrait(BTT_IsConvertible, ...) which is at the moment
328 // a private function in SemaExprCXX.cpp
329
330 ExprResult AddressExpr = buildMemberCall(S, E, Loc, "address", {});
331 if (AddressExpr.isInvalid())
332 return nullptr;
333
334 Expr *JustAddress = AddressExpr.get();
335
336 // Check that the type of AddressExpr is void*
337 if (!JustAddress->getType().getTypePtr()->isVoidPointerType())
338 S.Diag(cast<CallExpr>(JustAddress)->getCalleeDecl()->getLocation(),
339 diag::warn_coroutine_handle_address_invalid_return_type)
340 << JustAddress->getType();
341
342 // Clean up temporary objects, because the resulting expression
343 // will become the body of await_suspend wrapper.
344 return S.MaybeCreateExprWithCleanups(JustAddress);
345}
346
347/// Build calls to await_ready, await_suspend, and await_resume for a co_await
348/// expression.
349/// The generated AST tries to clean up temporary objects as early as
350/// possible so that they don't live across suspension points if possible.
351/// Having temporary objects living across suspension points unnecessarily can
352/// lead to large frame size, and also lead to memory corruptions if the
353/// coroutine frame is destroyed after coming back from suspension. This is done
354/// by wrapping both the await_ready call and the await_suspend call with
355/// ExprWithCleanups. In the end of this function, we also need to explicitly
356/// set cleanup state so that the CoawaitExpr is also wrapped with an
357/// ExprWithCleanups to clean up the awaiter associated with the co_await
358/// expression.
360 SourceLocation Loc, Expr *E) {
361 OpaqueValueExpr *Operand = new (S.Context)
362 OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
363
364 // Assume valid until we see otherwise.
365 // Further operations are responsible for setting IsInalid to true.
366 ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/false};
367
369
370 auto BuildSubExpr = [&](ACT CallType, StringRef Func,
371 MultiExprArg Arg) -> Expr * {
372 ExprResult Result = buildMemberCall(S, Operand, Loc, Func, Arg);
373 if (Result.isInvalid()) {
374 Calls.IsInvalid = true;
375 return nullptr;
376 }
377 Calls.Results[CallType] = Result.get();
378 return Result.get();
379 };
380
381 CallExpr *AwaitReady =
382 cast_or_null<CallExpr>(BuildSubExpr(ACT::ACT_Ready, "await_ready", {}));
383 if (!AwaitReady)
384 return Calls;
385 if (!AwaitReady->getType()->isDependentType()) {
386 // [expr.await]p3 [...]
387 // — await-ready is the expression e.await_ready(), contextually converted
388 // to bool.
389 ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady);
390 if (Conv.isInvalid()) {
391 S.Diag(AwaitReady->getDirectCallee()->getBeginLoc(),
392 diag::note_await_ready_no_bool_conversion);
393 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
394 << AwaitReady->getDirectCallee() << E->getSourceRange();
395 Calls.IsInvalid = true;
396 } else
397 Calls.Results[ACT::ACT_Ready] = S.MaybeCreateExprWithCleanups(Conv.get());
398 }
399
400 ExprResult CoroHandleRes =
401 buildCoroutineHandle(S, CoroPromise->getType(), Loc);
402 if (CoroHandleRes.isInvalid()) {
403 Calls.IsInvalid = true;
404 return Calls;
405 }
406 Expr *CoroHandle = CoroHandleRes.get();
407 CallExpr *AwaitSuspend = cast_or_null<CallExpr>(
408 BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
409 if (!AwaitSuspend)
410 return Calls;
411 if (!AwaitSuspend->getType()->isDependentType()) {
412 // [expr.await]p3 [...]
413 // - await-suspend is the expression e.await_suspend(h), which shall be
414 // a prvalue of type void, bool, or std::coroutine_handle<Z> for some
415 // type Z.
416 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
417
418 // Support for coroutine_handle returning await_suspend.
419 if (Expr *TailCallSuspend =
420 maybeTailCall(S, RetType, AwaitSuspend, Loc))
421 // Note that we don't wrap the expression with ExprWithCleanups here
422 // because that might interfere with tailcall contract (e.g. inserting
423 // clean up instructions in-between tailcall and return). Instead
424 // ExprWithCleanups is wrapped within maybeTailCall() prior to the resume
425 // call.
426 Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
427 else {
428 // non-class prvalues always have cv-unqualified types
429 if (RetType->isReferenceType() ||
430 (!RetType->isBooleanType() && !RetType->isVoidType())) {
431 S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
432 diag::err_await_suspend_invalid_return_type)
433 << RetType;
434 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
435 << AwaitSuspend->getDirectCallee();
436 Calls.IsInvalid = true;
437 } else
438 Calls.Results[ACT::ACT_Suspend] =
439 S.MaybeCreateExprWithCleanups(AwaitSuspend);
440 }
441 }
442
443 BuildSubExpr(ACT::ACT_Resume, "await_resume", {});
444
445 // Make sure the awaiter object gets a chance to be cleaned up.
447
448 return Calls;
449}
450
452 SourceLocation Loc, StringRef Name,
453 MultiExprArg Args) {
454
455 // Form a reference to the promise.
456 ExprResult PromiseRef = S.BuildDeclRefExpr(
457 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
458 if (PromiseRef.isInvalid())
459 return ExprError();
460
461 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
462}
463
465 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
466 auto *FD = cast<FunctionDecl>(CurContext);
467 bool IsThisDependentType = [&] {
468 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD))
469 return MD->isImplicitObjectMemberFunction() &&
470 MD->getThisType()->isDependentType();
471 return false;
472 }();
473
474 QualType T = FD->getType()->isDependentType() || IsThisDependentType
475 ? Context.DependentTy
476 : lookupPromiseType(*this, FD, Loc);
477 if (T.isNull())
478 return nullptr;
479
480 auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
481 &PP.getIdentifierTable().get("__promise"), T,
482 Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
483 VD->setImplicit();
485 if (VD->isInvalidDecl())
486 return nullptr;
487
488 auto *ScopeInfo = getCurFunction();
489
490 // Build a list of arguments, based on the coroutine function's arguments,
491 // that if present will be passed to the promise type's constructor.
492 llvm::SmallVector<Expr *, 4> CtorArgExprs;
493
494 // Add implicit object parameter.
495 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
496 if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
497 ExprResult ThisExpr = ActOnCXXThis(Loc);
498 if (ThisExpr.isInvalid())
499 return nullptr;
500 ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
501 if (ThisExpr.isInvalid())
502 return nullptr;
503 CtorArgExprs.push_back(ThisExpr.get());
504 }
505 }
506
507 // Add the coroutine function's parameters.
508 auto &Moves = ScopeInfo->CoroutineParameterMoves;
509 for (auto *PD : FD->parameters()) {
510 if (PD->getType()->isDependentType())
511 continue;
512
513 auto RefExpr = ExprEmpty();
514 auto Move = Moves.find(PD);
515 assert(Move != Moves.end() &&
516 "Coroutine function parameter not inserted into move map");
517 // If a reference to the function parameter exists in the coroutine
518 // frame, use that reference.
519 auto *MoveDecl =
520 cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
521 RefExpr =
522 BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
523 ExprValueKind::VK_LValue, FD->getLocation());
524 if (RefExpr.isInvalid())
525 return nullptr;
526 CtorArgExprs.push_back(RefExpr.get());
527 }
528
529 // If we have a non-zero number of constructor arguments, try to use them.
530 // Otherwise, fall back to the promise type's default constructor.
531 if (!CtorArgExprs.empty()) {
532 // Create an initialization sequence for the promise type using the
533 // constructor arguments, wrapped in a parenthesized list expression.
534 Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(),
535 CtorArgExprs, FD->getLocation());
538 VD->getLocation(), /*DirectInit=*/true, PLE);
539 InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
540 /*TopLevelOfInitList=*/false,
541 /*TreatUnavailableAsInvalid=*/false);
542
543 // [dcl.fct.def.coroutine]5.7
544 // promise-constructor-arguments is determined as follows: overload
545 // resolution is performed on a promise constructor call created by
546 // assembling an argument list q_1 ... q_n . If a viable constructor is
547 // found ([over.match.viable]), then promise-constructor-arguments is ( q_1
548 // , ..., q_n ), otherwise promise-constructor-arguments is empty.
549 if (InitSeq) {
550 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
551 if (Result.isInvalid()) {
552 VD->setInvalidDecl();
553 } else if (Result.get()) {
554 VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
555 VD->setInitStyle(VarDecl::CallInit);
557 }
558 } else
560 } else
562
563 FD->addDecl(VD);
564 return VD;
565}
566
567/// Check that this is a context in which a coroutine suspension can appear.
569 StringRef Keyword,
570 bool IsImplicit = false) {
571 if (!isValidCoroutineContext(S, Loc, Keyword))
572 return nullptr;
573
574 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
575
576 auto *ScopeInfo = S.getCurFunction();
577 assert(ScopeInfo && "missing function scope for function");
578
579 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
580 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
581
582 if (ScopeInfo->CoroutinePromise)
583 return ScopeInfo;
584
586 return nullptr;
587
588 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
589 if (!ScopeInfo->CoroutinePromise)
590 return nullptr;
591
592 return ScopeInfo;
593}
594
595/// Recursively check \p E and all its children to see if any call target
596/// (including constructor call) is declared noexcept. Also any value returned
597/// from the call has a noexcept destructor.
598static void checkNoThrow(Sema &S, const Stmt *E,
599 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {
600 auto checkDeclNoexcept = [&](const Decl *D, bool IsDtor = false) {
601 // In the case of dtor, the call to dtor is implicit and hence we should
602 // pass nullptr to canCalleeThrow.
603 if (Sema::canCalleeThrow(S, IsDtor ? nullptr : cast<Expr>(E), D)) {
604 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
605 // co_await promise.final_suspend() could end up calling
606 // __builtin_coro_resume for symmetric transfer if await_suspend()
607 // returns a handle. In that case, even __builtin_coro_resume is not
608 // declared as noexcept and may throw, it does not throw _into_ the
609 // coroutine that just suspended, but rather throws back out from
610 // whoever called coroutine_handle::resume(), hence we claim that
611 // logically it does not throw.
612 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)
613 return;
614 }
615 if (ThrowingDecls.empty()) {
616 // [dcl.fct.def.coroutine]p15
617 // The expression co_await promise.final_suspend() shall not be
618 // potentially-throwing ([except.spec]).
619 //
620 // First time seeing an error, emit the error message.
621 S.Diag(cast<FunctionDecl>(S.CurContext)->getLocation(),
622 diag::err_coroutine_promise_final_suspend_requires_nothrow);
623 }
624 ThrowingDecls.insert(D);
625 }
626 };
627
628 if (auto *CE = dyn_cast<CXXConstructExpr>(E)) {
629 CXXConstructorDecl *Ctor = CE->getConstructor();
630 checkDeclNoexcept(Ctor);
631 // Check the corresponding destructor of the constructor.
632 checkDeclNoexcept(Ctor->getParent()->getDestructor(), /*IsDtor=*/true);
633 } else if (auto *CE = dyn_cast<CallExpr>(E)) {
634 if (CE->isTypeDependent())
635 return;
636
637 checkDeclNoexcept(CE->getCalleeDecl());
638 QualType ReturnType = CE->getCallReturnType(S.getASTContext());
639 // Check the destructor of the call return type, if any.
640 if (ReturnType.isDestructedType() ==
642 const auto *T =
644 checkDeclNoexcept(
645 cast<CXXRecordDecl>(T->getDecl())->getDefinition()->getDestructor(),
646 /*IsDtor=*/true);
647 }
648 } else
649 for (const auto *Child : E->children()) {
650 if (!Child)
651 continue;
652 checkNoThrow(S, Child, ThrowingDecls);
653 }
654}
655
656bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
658 // We first collect all declarations that should not throw but not declared
659 // with noexcept. We then sort them based on the location before printing.
660 // This is to avoid emitting the same note multiple times on the same
661 // declaration, and also provide a deterministic order for the messages.
662 checkNoThrow(*this, FinalSuspend, ThrowingDecls);
663 auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(),
664 ThrowingDecls.end()};
665 sort(SortedDecls, [](const Decl *A, const Decl *B) {
666 return A->getEndLoc() < B->getEndLoc();
667 });
668 for (const auto *D : SortedDecls) {
669 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
670 }
671 return ThrowingDecls.empty();
672}
673
674// [stmt.return.coroutine]p1:
675// A coroutine shall not enclose a return statement ([stmt.return]).
677 assert(FSI && "FunctionScopeInfo is null");
678 assert(FSI->FirstCoroutineStmtLoc.isValid() &&
679 "first coroutine location not set");
680 if (FSI->FirstReturnLoc.isInvalid())
681 return;
682 S.Diag(FSI->FirstReturnLoc, diag::err_return_in_coroutine);
683 S.Diag(FSI->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
685}
686
688 StringRef Keyword) {
689 // Ignore previous expr evaluation contexts.
692 dyn_cast_or_null<FunctionDecl>(CurContext));
693
694 if (!checkCoroutineContext(*this, KWLoc, Keyword))
695 return false;
696 auto *ScopeInfo = getCurFunction();
697 assert(ScopeInfo->CoroutinePromise);
698
699 // Avoid duplicate errors, report only on first keyword.
700 if (ScopeInfo->FirstCoroutineStmtLoc == KWLoc)
701 checkReturnStmtInCoroutine(*this, ScopeInfo);
702
703 // If we have existing coroutine statements then we have already built
704 // the initial and final suspend points.
705 if (!ScopeInfo->NeedsCoroutineSuspends)
706 return true;
707
708 ScopeInfo->setNeedsCoroutineSuspends(false);
709
710 auto *Fn = cast<FunctionDecl>(CurContext);
711 SourceLocation Loc = Fn->getLocation();
712 // Build the initial suspend point
713 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
714 ExprResult Operand =
715 buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, {});
716 if (Operand.isInvalid())
717 return StmtError();
718 ExprResult Suspend =
719 buildOperatorCoawaitCall(*this, SC, Loc, Operand.get());
720 if (Suspend.isInvalid())
721 return StmtError();
722 Suspend = BuildResolvedCoawaitExpr(Loc, Operand.get(), Suspend.get(),
723 /*IsImplicit*/ true);
724 Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
725 if (Suspend.isInvalid()) {
726 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
727 << ((Name == "initial_suspend") ? 0 : 1);
728 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
729 return StmtError();
730 }
731 return cast<Stmt>(Suspend.get());
732 };
733
734 StmtResult InitSuspend = buildSuspends("initial_suspend");
735 if (InitSuspend.isInvalid())
736 return true;
737
738 StmtResult FinalSuspend = buildSuspends("final_suspend");
739 if (FinalSuspend.isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.get()))
740 return true;
741
742 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
743
744 return true;
745}
746
747// Recursively walks up the scope hierarchy until either a 'catch' or a function
748// scope is found, whichever comes first.
749static bool isWithinCatchScope(Scope *S) {
750 // 'co_await' and 'co_yield' keywords are disallowed within catch blocks, but
751 // lambdas that use 'co_await' are allowed. The loop below ends when a
752 // function scope is found in order to ensure the following behavior:
753 //
754 // void foo() { // <- function scope
755 // try { //
756 // co_await x; // <- 'co_await' is OK within a function scope
757 // } catch { // <- catch scope
758 // co_await x; // <- 'co_await' is not OK within a catch scope
759 // []() { // <- function scope
760 // co_await x; // <- 'co_await' is OK within a function scope
761 // }();
762 // }
763 // }
764 while (S && !S->isFunctionScope()) {
765 if (S->isCatchScope())
766 return true;
767 S = S->getParent();
768 }
769 return false;
770}
771
772// [expr.await]p2, emphasis added: "An await-expression shall appear only in
773// a *potentially evaluated* expression within the compound-statement of a
774// function-body *outside of a handler* [...] A context within a function
775// where an await-expression can appear is called a suspension context of the
776// function."
778 StringRef Keyword) {
779 // First emphasis of [expr.await]p2: must be a potentially evaluated context.
780 // That is, 'co_await' and 'co_yield' cannot appear in subexpressions of
781 // \c sizeof.
782 const auto ExprContext = S.currentEvaluationContext().ExprContext;
783 const bool BadContext =
787 if (BadContext) {
788 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
789 return false;
790 }
791
792 // Second emphasis of [expr.await]p2: must be outside of an exception handler.
794 S.Diag(Loc, diag::err_coroutine_within_handler) << Keyword;
795 return false;
796 }
797 return true;
798}
799
801 if (!checkSuspensionContext(*this, Loc, "co_await"))
802 return ExprError();
803
804 if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
805 return ExprError();
806 }
807
808 if (E->hasPlaceholderType()) {
810 if (R.isInvalid()) return ExprError();
811 E = R.get();
812 }
813
815 if (Lookup.isInvalid())
816 return ExprError();
817 return BuildUnresolvedCoawaitExpr(Loc, E,
819}
820
822 DeclarationName OpName =
823 Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
824 LookupResult Operators(*this, OpName, SourceLocation(),
826 LookupName(Operators, S);
827
828 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
829 const auto &Functions = Operators.asUnresolvedSet();
831 Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
832 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(),
833 Functions.end(), /*KnownDependent=*/false,
834 /*KnownInstantiationDependent=*/false);
835 assert(CoawaitOp);
836 return CoawaitOp;
837}
838
840 auto *Record = QT->getAsCXXRecordDecl();
841 return Record && Record->hasAttr<CoroAwaitElidableAttr>();
842}
843
844static void applySafeElideContext(Expr *Operand) {
845 // Strip both implicit nodes and parentheses to find the underlying CallExpr.
846 // The AST may have these in either order, so we apply both transformations
847 // iteratively until reaching a fixed point.
848 auto *Call = dyn_cast<CallExpr>(IgnoreExprNodes(
850 if (!Call || !Call->isPRValue())
851 return;
852
853 if (!isAttributedCoroAwaitElidable(Call->getType()))
854 return;
855
856 Call->setCoroElideSafe();
857
858 // Check parameter
859 auto *Fn = llvm::dyn_cast_if_present<FunctionDecl>(Call->getCalleeDecl());
860 if (!Fn)
861 return;
862
863 size_t ParmIdx = 0;
864 for (ParmVarDecl *PD : Fn->parameters()) {
865 if (PD->hasAttr<CoroAwaitElidableArgumentAttr>())
866 applySafeElideContext(Call->getArg(ParmIdx));
867
868 ParmIdx++;
869 }
870}
871
872// Attempts to resolve and build a CoawaitExpr from "raw" inputs, bailing out to
873// DependentCoawaitExpr if needed.
875 UnresolvedLookupExpr *Lookup) {
876 auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
877 if (!FSI)
878 return ExprError();
879
880 if (Operand->hasPlaceholderType()) {
881 ExprResult R = CheckPlaceholderExpr(Operand);
882 if (R.isInvalid())
883 return ExprError();
884 Operand = R.get();
885 }
886
887 auto *Promise = FSI->CoroutinePromise;
888 if (Promise->getType()->isDependentType()) {
889 Expr *Res = new (Context)
890 DependentCoawaitExpr(Loc, Context.DependentTy, Operand, Lookup);
891 return Res;
892 }
893
894 auto *RD = Promise->getType()->getAsCXXRecordDecl();
895
896 bool CurFnAwaitElidable = isAttributedCoroAwaitElidable(
897 getCurFunctionDecl(/*AllowLambda=*/true)->getReturnType());
898
899 if (CurFnAwaitElidable)
900 applySafeElideContext(Operand);
901
902 Expr *Transformed = Operand;
903 if (lookupMember(*this, "await_transform", RD, Loc)) {
904 ExprResult R =
905 buildPromiseCall(*this, Promise, Loc, "await_transform", Operand);
906 if (R.isInvalid()) {
907 Diag(Loc,
908 diag::note_coroutine_promise_implicit_await_transform_required_here)
909 << Operand->getSourceRange();
910 return ExprError();
911 }
912 Transformed = R.get();
913 }
914 ExprResult Awaiter = BuildOperatorCoawaitCall(Loc, Transformed, Lookup);
915 if (Awaiter.isInvalid())
916 return ExprError();
917
918 return BuildResolvedCoawaitExpr(Loc, Operand, Awaiter.get());
919}
920
922 Expr *Awaiter, bool IsImplicit) {
923 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
924 if (!Coroutine)
925 return ExprError();
926
927 if (Awaiter->hasPlaceholderType()) {
928 ExprResult R = CheckPlaceholderExpr(Awaiter);
929 if (R.isInvalid()) return ExprError();
930 Awaiter = R.get();
931 }
932
933 if (Awaiter->getType()->isDependentType()) {
934 Expr *Res = new (Context)
935 CoawaitExpr(Loc, Context.DependentTy, Operand, Awaiter, IsImplicit);
936 return Res;
937 }
938
939 // If the expression is a temporary, materialize it as an lvalue so that we
940 // can use it multiple times.
941 if (Awaiter->isPRValue())
942 Awaiter = CreateMaterializeTemporaryExpr(Awaiter->getType(), Awaiter, true);
943
944 // The location of the `co_await` token cannot be used when constructing
945 // the member call expressions since it's before the location of `Expr`, which
946 // is used as the start of the member call expression.
947 SourceLocation CallLoc = Awaiter->getExprLoc();
948
949 // Build the await_ready, await_suspend, await_resume calls.
951 buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, Awaiter);
952 if (RSS.IsInvalid)
953 return ExprError();
954
955 Expr *Res = new (Context)
956 CoawaitExpr(Loc, Operand, Awaiter, RSS.Results[0], RSS.Results[1],
957 RSS.Results[2], RSS.OpaqueValue, IsImplicit);
958
959 return Res;
960}
961
963 if (!checkSuspensionContext(*this, Loc, "co_yield"))
964 return ExprError();
965
966 if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
967 return ExprError();
968 }
969
970 // Build yield_value call.
971 ExprResult Awaitable = buildPromiseCall(
972 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
973 if (Awaitable.isInvalid())
974 return ExprError();
975
976 // Build 'operator co_await' call.
977 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
978 if (Awaitable.isInvalid())
979 return ExprError();
980
981 return BuildCoyieldExpr(Loc, Awaitable.get());
982}
984 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
985 if (!Coroutine)
986 return ExprError();
987
988 if (E->hasPlaceholderType()) {
990 if (R.isInvalid()) return ExprError();
991 E = R.get();
992 }
993
994 Expr *Operand = E;
995
996 if (E->getType()->isDependentType()) {
997 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, Operand, E);
998 return Res;
999 }
1000
1001 // If the expression is a temporary, materialize it as an lvalue so that we
1002 // can use it multiple times.
1003 if (E->isPRValue())
1004 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
1005
1006 // Build the await_ready, await_suspend, await_resume calls.
1008 *this, Coroutine->CoroutinePromise, Loc, E);
1009 if (RSS.IsInvalid)
1010 return ExprError();
1011
1012 Expr *Res =
1013 new (Context) CoyieldExpr(Loc, Operand, E, RSS.Results[0], RSS.Results[1],
1014 RSS.Results[2], RSS.OpaqueValue);
1015
1016 return Res;
1017}
1018
1020 if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
1021 return StmtError();
1022 }
1023 return BuildCoreturnStmt(Loc, E);
1024}
1025
1027 bool IsImplicit) {
1028 auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
1029 if (!FSI)
1030 return StmtError();
1031
1032 if (E && E->hasPlaceholderType() &&
1033 !E->hasPlaceholderType(BuiltinType::Overload)) {
1035 if (R.isInvalid()) return StmtError();
1036 E = R.get();
1037 }
1038
1039 VarDecl *Promise = FSI->CoroutinePromise;
1040 ExprResult PC;
1041 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
1043 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
1044 } else {
1046 PC = buildPromiseCall(*this, Promise, Loc, "return_void", {});
1047 }
1048 if (PC.isInvalid())
1049 return StmtError();
1050
1051 Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
1052
1053 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
1054 return Res;
1055}
1056
1057/// Look up the std::nothrow object.
1059 NamespaceDecl *Std = S.getStdNamespace();
1060 assert(Std && "Should already be diagnosed");
1061
1062 LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc,
1064 if (!S.LookupQualifiedName(Result, Std)) {
1065 // <coroutine> is not requred to include <new>, so we couldn't omit
1066 // the check here.
1067 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
1068 return nullptr;
1069 }
1070
1071 auto *VD = Result.getAsSingle<VarDecl>();
1072 if (!VD) {
1073 Result.suppressDiagnostics();
1074 // We found something weird. Complain about the first thing we found.
1075 NamedDecl *Found = *Result.begin();
1076 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);
1077 return nullptr;
1078 }
1079
1080 ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc);
1081 if (DR.isInvalid())
1082 return nullptr;
1083
1084 return DR.get();
1085}
1086
1088 SourceLocation Loc) {
1089 EnumDecl *StdAlignValDecl = S.getStdAlignValT();
1090 CanQualType StdAlignValT = S.Context.getCanonicalTagType(StdAlignValDecl);
1091 return S.Context.getTrivialTypeSourceInfo(StdAlignValT);
1092}
1093
1094// When searching for custom allocators on the PromiseType we want to
1095// warn that we will ignore type aware allocators.
1097 unsigned DiagnosticID,
1098 DeclarationName Name,
1099 QualType PromiseType) {
1100 assert(PromiseType->isRecordType());
1101
1102 LookupResult R(S, Name, Loc, Sema::LookupOrdinaryName);
1103 S.LookupQualifiedName(R, PromiseType->getAsCXXRecordDecl());
1104 bool HaveIssuedWarning = false;
1105 for (auto Decl : R) {
1106 if (!Decl->getUnderlyingDecl()
1107 ->getAsFunction()
1109 continue;
1110 if (!HaveIssuedWarning) {
1111 S.Diag(Loc, DiagnosticID) << Name;
1112 HaveIssuedWarning = true;
1113 }
1114 S.Diag(Decl->getLocation(), diag::note_type_aware_operator_declared)
1115 << /* isTypeAware=*/1 << Decl << Decl->getDeclContext();
1116 }
1118 return HaveIssuedWarning;
1119}
1120
1121// Find an appropriate delete for the promise.
1122static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType,
1123 FunctionDecl *&OperatorDelete) {
1124 DeclarationName DeleteName =
1127 diag::warn_coroutine_type_aware_allocator_ignored,
1128 DeleteName, PromiseType);
1129 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
1130 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
1131
1132 const bool Overaligned = S.getLangOpts().CoroAlignedAllocation;
1133
1134 // [dcl.fct.def.coroutine]p12
1135 // The deallocation function's name is looked up by searching for it in the
1136 // scope of the promise type. If nothing is found, a search is performed in
1137 // the global scope.
1140 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete,
1141 IDP, /*Diagnose=*/true))
1142 return false;
1143
1144 // [dcl.fct.def.coroutine]p12
1145 // If both a usual deallocation function with only a pointer parameter and a
1146 // usual deallocation function with both a pointer parameter and a size
1147 // parameter are found, then the selected deallocation function shall be the
1148 // one with two parameters. Otherwise, the selected deallocation function
1149 // shall be the function with one parameter.
1150 if (!OperatorDelete) {
1151 // Look for a global declaration.
1152 // Sema::FindUsualDeallocationFunction will try to find the one with two
1153 // parameters first. It will return the deallocation function with one
1154 // parameter if failed.
1155 // Coroutines can always provide their required size.
1157 OperatorDelete = S.FindUsualDeallocationFunction(Loc, IDP, DeleteName);
1158
1159 if (!OperatorDelete)
1160 return false;
1161 }
1162
1163 assert(!OperatorDelete->isTypeAwareOperatorNewOrDelete());
1164 S.MarkFunctionReferenced(Loc, OperatorDelete);
1165 return true;
1166}
1167
1168
1171 assert(Fn && Fn->isCoroutine() && "not a coroutine");
1172 if (!Body) {
1173 assert(FD->isInvalidDecl() &&
1174 "a null body is only allowed for invalid declarations");
1175 return;
1176 }
1177 // We have a function that uses coroutine keywords, but we failed to build
1178 // the promise type.
1179 if (!Fn->CoroutinePromise)
1180 return FD->setInvalidDecl();
1181
1182 if (isa<CoroutineBodyStmt>(Body)) {
1183 // Nothing todo. the body is already a transformed coroutine body statement.
1184 return;
1185 }
1186
1187 // The always_inline attribute doesn't reliably apply to a coroutine,
1188 // because the coroutine will be split into pieces and some pieces
1189 // might be called indirectly, as in a virtual call. Even the ramp
1190 // function cannot be inlined at -O0, due to pipeline ordering
1191 // problems (see https://llvm.org/PR53413). Tell the user about it.
1192 if (FD->hasAttr<AlwaysInlineAttr>())
1193 Diag(FD->getLocation(), diag::warn_always_inline_coroutine);
1194
1195 // The design of coroutines means we cannot allow use of VLAs within one, so
1196 // diagnose if we've seen a VLA in the body of this function.
1197 if (Fn->FirstVLALoc.isValid())
1198 Diag(Fn->FirstVLALoc, diag::err_vla_in_coroutine_unsupported);
1199
1200 // Coroutines will get splitted into pieces. The GNU address of label
1201 // extension wouldn't be meaningful in coroutines.
1202 for (AddrLabelExpr *ALE : Fn->AddrLabels)
1203 Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
1204
1205 // Coroutines always return a handle, so they can't be [[noreturn]].
1206 if (FD->isNoReturn())
1207 Diag(FD->getLocation(), diag::warn_noreturn_coroutine) << FD;
1208
1209 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
1210 if (Builder.isInvalid() || !Builder.buildStatements())
1211 return FD->setInvalidDecl();
1212
1213 // Build body for the coroutine wrapper statement.
1214 Body = CoroutineBodyStmt::Create(Context, Builder);
1215}
1216
1218 if (auto *CS = dyn_cast<CompoundStmt>(Body))
1219 return CS;
1220
1221 // The body of the coroutine may be a try statement if it is in
1222 // 'function-try-block' syntax. Here we wrap it into a compound
1223 // statement for consistency.
1224 assert(isa<CXXTryStmt>(Body) && "Unimaged coroutine body type");
1225 return CompoundStmt::Create(Context, {Body}, FPOptionsOverride(),
1227}
1228
1231 Stmt *Body)
1232 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1233 IsPromiseDependentType(
1234 !Fn.CoroutinePromise ||
1235 Fn.CoroutinePromise->getType()->isDependentType()) {
1236 this->Body = buildCoroutineBody(Body, S.getASTContext());
1237
1238 for (auto KV : Fn.CoroutineParameterMoves)
1239 this->ParamMovesVector.push_back(KV.second);
1240 this->ParamMoves = this->ParamMovesVector;
1241
1242 if (!IsPromiseDependentType) {
1243 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
1244 assert(PromiseRecordDecl && "Type should have already been checked");
1245 }
1246 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1247}
1248
1250 assert(this->IsValid && "coroutine already invalid");
1251 this->IsValid = makeReturnObject();
1252 if (this->IsValid && !IsPromiseDependentType)
1254 return this->IsValid;
1255}
1256
1258 assert(this->IsValid && "coroutine already invalid");
1259 assert(!this->IsPromiseDependentType &&
1260 "coroutine cannot have a dependent promise type");
1261 this->IsValid = makeOnException() && makeOnFallthrough() &&
1262 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1263 makeNewAndDeleteExpr();
1264 return this->IsValid;
1265}
1266
1267bool CoroutineStmtBuilder::makePromiseStmt() {
1268 // Form a declaration statement for the promise declaration, so that AST
1269 // visitors can more easily find it.
1270 StmtResult PromiseStmt =
1272 if (PromiseStmt.isInvalid())
1273 return false;
1274
1275 this->Promise = PromiseStmt.get();
1276 return true;
1277}
1278
1279bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1281 return false;
1283 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
1284 return true;
1285}
1286
1288 CXXRecordDecl *PromiseRecordDecl,
1289 FunctionScopeInfo &Fn) {
1290 auto Loc = E->getExprLoc();
1291 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1292 auto *Decl = DeclRef->getDecl();
1293 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) {
1294 if (Method->isStatic())
1295 return true;
1296 else
1297 Loc = Decl->getLocation();
1298 }
1299 }
1300
1301 S.Diag(
1302 Loc,
1303 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1304 << PromiseRecordDecl;
1305 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1306 << Fn.getFirstCoroutineStmtKeyword();
1307 return false;
1308}
1309
1310bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1311 assert(!IsPromiseDependentType &&
1312 "cannot make statement while the promise type is dependent");
1313
1314 // [dcl.fct.def.coroutine]p10
1315 // If a search for the name get_return_object_on_allocation_failure in
1316 // the scope of the promise type ([class.member.lookup]) finds any
1317 // declarations, then the result of a call to an allocation function used to
1318 // obtain storage for the coroutine state is assumed to return nullptr if it
1319 // fails to obtain storage, ... If the allocation function returns nullptr,
1320 // ... and the return value is obtained by a call to
1321 // T::get_return_object_on_allocation_failure(), where T is the
1322 // promise type.
1323 DeclarationName DN =
1324 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");
1325 LookupResult Found(S, DN, Loc, Sema::LookupMemberName);
1326 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))
1327 return true;
1328
1329 CXXScopeSpec SS;
1330 ExprResult DeclNameExpr =
1331 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
1332 if (DeclNameExpr.isInvalid())
1333 return false;
1334
1335 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn))
1336 return false;
1337
1338 ExprResult ReturnObjectOnAllocationFailure =
1339 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
1340 if (ReturnObjectOnAllocationFailure.isInvalid())
1341 return false;
1342
1344 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
1345 if (ReturnStmt.isInvalid()) {
1346 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1347 << DN;
1348 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1349 << Fn.getFirstCoroutineStmtKeyword();
1350 return false;
1351 }
1352
1354 return true;
1355}
1356
1357// Collect placement arguments for allocation function of coroutine FD.
1358// Return true if we collect placement arguments succesfully. Return false,
1359// otherwise.
1361 SmallVectorImpl<Expr *> &PlacementArgs) {
1362 if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1363 if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
1364 ExprResult ThisExpr = S.ActOnCXXThis(Loc);
1365 if (ThisExpr.isInvalid())
1366 return false;
1367 ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
1368 if (ThisExpr.isInvalid())
1369 return false;
1370 PlacementArgs.push_back(ThisExpr.get());
1371 }
1372 }
1373
1374 for (auto *PD : FD.parameters()) {
1375 if (PD->getType()->isDependentType())
1376 continue;
1377
1378 // Build a reference to the parameter.
1379 auto PDLoc = PD->getLocation();
1380 ExprResult PDRefExpr =
1381 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
1383 if (PDRefExpr.isInvalid())
1384 return false;
1385
1386 PlacementArgs.push_back(PDRefExpr.get());
1387 }
1388
1389 return true;
1390}
1391
1392bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1393 // Form and check allocation and deallocation calls.
1394 assert(!IsPromiseDependentType &&
1395 "cannot make statement while the promise type is dependent");
1396 QualType PromiseType = Fn.CoroutinePromise->getType();
1397
1398 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
1399 return false;
1400
1401 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
1402
1403 // According to [dcl.fct.def.coroutine]p9, Lookup allocation functions using a
1404 // parameter list composed of the requested size of the coroutine state being
1405 // allocated, followed by the coroutine function's arguments. If a matching
1406 // allocation function exists, use it. Otherwise, use an allocation function
1407 // that just takes the requested size.
1408 //
1409 // [dcl.fct.def.coroutine]p9
1410 // An implementation may need to allocate additional storage for a
1411 // coroutine.
1412 // This storage is known as the coroutine state and is obtained by calling a
1413 // non-array allocation function ([basic.stc.dynamic.allocation]). The
1414 // allocation function's name is looked up by searching for it in the scope of
1415 // the promise type.
1416 // - If any declarations are found, overload resolution is performed on a
1417 // function call created by assembling an argument list. The first argument is
1418 // the amount of space requested, and has type std::size_t. The
1419 // lvalues p1 ... pn are the succeeding arguments.
1420 //
1421 // ...where "p1 ... pn" are defined earlier as:
1422 //
1423 // [dcl.fct.def.coroutine]p3
1424 // The promise type of a coroutine is `std::coroutine_traits<R, P1, ...,
1425 // Pn>`
1426 // , where R is the return type of the function, and `P1, ..., Pn` are the
1427 // sequence of types of the non-object function parameters, preceded by the
1428 // type of the object parameter ([dcl.fct]) if the coroutine is a non-static
1429 // member function. [dcl.fct.def.coroutine]p4 In the following, p_i is an
1430 // lvalue of type P_i, where p1 denotes the object parameter and p_i+1 denotes
1431 // the i-th non-object function parameter for a non-static member function,
1432 // and p_i denotes the i-th function parameter otherwise. For a non-static
1433 // member function, q_1 is an lvalue that denotes *this; any other q_i is an
1434 // lvalue that denotes the parameter copy corresponding to p_i.
1435
1436 FunctionDecl *OperatorNew = nullptr;
1437 SmallVector<Expr *, 1> PlacementArgs;
1438 DeclarationName NewName =
1439 S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New);
1440
1441 const bool PromiseContainsNew = [this, &PromiseType, NewName]() -> bool {
1442 LookupResult R(S, NewName, Loc, Sema::LookupOrdinaryName);
1443
1444 if (PromiseType->isRecordType())
1445 S.LookupQualifiedName(R, PromiseType->getAsCXXRecordDecl());
1446
1447 return !R.empty() && !R.isAmbiguous();
1448 }();
1449
1450 // Helper function to indicate whether the last lookup found the aligned
1451 // allocation function.
1452 ImplicitAllocationParameters IAP(
1453 alignedAllocationModeFromBool(S.getLangOpts().CoroAlignedAllocation));
1454 auto LookupAllocationFunction = [&](AllocationFunctionScope NewScope =
1456 bool WithoutPlacementArgs = false,
1457 bool ForceNonAligned = false) {
1458 // [dcl.fct.def.coroutine]p9
1459 // The allocation function's name is looked up by searching for it in the
1460 // scope of the promise type.
1461 // - If any declarations are found, ...
1462 // - If no declarations are found in the scope of the promise type, a search
1463 // is performed in the global scope.
1464 if (NewScope == AllocationFunctionScope::Both)
1465 NewScope = PromiseContainsNew ? AllocationFunctionScope::Class
1467
1468 bool ShouldUseAlignedAlloc =
1469 !ForceNonAligned && S.getLangOpts().CoroAlignedAllocation;
1470 IAP = ImplicitAllocationParameters(
1471 alignedAllocationModeFromBool(ShouldUseAlignedAlloc));
1472
1473 FunctionDecl *UnusedResult = nullptr;
1474 S.FindAllocationFunctions(
1475 Loc, SourceRange(), NewScope,
1476 /*DeleteScope=*/AllocationFunctionScope::Both, PromiseType,
1477 /*isArray=*/false, IAP,
1478 WithoutPlacementArgs ? MultiExprArg{} : PlacementArgs, OperatorNew,
1479 UnusedResult, /*Diagnose=*/false);
1480 assert(!OperatorNew || !OperatorNew->isTypeAwareOperatorNewOrDelete());
1481 };
1482
1483 // We don't expect to call to global operator new with (size, p0, …, pn).
1484 // So if we choose to lookup the allocation function in global scope, we
1485 // shouldn't lookup placement arguments.
1486 if (PromiseContainsNew && !collectPlacementArgs(S, FD, Loc, PlacementArgs))
1487 return false;
1488
1489 LookupAllocationFunction();
1490
1491 if (PromiseContainsNew && !PlacementArgs.empty()) {
1492 // [dcl.fct.def.coroutine]p9
1493 // If no viable function is found ([over.match.viable]), overload
1494 // resolution
1495 // is performed again on a function call created by passing just the amount
1496 // of space required as an argument of type std::size_t.
1497 //
1498 // Proposed Change of [dcl.fct.def.coroutine]p9 in P2014R0:
1499 // Otherwise, overload resolution is performed again on a function call
1500 // created
1501 // by passing the amount of space requested as an argument of type
1502 // std::size_t as the first argument, and the requested alignment as
1503 // an argument of type std:align_val_t as the second argument.
1504 if (!OperatorNew || (S.getLangOpts().CoroAlignedAllocation &&
1505 !isAlignedAllocation(IAP.PassAlignment)))
1506 LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
1507 /*WithoutPlacementArgs*/ true);
1508 }
1509
1510 // Proposed Change of [dcl.fct.def.coroutine]p12 in P2014R0:
1511 // Otherwise, overload resolution is performed again on a function call
1512 // created
1513 // by passing the amount of space requested as an argument of type
1514 // std::size_t as the first argument, and the lvalues p1 ... pn as the
1515 // succeeding arguments. Otherwise, overload resolution is performed again
1516 // on a function call created by passing just the amount of space required as
1517 // an argument of type std::size_t.
1518 //
1519 // So within the proposed change in P2014RO, the priority order of aligned
1520 // allocation functions wiht promise_type is:
1521 //
1522 // void* operator new( std::size_t, std::align_val_t, placement_args... );
1523 // void* operator new( std::size_t, std::align_val_t);
1524 // void* operator new( std::size_t, placement_args... );
1525 // void* operator new( std::size_t);
1526
1527 // Helper variable to emit warnings.
1528 bool FoundNonAlignedInPromise = false;
1529 if (PromiseContainsNew && S.getLangOpts().CoroAlignedAllocation)
1530 if (!OperatorNew || !isAlignedAllocation(IAP.PassAlignment)) {
1531 FoundNonAlignedInPromise = OperatorNew;
1532
1533 LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
1534 /*WithoutPlacementArgs*/ false,
1535 /*ForceNonAligned*/ true);
1536
1537 if (!OperatorNew && !PlacementArgs.empty())
1538 LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
1539 /*WithoutPlacementArgs*/ true,
1540 /*ForceNonAligned*/ true);
1541 }
1542
1543 bool IsGlobalOverload =
1544 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
1545 // If we didn't find a class-local new declaration and non-throwing new
1546 // was is required then we need to lookup the non-throwing global operator
1547 // instead.
1548 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
1549 auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc);
1550 if (!StdNoThrow)
1551 return false;
1552 PlacementArgs = {StdNoThrow};
1553 OperatorNew = nullptr;
1554 LookupAllocationFunction(AllocationFunctionScope::Global);
1555 }
1556
1557 // If we found a non-aligned allocation function in the promise_type,
1558 // it indicates the user forgot to update the allocation function. Let's emit
1559 // a warning here.
1560 if (FoundNonAlignedInPromise) {
1561 S.Diag(OperatorNew->getLocation(),
1562 diag::warn_non_aligned_allocation_function)
1563 << &FD;
1564 }
1565
1566 if (!OperatorNew) {
1567 if (PromiseContainsNew) {
1568 S.Diag(Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD;
1570 S, Loc, diag::note_coroutine_unusable_type_aware_allocators, NewName,
1571 PromiseType);
1572 } else if (RequiresNoThrowAlloc)
1573 S.Diag(Loc, diag::err_coroutine_unfound_nothrow_new)
1574 << &FD << S.getLangOpts().CoroAlignedAllocation;
1575
1576 return false;
1577 }
1578 assert(!OperatorNew->isTypeAwareOperatorNewOrDelete());
1579
1581 diag::warn_coroutine_type_aware_allocator_ignored,
1582 NewName, PromiseType);
1583
1584 if (RequiresNoThrowAlloc) {
1585 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();
1586 if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
1587 S.Diag(OperatorNew->getLocation(),
1588 diag::err_coroutine_promise_new_requires_nothrow)
1589 << OperatorNew;
1590 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1591 << OperatorNew;
1592 return false;
1593 }
1594 }
1595
1596 FunctionDecl *OperatorDelete = nullptr;
1597 if (!findDeleteForPromise(S, Loc, PromiseType, OperatorDelete)) {
1598 // FIXME: We should add an error here. According to:
1599 // [dcl.fct.def.coroutine]p12
1600 // If no usual deallocation function is found, the program is ill-formed.
1601 return false;
1602 }
1603
1604 assert(!OperatorDelete->isTypeAwareOperatorNewOrDelete());
1605
1606 Expr *FramePtr =
1607 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
1608
1609 Expr *FrameSize =
1610 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
1611
1612 Expr *FrameAlignment = nullptr;
1613
1614 if (S.getLangOpts().CoroAlignedAllocation) {
1615 FrameAlignment =
1616 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_align, {});
1617
1618 TypeSourceInfo *AlignValTy = getTypeSourceInfoForStdAlignValT(S, Loc);
1619 if (!AlignValTy)
1620 return false;
1621
1622 FrameAlignment = S.BuildCXXNamedCast(Loc, tok::kw_static_cast, AlignValTy,
1623 FrameAlignment, SourceRange(Loc, Loc),
1624 SourceRange(Loc, Loc))
1625 .get();
1626 }
1627
1628 // Make new call.
1629 ExprResult NewRef =
1630 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
1631 if (NewRef.isInvalid())
1632 return false;
1633
1634 SmallVector<Expr *, 2> NewArgs(1, FrameSize);
1635 if (S.getLangOpts().CoroAlignedAllocation &&
1636 isAlignedAllocation(IAP.PassAlignment))
1637 NewArgs.push_back(FrameAlignment);
1638
1639 if (OperatorNew->getNumParams() > NewArgs.size())
1640 llvm::append_range(NewArgs, PlacementArgs);
1641
1642 ExprResult NewExpr =
1643 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
1644 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
1645 if (NewExpr.isInvalid())
1646 return false;
1647
1648 // Make delete call.
1649
1650 QualType OpDeleteQualType = OperatorDelete->getType();
1651
1652 ExprResult DeleteRef =
1653 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
1654 if (DeleteRef.isInvalid())
1655 return false;
1656
1657 Expr *CoroFree =
1658 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
1659
1660 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
1661
1662 // [dcl.fct.def.coroutine]p12
1663 // The selected deallocation function shall be called with the address of
1664 // the block of storage to be reclaimed as its first argument. If a
1665 // deallocation function with a parameter of type std::size_t is
1666 // used, the size of the block is passed as the corresponding argument.
1667 const auto *OpDeleteType =
1668 OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
1669 if (OpDeleteType->getNumParams() > DeleteArgs.size() &&
1670 S.getASTContext().hasSameUnqualifiedType(
1671 OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))
1672 DeleteArgs.push_back(FrameSize);
1673
1674 // Proposed Change of [dcl.fct.def.coroutine]p12 in P2014R0:
1675 // If deallocation function lookup finds a usual deallocation function with
1676 // a pointer parameter, size parameter and alignment parameter then this
1677 // will be the selected deallocation function, otherwise if lookup finds a
1678 // usual deallocation function with both a pointer parameter and a size
1679 // parameter, then this will be the selected deallocation function.
1680 // Otherwise, if lookup finds a usual deallocation function with only a
1681 // pointer parameter, then this will be the selected deallocation
1682 // function.
1683 //
1684 // So we are not forced to pass alignment to the deallocation function.
1685 if (S.getLangOpts().CoroAlignedAllocation &&
1686 OpDeleteType->getNumParams() > DeleteArgs.size() &&
1687 S.getASTContext().hasSameUnqualifiedType(
1688 OpDeleteType->getParamType(DeleteArgs.size()),
1689 FrameAlignment->getType()))
1690 DeleteArgs.push_back(FrameAlignment);
1691
1692 ExprResult DeleteExpr =
1693 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
1694 DeleteExpr =
1695 S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
1696 if (DeleteExpr.isInvalid())
1697 return false;
1698
1699 this->Allocate = NewExpr.get();
1700 this->Deallocate = DeleteExpr.get();
1701
1702 return true;
1703}
1704
1705bool CoroutineStmtBuilder::makeOnFallthrough() {
1706 assert(!IsPromiseDependentType &&
1707 "cannot make statement while the promise type is dependent");
1708
1709 // [dcl.fct.def.coroutine]/p6
1710 // If searches for the names return_void and return_value in the scope of
1711 // the promise type each find any declarations, the program is ill-formed.
1712 // [Note 1: If return_void is found, flowing off the end of a coroutine is
1713 // equivalent to a co_return with no operand. Otherwise, flowing off the end
1714 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
1715 // end note]
1716 bool HasRVoid, HasRValue;
1717 LookupResult LRVoid =
1718 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
1719 LookupResult LRValue =
1720 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
1721
1722 StmtResult Fallthrough;
1723 if (HasRVoid && HasRValue) {
1724 // FIXME Improve this diagnostic
1725 S.Diag(FD.getLocation(),
1726 diag::err_coroutine_promise_incompatible_return_functions)
1727 << PromiseRecordDecl;
1728 S.Diag(LRVoid.getRepresentativeDecl()->getLocation(),
1729 diag::note_member_first_declared_here)
1730 << LRVoid.getLookupName();
1731 S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
1732 diag::note_member_first_declared_here)
1733 << LRValue.getLookupName();
1734 return false;
1735 } else if (!HasRVoid && !HasRValue) {
1736 // We need to set 'Fallthrough'. Otherwise the other analysis part might
1737 // think the coroutine has defined a return_value method. So it might emit
1738 // **false** positive warning. e.g.,
1739 //
1740 // promise_without_return_func foo() {
1741 // co_await something();
1742 // }
1743 //
1744 // Then AnalysisBasedWarning would emit a warning about `foo()` lacking a
1745 // co_return statements, which isn't correct.
1746 Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());
1747 if (Fallthrough.isInvalid())
1748 return false;
1749 } else if (HasRVoid) {
1750 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
1751 /*IsImplicit=*/true);
1752 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
1753 if (Fallthrough.isInvalid())
1754 return false;
1755 }
1756
1757 this->OnFallthrough = Fallthrough.get();
1758 return true;
1759}
1760
1761bool CoroutineStmtBuilder::makeOnException() {
1762 // Try to form 'p.unhandled_exception();'
1763 assert(!IsPromiseDependentType &&
1764 "cannot make statement while the promise type is dependent");
1765
1766 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
1767
1768 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
1769 auto DiagID =
1770 RequireUnhandledException
1771 ? diag::err_coroutine_promise_unhandled_exception_required
1772 : diag::
1773 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1774 S.Diag(Loc, DiagID) << PromiseRecordDecl;
1775 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1776 << PromiseRecordDecl;
1777 return !RequireUnhandledException;
1778 }
1779
1780 // If exceptions are disabled, don't try to build OnException.
1781 if (!S.getLangOpts().CXXExceptions)
1782 return true;
1783
1784 ExprResult UnhandledException =
1785 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", {});
1786 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
1787 /*DiscardedValue*/ false);
1788 if (UnhandledException.isInvalid())
1789 return false;
1790
1791 // Since the body of the coroutine will be wrapped in try-catch, it will
1792 // be incompatible with SEH __try if present in a function.
1793 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
1794 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
1795 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1796 << Fn.getFirstCoroutineStmtKeyword();
1797 return false;
1798 }
1799
1800 this->OnException = UnhandledException.get();
1801 return true;
1802}
1803
1804bool CoroutineStmtBuilder::makeReturnObject() {
1805 // [dcl.fct.def.coroutine]p7
1806 // The expression promise.get_return_object() is used to initialize the
1807 // returned reference or prvalue result object of a call to a coroutine.
1808 ExprResult ReturnObject =
1809 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", {});
1810 if (ReturnObject.isInvalid())
1811 return false;
1812
1813 this->ReturnValue = ReturnObject.get();
1814 return true;
1815}
1816
1818 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1819 auto *MethodDecl = MbrRef->getMethodDecl();
1820 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1821 << MethodDecl;
1822 }
1823 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1824 << Fn.getFirstCoroutineStmtKeyword();
1825}
1826
1827bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1828 assert(!IsPromiseDependentType &&
1829 "cannot make statement while the promise type is dependent");
1830 assert(this->ReturnValue && "ReturnValue must be already formed");
1831
1832 QualType const GroType = this->ReturnValue->getType();
1833 assert(!GroType->isDependentType() &&
1834 "get_return_object type must no longer be dependent");
1835
1836 QualType const FnRetType = FD.getReturnType();
1837 assert(!FnRetType->isDependentType() &&
1838 "get_return_object type must no longer be dependent");
1839
1840 // The call to get_­return_­object is sequenced before the call to
1841 // initial_­suspend and is invoked at most once, but there are caveats
1842 // regarding on whether the prvalue result object may be initialized
1843 // directly/eager or delayed, depending on the types involved.
1844 //
1845 // More info at https://github.com/cplusplus/papers/issues/1414
1846 bool GroMatchesRetType = S.getASTContext().hasSameType(GroType, FnRetType);
1847
1848 if (FnRetType->isVoidType()) {
1849 ExprResult Res =
1850 S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
1851 if (Res.isInvalid())
1852 return false;
1853
1854 if (!GroMatchesRetType)
1855 this->ResultDecl = Res.get();
1856 return true;
1857 }
1858
1859 if (GroType->isVoidType()) {
1860 // Trigger a nice error message.
1861 InitializedEntity Entity =
1863 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1865 return false;
1866 }
1867
1869 clang::VarDecl *GroDecl = nullptr;
1870 if (GroMatchesRetType) {
1871 ReturnStmt = S.BuildReturnStmt(Loc, ReturnValue);
1872 } else {
1873 GroDecl = VarDecl::Create(
1874 S.Context, &FD, FD.getLocation(), FD.getLocation(),
1875 &S.PP.getIdentifierTable().get("__coro_gro"),
1876 S.BuildDecltypeType(ReturnValue).getCanonicalType(),
1877 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
1878 GroDecl->setImplicit();
1879
1880 S.CheckVariableDeclarationType(GroDecl);
1881 if (GroDecl->isInvalidDecl())
1882 return false;
1883
1884 InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
1885 ExprResult Res =
1886 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1887 if (Res.isInvalid())
1888 return false;
1889
1890 Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
1891 if (Res.isInvalid())
1892 return false;
1893
1894 S.AddInitializerToDecl(GroDecl, Res.get(),
1895 /*DirectInit=*/false);
1896
1897 S.FinalizeDeclaration(GroDecl);
1898
1899 // Form a declaration statement for the return declaration, so that AST
1900 // visitors can more easily find it.
1901 StmtResult GroDeclStmt =
1902 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
1903 if (GroDeclStmt.isInvalid())
1904 return false;
1905
1906 this->ResultDecl = GroDeclStmt.get();
1907
1908 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
1909 if (declRef.isInvalid())
1910 return false;
1911
1912 ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
1913 }
1914
1915 if (ReturnStmt.isInvalid()) {
1917 return false;
1918 }
1919
1920 if (!GroMatchesRetType &&
1921 cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
1922 GroDecl->setNRVOVariable(true);
1923
1924 this->ReturnStmt = ReturnStmt.get();
1925 return true;
1926}
1927
1928// Create a static_cast<T&&>(expr).
1930 if (T.isNull())
1931 T = E->getType();
1932 QualType TargetType = S.BuildReferenceType(
1933 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
1934 SourceLocation ExprLoc = E->getBeginLoc();
1935 TypeSourceInfo *TargetLoc =
1936 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
1937
1938 return S
1939 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
1940 SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
1941 .get();
1942}
1943
1944/// Build a variable declaration for move parameter.
1946 IdentifierInfo *II) {
1948 VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
1949 TInfo, SC_None);
1950 Decl->setImplicit();
1951 return Decl;
1952}
1953
1954// Build statements that move coroutine function parameters to the coroutine
1955// frame, and store them on the function scope info.
1957 assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
1958 auto *FD = cast<FunctionDecl>(CurContext);
1959
1960 auto *ScopeInfo = getCurFunction();
1961 if (!ScopeInfo->CoroutineParameterMoves.empty())
1962 return false;
1963
1964 // [dcl.fct.def.coroutine]p13
1965 // When a coroutine is invoked, after initializing its parameters
1966 // ([expr.call]), a copy is created for each coroutine parameter. For a
1967 // parameter of type cv T, the copy is a variable of type cv T with
1968 // automatic storage duration that is direct-initialized from an xvalue of
1969 // type T referring to the parameter.
1970 for (auto *PD : FD->parameters()) {
1971 if (PD->getType()->isDependentType())
1972 continue;
1973
1974 // Preserve the referenced state for unused parameter diagnostics.
1975 bool DeclReferenced = PD->isReferenced();
1976
1977 ExprResult PDRefExpr =
1978 BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
1979 ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1980
1981 PD->setReferenced(DeclReferenced);
1982
1983 if (PDRefExpr.isInvalid())
1984 return false;
1985
1986 Expr *CExpr = nullptr;
1987 if (PD->getType()->getAsCXXRecordDecl() ||
1988 PD->getType()->isRValueReferenceType())
1989 CExpr = castForMoving(*this, PDRefExpr.get());
1990 else
1991 CExpr = PDRefExpr.get();
1992 // [dcl.fct.def.coroutine]p13
1993 // The initialization and destruction of each parameter copy occurs in the
1994 // context of the called coroutine.
1995 auto *D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
1996 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
1997
1998 // Convert decl to a statement.
2000 if (Stmt.isInvalid())
2001 return false;
2002
2003 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
2004 }
2005 return true;
2006}
2007
2010 if (!Res)
2011 return StmtError();
2012 return Res;
2013}
2014
2016 SourceLocation FuncLoc) {
2019
2020 IdentifierInfo const &TraitIdent =
2021 PP.getIdentifierTable().get("coroutine_traits");
2022
2023 NamespaceDecl *StdSpace = getStdNamespace();
2024 LookupResult Result(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
2025 bool Found = StdSpace && LookupQualifiedName(Result, StdSpace);
2026
2027 if (!Found) {
2028 // The goggles, we found nothing!
2029 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
2030 << "std::coroutine_traits";
2031 return nullptr;
2032 }
2033
2034 // coroutine_traits is required to be a class template.
2037 Result.suppressDiagnostics();
2038 NamedDecl *Found = *Result.begin();
2039 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
2040 return nullptr;
2041 }
2042
2044}
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines enum values for all the target-independent builtin functions.
Defines the clang::Expr interface and subclasses for C++ expressions.
TokenType getType() const
Returns the token's type, e.g.
llvm::MachO::Record Record
Definition MachO.h:31
Defines the clang::Preprocessor interface.
static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, SourceLocation Loc)
static bool DiagnoseTypeAwareAllocators(Sema &S, SourceLocation Loc, unsigned DiagnosticID, DeclarationName Name, QualType PromiseType)
static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn)
static void checkReturnStmtInCoroutine(Sema &S, FunctionScopeInfo *FSI)
static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static void applySafeElideContext(Expr *Operand)
static Expr * buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc)
Look up the std::nothrow object.
static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E)
static bool diagReturnOnAllocFailure(Sema &S, Expr *E, CXXRecordDecl *PromiseRecordDecl, FunctionScopeInfo &Fn)
static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, SourceLocation Loc, StringRef Name, MultiExprArg Args)
static Expr * castForMoving(Sema &S, Expr *E, QualType T=QualType())
static Expr * maybeTailCall(Sema &S, QualType RetType, Expr *E, SourceLocation Loc)
static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, StringRef Name, MultiExprArg Args)
static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, SourceLocation Loc, bool &Res)
static TypeSourceInfo * getTypeSourceInfoForStdAlignValT(Sema &S, SourceLocation Loc)
static bool isWithinCatchScope(Scope *S)
static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType, FunctionDecl *&OperatorDelete)
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static void checkNoThrow(Sema &S, const Stmt *E, llvm::SmallPtrSetImpl< const Decl * > &ThrowingDecls)
Recursively check E and all its children to see if any call target (including constructor call) is de...
static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, SourceLocation Loc, Expr *E)
Build calls to await_ready, await_suspend, and await_resume for a co_await expression.
static bool checkSuspensionContext(Sema &S, SourceLocation Loc, StringRef Keyword)
static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, SourceLocation Loc)
Look up the std::coroutine_handle<PromiseType>.
static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc, SmallVectorImpl< Expr * > &PlacementArgs)
static CompoundStmt * buildCoroutineBody(Stmt *Body, ASTContext &Context)
static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, SourceLocation KwLoc)
Look up the std::coroutine_traits<...>::promise_type for the given function type.
static bool isAttributedCoroAwaitElidable(const QualType &QT)
static FunctionScopeInfo * checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword, bool IsImplicit=false)
Check that this is a context in which a coroutine suspension can appear.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
DeclarationNameTable DeclarationNames
Definition ASTContext.h:801
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
CanQualType getCanonicalTagType(const TagDecl *TD) const
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition Expr.h:4553
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4573
Represents a C++ constructor within a class.
Definition DeclCXX.h:2611
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2262
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2131
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:74
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3129
Decl * getCalleeDecl()
Definition Expr.h:3123
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1603
Declaration of a class template.
void setExprNeedsCleanups(bool SideEffects)
Definition CleanupInfo.h:28
Represents a 'co_await' expression.
Definition ExprCXX.h:5370
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1732
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition StmtCXX.h:473
Represents the body of a coroutine.
Definition StmtCXX.h:320
static CoroutineBodyStmt * Create(const ASTContext &C, CtorArgs const &Args)
Definition StmtCXX.cpp:87
CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn, Stmt *Body)
Construct a CoroutineStmtBuilder and initialize the promise statement and initial/final suspends from...
bool buildDependentStatements()
Build the coroutine body statements that require a non-dependent promise type in order to construct.
bool buildStatements()
Build the coroutine body statements, including the "promise dependent" statements when the promise ty...
Represents a 'co_yield' expression.
Definition ExprCXX.h:5451
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition DeclBase.h:435
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
bool isInvalidDecl() const
Definition DeclBase.h:588
SourceLocation getLocation() const
Definition DeclBase.h:439
void setImplicit(bool I=true)
Definition DeclBase.h:594
DeclContext * getDeclContext()
Definition DeclBase.h:448
bool hasAttr() const
Definition DeclBase.h:577
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
Represents a 'co_await' expression while the type of the promise is dependent.
Definition ExprCXX.h:5402
RAII object that enters a new function expression evaluation context.
Represents an enum.
Definition Decl.h:4013
This represents one expression.
Definition Expr.h:112
bool isPRValue() const
Definition Expr.h:285
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:454
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:277
QualType getType() const
Definition Expr.h:144
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition Expr.h:526
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:2000
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Definition Decl.cpp:3652
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isTypeAwareOperatorNewOrDelete() const
Determine whether this is a type aware operator new or delete.
Definition Decl.cpp:3560
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5315
ArrayRef< QualType > getParamTypes() const
Definition TypeBase.h:5600
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this function type.
Definition TypeBase.h:5749
QualType getReturnType() const
Definition TypeBase.h:4851
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)
Create an initialization from an initializer (which, for direct initialization from a parenthesized l...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)
Create the initialization entity for the result of a function.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
Represents the results of name lookup.
Definition Lookup.h:147
DeclClass * getAsSingle() const
Definition Lookup.h:558
bool isAmbiguous() const
Definition Lookup.h:324
const UnresolvedSetImpl & asUnresolvedSet() const
Definition Lookup.h:354
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition Lookup.h:576
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition Lookup.h:636
DeclarationName getLookupName() const
Gets the name to look up.
Definition Lookup.h:265
This represents a decl that may have a name.
Definition Decl.h:274
Represent a C++ namespace.
Definition Decl.h:592
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1181
decls_iterator decls_begin() const
Definition ExprCXX.h:3222
decls_iterator decls_end() const
Definition ExprCXX.h:3225
static ParenListExpr * Create(const ASTContext &Ctx, SourceLocation LParenLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc)
Create a paren list.
Definition Expr.cpp:4948
Represents a parameter to a function.
Definition Decl.h:1790
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
IdentifierTable & getIdentifierTable()
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8388
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8573
QualType getCanonicalType() const
Definition TypeBase.h:8440
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1551
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
bool isCatchScope() const
isCatchScope - Return true if this scope is a C++ catch statement.
Definition Scope.h:503
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:287
bool isFunctionScope() const
isFunctionScope() - Return true if this scope is a function scope.
Definition Scope.h:425
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Expr * get() const
Definition Sema.h:7817
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
FunctionDecl * FindUsualDeallocationFunction(SourceLocation StartLoc, ImplicitDeallocationParameters, DeclarationName Name, bool Diagnose=true)
ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E, UnresolvedLookupExpr *Lookup)
Build a call to 'operator co_await' if there is a suitable operator for the given expression.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1133
ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs=nullptr)
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9382
@ LookupOperatorName
Look up of an operator name (e.g., operator+) for use with operator overloading.
Definition Sema.h:9394
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
Definition Sema.h:9390
bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend)
Check that the expression co_await promise.final_suspend() shall not be potentially-throwing.
StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs)
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl *&Operator, ImplicitDeallocationParameters, bool Diagnose=true)
ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body)
bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword)
VarDecl * buildCoroutinePromise(SourceLocation Loc)
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
Definition Sema.h:6979
StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, bool IsImplicit=false)
Expr * BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs)
BuildBuiltinCallExpr - Create a call to a builtin function specified by Id.
ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, Expr *Awaiter, bool IsImplicit=false)
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition Sema.cpp:1674
ASTContext & Context
Definition Sema.h:1300
ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E)
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:79
ClassTemplateDecl * StdCoroutineTraitsCache
The C++ "std::coroutine_traits" template, which is defined in <coroutine_traits>
Definition Sema.h:3191
ASTContext & getASTContext() const
Definition Sema.h:939
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
EnumDecl * getStdAlignValT() const
NamedReturnInfo getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode=SimplerImplicitMoveMode::Normal)
Determine whether the given expression might be move-eligible or copy-elidable in either a (co_)retur...
StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E)
const LangOptions & getLangOpts() const
Definition Sema.h:932
Preprocessor & PP
Definition Sema.h:1299
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
CleanupInfo Cleanup
Used to control the generation of ExprWithCleanups.
Definition Sema.h:7012
ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, UnresolvedLookupExpr *Lookup)
bool buildCoroutineParameterMoves(SourceLocation Loc)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1333
QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity)
Build a reference type.
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *input, bool RequiresADL=true)
Create a unary operation that may resolve to an overloaded operator.
ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1438
MaterializeTemporaryExpr * CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference)
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
bool isUnevaluatedContext() const
Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.
Definition Sema.h:8228
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
ClassTemplateDecl * lookupCoroutineTraits(SourceLocation KwLoc, SourceLocation FuncLoc)
Lookup 'coroutine_traits' in std namespace and std::experimental namespace.
DeclContext * computeDeclContext(QualType T)
Compute the DeclContext that is associated with the given type.
void CheckCompleteVariableDeclaration(VarDecl *VD)
QualType CheckTemplateIdType(ElaboratedTypeKeyword Keyword, TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, Scope *Scope, bool ForNestedNameSpecifier)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6790
ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
FullExprArg MakeFullDiscardedValueExpr(Expr *Arg)
Definition Sema.h:7838
NamespaceDecl * getStdNamespace() const
friend class InitializationSequence
Definition Sema.h:1580
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, TypeSourceInfo *Ty, Expr *E, SourceRange AngleBrackets, SourceRange Parens)
Definition SemaCast.cpp:337
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
void CheckVariableDeclarationType(VarDecl *NewVD)
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
ExprResult ActOnCXXThis(SourceLocation Loc)
static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, SourceLocation Loc=SourceLocation())
Determine whether the callee of a particular function call can throw.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8710
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:86
child_range children()
Definition Stmt.cpp:304
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
Location wrapper for a TemplateArgument.
Represents a template argument.
Represents a declaration of a type.
Definition Decl.h:3513
A container of type source information.
Definition TypeBase.h:8359
The base class of the type hierarchy.
Definition TypeBase.h:1839
bool isVoidType() const
Definition TypeBase.h:8991
bool isBooleanType() const
Definition TypeBase.h:9128
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isVoidPointerType() const
Definition Type.cpp:713
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9285
bool isReferenceType() const
Definition TypeBase.h:8649
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2790
bool isRecordType() const
Definition TypeBase.h:8752
A reference to a name which we were able to look up during parsing but could not resolve to a specifi...
Definition ExprCXX.h:3391
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
Definition ExprCXX.cpp:432
void append(iterator I, iterator E)
A set of unresolved declarations.
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2163
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:934
void setNRVOVariable(bool NRVO)
Definition Decl.h:1515
Retains information about a function, method, or block that is currently being parsed.
Definition ScopeInfo.h:104
SourceLocation FirstCoroutineStmtLoc
First coroutine statement in the current function.
Definition ScopeInfo.h:183
std::pair< Stmt *, Stmt * > CoroutineSuspends
The initial and final coroutine suspend points.
Definition ScopeInfo.h:224
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
Definition ScopeInfo.h:217
bool hasInvalidCoroutineSuspends() const
Definition ScopeInfo.h:544
StringRef getFirstCoroutineStmtKeyword() const
Definition ScopeInfo.h:522
SourceLocation FirstReturnLoc
First 'return' statement in the current function.
Definition ScopeInfo.h:186
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
AllocationFunctionScope
The scope in which to find allocation functions.
Definition Sema.h:791
@ Both
Look for allocation functions in both the global scope and in the scope of the allocated class.
Definition Sema.h:799
@ Global
Only look for allocation functions in the global scope.
Definition Sema.h:793
@ Class
Only look for allocation functions in the scope of the allocated class.
Definition Sema.h:796
AlignedAllocationMode alignedAllocationModeFromBool(bool IsAligned)
Definition ExprCXX.h:2270
Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)
Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...
Definition IgnoreExpr.h:24
@ RQ_RValue
An rvalue ref-qualifier was provided (&&).
Definition TypeBase.h:1794
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
@ SC_None
Definition Specifiers.h:250
bool isAlignedAllocation(AlignedAllocationMode Mode)
Definition ExprCXX.h:2266
ExprResult ExprEmpty()
Definition Ownership.h:272
MutableArrayRef< Expr * > MultiExprArg
Definition Ownership.h:259
StmtResult StmtError()
Definition Ownership.h:266
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ExprResult ExprError()
Definition Ownership.h:265
@ Keyword
The name has been typo-corrected to a keyword.
Definition Sema.h:562
Expr * IgnoreImplicitSingleStep(Expr *E)
Definition IgnoreExpr.h:101
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
Expr * IgnoreParensSingleStep(Expr *E)
Definition IgnoreExpr.h:157
U cast(CodeGen::Address addr)
Definition Address.h:327
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:5935
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
OpaqueValueExpr * OpaqueValue
ArrayRef< Stmt * > ParamMoves
Definition StmtCXX.h:361
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SizedDeallocationMode PassSize
Definition ExprCXX.h:2341
enum clang::Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext