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