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