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