Bug Summary

File:clang/lib/Sema/SemaCoroutine.cpp
Warning:line 683, column 25
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name SemaCoroutine.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/build-llvm -resource-dir /usr/lib/llvm-15/lib/clang/15.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/Sema -I /build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/clang/lib/Sema -I /build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-15/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-02-12-124252-137181-1 -x c++ /build/llvm-toolchain-snapshot-15~++20220212111237+869c066ca8a4/clang/lib/Sema/SemaCoroutine.cpp
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
16#include "CoroutineStmtBuilder.h"
17#include "clang/AST/ASTLambda.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/StmtCXX.h"
21#include "clang/Basic/Builtins.h"
22#include "clang/Lex/Preprocessor.h"
23#include "clang/Sema/Initialization.h"
24#include "clang/Sema/Overload.h"
25#include "clang/Sema/ScopeInfo.h"
26#include "clang/Sema/SemaInternal.h"
27#include "llvm/ADT/SmallSet.h"
28
29using namespace clang;
30using namespace sema;
31
32static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
33 SourceLocation Loc, bool &Res) {
34 DeclarationName DN = S.PP.getIdentifierInfo(Name);
35 LookupResult LR(S, DN, Loc, Sema::LookupMemberName);
36 // Suppress diagnostics when a private member is selected. The same warnings
37 // will be produced again when building the call.
38 LR.suppressDiagnostics();
39 Res = S.LookupQualifiedName(LR, RD);
40 return LR;
41}
42
43static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
44 SourceLocation Loc) {
45 bool Res;
46 lookupMember(S, Name, RD, Loc, Res);
47 return Res;
48}
49
50/// Look up the std::coroutine_traits<...>::promise_type for the given
51/// function type.
52static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
53 SourceLocation KwLoc) {
54 const FunctionProtoType *FnType = FD->getType()->castAs<FunctionProtoType>();
55 const SourceLocation FuncLoc = FD->getLocation();
56
57 NamespaceDecl *CoroNamespace = nullptr;
58 ClassTemplateDecl *CoroTraits =
59 S.lookupCoroutineTraits(KwLoc, FuncLoc, CoroNamespace);
60 if (!CoroTraits) {
61 return QualType();
62 }
63
64 // Form template argument list for coroutine_traits<R, P1, P2, ...> according
65 // to [dcl.fct.def.coroutine]3
66 TemplateArgumentListInfo Args(KwLoc, KwLoc);
67 auto AddArg = [&](QualType T) {
68 Args.addArgument(TemplateArgumentLoc(
69 TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc)));
70 };
71 AddArg(FnType->getReturnType());
72 // If the function is a non-static member function, add the type
73 // of the implicit object parameter before the formal parameters.
74 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
75 if (MD->isInstance()) {
76 // [over.match.funcs]4
77 // For non-static member functions, the type of the implicit object
78 // parameter is
79 // -- "lvalue reference to cv X" for functions declared without a
80 // ref-qualifier or with the & ref-qualifier
81 // -- "rvalue reference to cv X" for functions declared with the &&
82 // ref-qualifier
83 QualType T = MD->getThisType()->castAs<PointerType>()->getPointeeType();
84 T = FnType->getRefQualifier() == RQ_RValue
85 ? S.Context.getRValueReferenceType(T)
86 : S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true);
87 AddArg(T);
88 }
89 }
90 for (QualType T : FnType->getParamTypes())
91 AddArg(T);
92
93 // Build the template-id.
94 QualType CoroTrait =
95 S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args);
96 if (CoroTrait.isNull())
97 return QualType();
98 if (S.RequireCompleteType(KwLoc, CoroTrait,
99 diag::err_coroutine_type_missing_specialization))
100 return QualType();
101
102 auto *RD = CoroTrait->getAsCXXRecordDecl();
103 assert(RD && "specialization of class template is not a class?")(static_cast <bool> (RD && "specialization of class template is not a class?"
) ? void (0) : __assert_fail ("RD && \"specialization of class template is not a class?\""
, "clang/lib/Sema/SemaCoroutine.cpp", 103, __extension__ __PRETTY_FUNCTION__
))
;
104
105 // Look up the ::promise_type member.
106 LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), KwLoc,
107 Sema::LookupOrdinaryName);
108 S.LookupQualifiedName(R, RD);
109 auto *Promise = R.getAsSingle<TypeDecl>();
110 if (!Promise) {
111 S.Diag(FuncLoc,
112 diag::err_implied_std_coroutine_traits_promise_type_not_found)
113 << RD;
114 return QualType();
115 }
116 // The promise type is required to be a class type.
117 QualType PromiseType = S.Context.getTypeDeclType(Promise);
118
119 auto buildElaboratedType = [&]() {
120 auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, CoroNamespace);
121 NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
122 CoroTrait.getTypePtr());
123 return S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
124 };
125
126 if (!PromiseType->getAsCXXRecordDecl()) {
127 S.Diag(FuncLoc,
128 diag::err_implied_std_coroutine_traits_promise_type_not_class)
129 << buildElaboratedType();
130 return QualType();
131 }
132 if (S.RequireCompleteType(FuncLoc, buildElaboratedType(),
133 diag::err_coroutine_promise_type_incomplete))
134 return QualType();
135
136 return PromiseType;
137}
138
139/// Look up the std::coroutine_handle<PromiseType>.
140static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
141 SourceLocation Loc) {
142 if (PromiseType.isNull())
143 return QualType();
144
145 NamespaceDecl *CoroNamespace = S.getCachedCoroNamespace();
146 assert(CoroNamespace && "Should already be diagnosed")(static_cast <bool> (CoroNamespace && "Should already be diagnosed"
) ? void (0) : __assert_fail ("CoroNamespace && \"Should already be diagnosed\""
, "clang/lib/Sema/SemaCoroutine.cpp", 146, __extension__ __PRETTY_FUNCTION__
))
;
147
148 LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
149 Loc, Sema::LookupOrdinaryName);
150 if (!S.LookupQualifiedName(Result, CoroNamespace)) {
151 S.Diag(Loc, diag::err_implied_coroutine_type_not_found)
152 << "std::coroutine_handle";
153 return QualType();
154 }
155
156 ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>();
157 if (!CoroHandle) {
158 Result.suppressDiagnostics();
159 // We found something weird. Complain about the first thing we found.
160 NamedDecl *Found = *Result.begin();
161 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle);
162 return QualType();
163 }
164
165 // Form template argument list for coroutine_handle<Promise>.
166 TemplateArgumentListInfo Args(Loc, Loc);
167 Args.addArgument(TemplateArgumentLoc(
168 TemplateArgument(PromiseType),
169 S.Context.getTrivialTypeSourceInfo(PromiseType, Loc)));
170
171 // Build the template-id.
172 QualType CoroHandleType =
173 S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args);
174 if (CoroHandleType.isNull())
175 return QualType();
176 if (S.RequireCompleteType(Loc, CoroHandleType,
177 diag::err_coroutine_type_missing_specialization))
178 return QualType();
179
180 return CoroHandleType;
181}
182
183static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
184 StringRef Keyword) {
185 // [expr.await]p2 dictates that 'co_await' and 'co_yield' must be used within
186 // a function body.
187 // FIXME: This also covers [expr.await]p2: "An await-expression shall not
188 // appear in a default argument." But the diagnostic QoI here could be
189 // improved to inform the user that default arguments specifically are not
190 // allowed.
191 auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
192 if (!FD) {
193 S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
194 ? diag::err_coroutine_objc_method
195 : diag::err_coroutine_outside_function) << Keyword;
196 return false;
197 }
198
199 // An enumeration for mapping the diagnostic type to the correct diagnostic
200 // selection index.
201 enum InvalidFuncDiag {
202 DiagCtor = 0,
203 DiagDtor,
204 DiagMain,
205 DiagConstexpr,
206 DiagAutoRet,
207 DiagVarargs,
208 DiagConsteval,
209 };
210 bool Diagnosed = false;
211 auto DiagInvalid = [&](InvalidFuncDiag ID) {
212 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
213 Diagnosed = true;
214 return false;
215 };
216
217 // Diagnose when a constructor, destructor
218 // or the function 'main' are declared as a coroutine.
219 auto *MD = dyn_cast<CXXMethodDecl>(FD);
220 // [class.ctor]p11: "A constructor shall not be a coroutine."
221 if (MD && isa<CXXConstructorDecl>(MD))
222 return DiagInvalid(DiagCtor);
223 // [class.dtor]p17: "A destructor shall not be a coroutine."
224 else if (MD && isa<CXXDestructorDecl>(MD))
225 return DiagInvalid(DiagDtor);
226 // [basic.start.main]p3: "The function main shall not be a coroutine."
227 else if (FD->isMain())
228 return DiagInvalid(DiagMain);
229
230 // Emit a diagnostics for each of the following conditions which is not met.
231 // [expr.const]p2: "An expression e is a core constant expression unless the
232 // evaluation of e [...] would evaluate one of the following expressions:
233 // [...] an await-expression [...] a yield-expression."
234 if (FD->isConstexpr())
235 DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);
236 // [dcl.spec.auto]p15: "A function declared with a return type that uses a
237 // placeholder type shall not be a coroutine."
238 if (FD->getReturnType()->isUndeducedType())
239 DiagInvalid(DiagAutoRet);
240 // [dcl.fct.def.coroutine]p1
241 // The parameter-declaration-clause of the coroutine shall not terminate with
242 // an ellipsis that is not part of a parameter-declaration.
243 if (FD->isVariadic())
244 DiagInvalid(DiagVarargs);
245
246 return !Diagnosed;
247}
248
249static ExprResult buildOperatorCoawaitLookupExpr(Sema &SemaRef, Scope *S,
250 SourceLocation Loc) {
251 DeclarationName OpName =
252 SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
253 LookupResult Operators(SemaRef, OpName, SourceLocation(),
254 Sema::LookupOperatorName);
255 SemaRef.LookupName(Operators, S);
256
257 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous")(static_cast <bool> (!Operators.isAmbiguous() &&
"Operator lookup cannot be ambiguous") ? void (0) : __assert_fail
("!Operators.isAmbiguous() && \"Operator lookup cannot be ambiguous\""
, "clang/lib/Sema/SemaCoroutine.cpp", 257, __extension__ __PRETTY_FUNCTION__
))
;
258 const auto &Functions = Operators.asUnresolvedSet();
259 bool IsOverloaded =
260 Functions.size() > 1 ||
261 (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
262 Expr *CoawaitOp = UnresolvedLookupExpr::Create(
263 SemaRef.Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
264 DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded,
265 Functions.begin(), Functions.end());
266 assert(CoawaitOp)(static_cast <bool> (CoawaitOp) ? void (0) : __assert_fail
("CoawaitOp", "clang/lib/Sema/SemaCoroutine.cpp", 266, __extension__
__PRETTY_FUNCTION__))
;
267 return CoawaitOp;
268}
269
270/// Build a call to 'operator co_await' if there is a suitable operator for
271/// the given expression.
272static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, SourceLocation Loc,
273 Expr *E,
274 UnresolvedLookupExpr *Lookup) {
275 UnresolvedSet<16> Functions;
276 Functions.append(Lookup->decls_begin(), Lookup->decls_end());
277 return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
278}
279
280static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
281 SourceLocation Loc, Expr *E) {
282 ExprResult R = buildOperatorCoawaitLookupExpr(SemaRef, S, Loc);
283 if (R.isInvalid())
284 return ExprError();
285 return buildOperatorCoawaitCall(SemaRef, Loc, E,
286 cast<UnresolvedLookupExpr>(R.get()));
287}
288
289static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
290 SourceLocation Loc) {
291 QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
292 if (CoroHandleType.isNull())
293 return ExprError();
294
295 DeclContext *LookupCtx = S.computeDeclContext(CoroHandleType);
296 LookupResult Found(S, &S.PP.getIdentifierTable().get("from_address"), Loc,
297 Sema::LookupOrdinaryName);
298 if (!S.LookupQualifiedName(Found, LookupCtx)) {
299 S.Diag(Loc, diag::err_coroutine_handle_missing_member)
300 << "from_address";
301 return ExprError();
302 }
303
304 Expr *FramePtr =
305 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
306
307 CXXScopeSpec SS;
308 ExprResult FromAddr =
309 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
310 if (FromAddr.isInvalid())
311 return ExprError();
312
313 return S.BuildCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc);
314}
315
316struct ReadySuspendResumeResult {
317 enum AwaitCallType { ACT_Ready, ACT_Suspend, ACT_Resume };
318 Expr *Results[3];
319 OpaqueValueExpr *OpaqueValue;
320 bool IsInvalid;
321};
322
323static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
324 StringRef Name, MultiExprArg Args) {
325 DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
326
327 // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
328 CXXScopeSpec SS;
329 ExprResult Result = S.BuildMemberReferenceExpr(
330 Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
331 SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
332 /*Scope=*/nullptr);
333 if (Result.isInvalid())
334 return ExprError();
335
336 // We meant exactly what we asked for. No need for typo correction.
337 if (auto *TE = dyn_cast<TypoExpr>(Result.get())) {
338 S.clearDelayedTypo(TE);
339 S.Diag(Loc, diag::err_no_member)
340 << NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
341 << Base->getSourceRange();
342 return ExprError();
343 }
344
345 return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
346}
347
348// See if return type is coroutine-handle and if so, invoke builtin coro-resume
349// on its address. This is to enable experimental support for coroutine-handle
350// returning await_suspend that results in a guaranteed tail call to the target
351// coroutine.
352static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
353 SourceLocation Loc) {
354 if (RetType->isReferenceType())
355 return nullptr;
356 Type const *T = RetType.getTypePtr();
357 if (!T->isClassType() && !T->isStructureType())
358 return nullptr;
359
360 // FIXME: Add convertability check to coroutine_handle<>. Possibly via
361 // EvaluateBinaryTypeTrait(BTT_IsConvertible, ...) which is at the moment
362 // a private function in SemaExprCXX.cpp
363
364 ExprResult AddressExpr = buildMemberCall(S, E, Loc, "address", None);
365 if (AddressExpr.isInvalid())
366 return nullptr;
367
368 Expr *JustAddress = AddressExpr.get();
369
370 // Check that the type of AddressExpr is void*
371 if (!JustAddress->getType().getTypePtr()->isVoidPointerType())
372 S.Diag(cast<CallExpr>(JustAddress)->getCalleeDecl()->getLocation(),
373 diag::warn_coroutine_handle_address_invalid_return_type)
374 << JustAddress->getType();
375
376 // Clean up temporary objects so that they don't live across suspension points
377 // unnecessarily. We choose to clean up before the call to
378 // __builtin_coro_resume so that the cleanup code are not inserted in-between
379 // the resume call and return instruction, which would interfere with the
380 // musttail call contract.
381 JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
382 return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume,
383 JustAddress);
384}
385
386/// Build calls to await_ready, await_suspend, and await_resume for a co_await
387/// expression.
388/// The generated AST tries to clean up temporary objects as early as
389/// possible so that they don't live across suspension points if possible.
390/// Having temporary objects living across suspension points unnecessarily can
391/// lead to large frame size, and also lead to memory corruptions if the
392/// coroutine frame is destroyed after coming back from suspension. This is done
393/// by wrapping both the await_ready call and the await_suspend call with
394/// ExprWithCleanups. In the end of this function, we also need to explicitly
395/// set cleanup state so that the CoawaitExpr is also wrapped with an
396/// ExprWithCleanups to clean up the awaiter associated with the co_await
397/// expression.
398static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
399 SourceLocation Loc, Expr *E) {
400 OpaqueValueExpr *Operand = new (S.Context)
401 OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
402
403 // Assume valid until we see otherwise.
404 // Further operations are responsible for setting IsInalid to true.
405 ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/false};
406
407 using ACT = ReadySuspendResumeResult::AwaitCallType;
408
409 auto BuildSubExpr = [&](ACT CallType, StringRef Func,
410 MultiExprArg Arg) -> Expr * {
411 ExprResult Result = buildMemberCall(S, Operand, Loc, Func, Arg);
412 if (Result.isInvalid()) {
413 Calls.IsInvalid = true;
414 return nullptr;
415 }
416 Calls.Results[CallType] = Result.get();
417 return Result.get();
418 };
419
420 CallExpr *AwaitReady =
421 cast_or_null<CallExpr>(BuildSubExpr(ACT::ACT_Ready, "await_ready", None));
422 if (!AwaitReady)
423 return Calls;
424 if (!AwaitReady->getType()->isDependentType()) {
425 // [expr.await]p3 [...]
426 // — await-ready is the expression e.await_ready(), contextually converted
427 // to bool.
428 ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady);
429 if (Conv.isInvalid()) {
430 S.Diag(AwaitReady->getDirectCallee()->getBeginLoc(),
431 diag::note_await_ready_no_bool_conversion);
432 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
433 << AwaitReady->getDirectCallee() << E->getSourceRange();
434 Calls.IsInvalid = true;
435 } else
436 Calls.Results[ACT::ACT_Ready] = S.MaybeCreateExprWithCleanups(Conv.get());
437 }
438
439 ExprResult CoroHandleRes =
440 buildCoroutineHandle(S, CoroPromise->getType(), Loc);
441 if (CoroHandleRes.isInvalid()) {
442 Calls.IsInvalid = true;
443 return Calls;
444 }
445 Expr *CoroHandle = CoroHandleRes.get();
446 CallExpr *AwaitSuspend = cast_or_null<CallExpr>(
447 BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
448 if (!AwaitSuspend)
449 return Calls;
450 if (!AwaitSuspend->getType()->isDependentType()) {
451 // [expr.await]p3 [...]
452 // - await-suspend is the expression e.await_suspend(h), which shall be
453 // a prvalue of type void, bool, or std::coroutine_handle<Z> for some
454 // type Z.
455 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
456
457 // Experimental support for coroutine_handle returning await_suspend.
458 if (Expr *TailCallSuspend =
459 maybeTailCall(S, RetType, AwaitSuspend, Loc))
460 // Note that we don't wrap the expression with ExprWithCleanups here
461 // because that might interfere with tailcall contract (e.g. inserting
462 // clean up instructions in-between tailcall and return). Instead
463 // ExprWithCleanups is wrapped within maybeTailCall() prior to the resume
464 // call.
465 Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
466 else {
467 // non-class prvalues always have cv-unqualified types
468 if (RetType->isReferenceType() ||
469 (!RetType->isBooleanType() && !RetType->isVoidType())) {
470 S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
471 diag::err_await_suspend_invalid_return_type)
472 << RetType;
473 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
474 << AwaitSuspend->getDirectCallee();
475 Calls.IsInvalid = true;
476 } else
477 Calls.Results[ACT::ACT_Suspend] =
478 S.MaybeCreateExprWithCleanups(AwaitSuspend);
479 }
480 }
481
482 BuildSubExpr(ACT::ACT_Resume, "await_resume", None);
483
484 // Make sure the awaiter object gets a chance to be cleaned up.
485 S.Cleanup.setExprNeedsCleanups(true);
486
487 return Calls;
488}
489
490static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise,
491 SourceLocation Loc, StringRef Name,
492 MultiExprArg Args) {
493
494 // Form a reference to the promise.
495 ExprResult PromiseRef = S.BuildDeclRefExpr(
496 Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
497 if (PromiseRef.isInvalid())
498 return ExprError();
499
500 return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
501}
502
503VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
504 assert(isa<FunctionDecl>(CurContext) && "not in a function scope")(static_cast <bool> (isa<FunctionDecl>(CurContext
) && "not in a function scope") ? void (0) : __assert_fail
("isa<FunctionDecl>(CurContext) && \"not in a function scope\""
, "clang/lib/Sema/SemaCoroutine.cpp", 504, __extension__ __PRETTY_FUNCTION__
))
;
505 auto *FD = cast<FunctionDecl>(CurContext);
506 bool IsThisDependentType = [&] {
507 if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD))
508 return MD->isInstance() && MD->getThisType()->isDependentType();
509 else
510 return false;
511 }();
512
513 QualType T = FD->getType()->isDependentType() || IsThisDependentType
514 ? Context.DependentTy
515 : lookupPromiseType(*this, FD, Loc);
516 if (T.isNull())
517 return nullptr;
518
519 auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
520 &PP.getIdentifierTable().get("__promise"), T,
521 Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
522 VD->setImplicit();
523 CheckVariableDeclarationType(VD);
524 if (VD->isInvalidDecl())
525 return nullptr;
526
527 auto *ScopeInfo = getCurFunction();
528
529 // Build a list of arguments, based on the coroutine function's arguments,
530 // that if present will be passed to the promise type's constructor.
531 llvm::SmallVector<Expr *, 4> CtorArgExprs;
532
533 // Add implicit object parameter.
534 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
535 if (MD->isInstance() && !isLambdaCallOperator(MD)) {
536 ExprResult ThisExpr = ActOnCXXThis(Loc);
537 if (ThisExpr.isInvalid())
538 return nullptr;
539 ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
540 if (ThisExpr.isInvalid())
541 return nullptr;
542 CtorArgExprs.push_back(ThisExpr.get());
543 }
544 }
545
546 // Add the coroutine function's parameters.
547 auto &Moves = ScopeInfo->CoroutineParameterMoves;
548 for (auto *PD : FD->parameters()) {
549 if (PD->getType()->isDependentType())
550 continue;
551
552 auto RefExpr = ExprEmpty();
553 auto Move = Moves.find(PD);
554 assert(Move != Moves.end() &&(static_cast <bool> (Move != Moves.end() && "Coroutine function parameter not inserted into move map"
) ? void (0) : __assert_fail ("Move != Moves.end() && \"Coroutine function parameter not inserted into move map\""
, "clang/lib/Sema/SemaCoroutine.cpp", 555, __extension__ __PRETTY_FUNCTION__
))
555 "Coroutine function parameter not inserted into move map")(static_cast <bool> (Move != Moves.end() && "Coroutine function parameter not inserted into move map"
) ? void (0) : __assert_fail ("Move != Moves.end() && \"Coroutine function parameter not inserted into move map\""
, "clang/lib/Sema/SemaCoroutine.cpp", 555, __extension__ __PRETTY_FUNCTION__
))
;
556 // If a reference to the function parameter exists in the coroutine
557 // frame, use that reference.
558 auto *MoveDecl =
559 cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
560 RefExpr =
561 BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
562 ExprValueKind::VK_LValue, FD->getLocation());
563 if (RefExpr.isInvalid())
564 return nullptr;
565 CtorArgExprs.push_back(RefExpr.get());
566 }
567
568 // If we have a non-zero number of constructor arguments, try to use them.
569 // Otherwise, fall back to the promise type's default constructor.
570 if (!CtorArgExprs.empty()) {
571 // Create an initialization sequence for the promise type using the
572 // constructor arguments, wrapped in a parenthesized list expression.
573 Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(),
574 CtorArgExprs, FD->getLocation());
575 InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
576 InitializationKind Kind = InitializationKind::CreateForInit(
577 VD->getLocation(), /*DirectInit=*/true, PLE);
578 InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
579 /*TopLevelOfInitList=*/false,
580 /*TreatUnavailableAsInvalid=*/false);
581
582 // [dcl.fct.def.coroutine]5.7
583 // promise-constructor-arguments is determined as follows: overload
584 // resolution is performed on a promise constructor call created by
585 // assembling an argument list q_1 ... q_n . If a viable constructor is
586 // found ([over.match.viable]), then promise-constructor-arguments is ( q_1
587 // , ..., q_n ), otherwise promise-constructor-arguments is empty.
588 if (InitSeq) {
589 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
590 if (Result.isInvalid()) {
591 VD->setInvalidDecl();
592 } else if (Result.get()) {
593 VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
594 VD->setInitStyle(VarDecl::CallInit);
595 CheckCompleteVariableDeclaration(VD);
596 }
597 } else
598 ActOnUninitializedDecl(VD);
599 } else
600 ActOnUninitializedDecl(VD);
601
602 FD->addDecl(VD);
603 return VD;
604}
605
606/// Check that this is a context in which a coroutine suspension can appear.
607static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
608 StringRef Keyword,
609 bool IsImplicit = false) {
610 if (!isValidCoroutineContext(S, Loc, Keyword))
611 return nullptr;
612
613 assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope")(static_cast <bool> (isa<FunctionDecl>(S.CurContext
) && "not in a function scope") ? void (0) : __assert_fail
("isa<FunctionDecl>(S.CurContext) && \"not in a function scope\""
, "clang/lib/Sema/SemaCoroutine.cpp", 613, __extension__ __PRETTY_FUNCTION__
))
;
614
615 auto *ScopeInfo = S.getCurFunction();
616 assert(ScopeInfo && "missing function scope for function")(static_cast <bool> (ScopeInfo && "missing function scope for function"
) ? void (0) : __assert_fail ("ScopeInfo && \"missing function scope for function\""
, "clang/lib/Sema/SemaCoroutine.cpp", 616, __extension__ __PRETTY_FUNCTION__
))
;
617
618 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
619 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
620
621 if (ScopeInfo->CoroutinePromise)
622 return ScopeInfo;
623
624 if (!S.buildCoroutineParameterMoves(Loc))
625 return nullptr;
626
627 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
628 if (!ScopeInfo->CoroutinePromise)
629 return nullptr;
630
631 return ScopeInfo;
632}
633
634/// Recursively check \p E and all its children to see if any call target
635/// (including constructor call) is declared noexcept. Also any value returned
636/// from the call has a noexcept destructor.
637static void checkNoThrow(Sema &S, const Stmt *E,
638 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {
639 auto checkDeclNoexcept = [&](const Decl *D, bool IsDtor = false) {
640 // In the case of dtor, the call to dtor is implicit and hence we should
641 // pass nullptr to canCalleeThrow.
642 if (Sema::canCalleeThrow(S, IsDtor ? nullptr : cast<Expr>(E), D)) {
643 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
644 // co_await promise.final_suspend() could end up calling
645 // __builtin_coro_resume for symmetric transfer if await_suspend()
646 // returns a handle. In that case, even __builtin_coro_resume is not
647 // declared as noexcept and may throw, it does not throw _into_ the
648 // coroutine that just suspended, but rather throws back out from
649 // whoever called coroutine_handle::resume(), hence we claim that
650 // logically it does not throw.
651 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)
652 return;
653 }
654 if (ThrowingDecls.empty()) {
655 // [dcl.fct.def.coroutine]p15
656 // The expression co_await promise.final_suspend() shall not be
657 // potentially-throwing ([except.spec]).
658 //
659 // First time seeing an error, emit the error message.
660 S.Diag(cast<FunctionDecl>(S.CurContext)->getLocation(),
661 diag::err_coroutine_promise_final_suspend_requires_nothrow);
662 }
663 ThrowingDecls.insert(D);
664 }
665 };
666
667 if (auto *CE
13.1
'CE' is null
20.1
'CE' is null
= dyn_cast<CXXConstructExpr>(E)) {
13
Assuming 'E' is not a 'CXXConstructExpr'
14
Taking false branch
20
Assuming 'E' is not a 'CXXConstructExpr'
21
Taking false branch
668 CXXConstructorDecl *Ctor = CE->getConstructor();
669 checkDeclNoexcept(Ctor);
670 // Check the corresponding destructor of the constructor.
671 checkDeclNoexcept(Ctor->getParent()->getDestructor(), /*IsDtor=*/true);
672 } else if (auto *CE
15.1
'CE' is null
22.1
'CE' is non-null
= dyn_cast<CallExpr>(E)) {
15
Assuming 'E' is not a 'CallExpr'
16
Taking false branch
22
Assuming 'E' is a 'CallExpr'
23
Taking true branch
673 if (CE->isTypeDependent())
24
Assuming the condition is false
25
Taking false branch
674 return;
675
676 checkDeclNoexcept(CE->getCalleeDecl());
677 QualType ReturnType = CE->getCallReturnType(S.getASTContext());
678 // Check the destructor of the call return type, if any.
679 if (ReturnType.isDestructedType() ==
26
Assuming the condition is true
27
Taking true branch
680 QualType::DestructionKind::DK_cxx_destructor) {
681 const auto *T =
682 cast<RecordType>(ReturnType.getCanonicalType().getTypePtr());
28
The object is a 'RecordType'
683 checkDeclNoexcept(dyn_cast<CXXRecordDecl>(T->getDecl())->getDestructor(),
29
Assuming the object is not a 'CXXRecordDecl'
30
Called C++ object pointer is null
684 /*IsDtor=*/true);
685 }
686 } else
687 for (const auto *Child : E->children()) {
688 if (!Child)
17
Assuming 'Child' is non-null
18
Taking false branch
689 continue;
690 checkNoThrow(S, Child, ThrowingDecls);
19
Calling 'checkNoThrow'
691 }
692}
693
694bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
695 llvm::SmallPtrSet<const Decl *, 4> ThrowingDecls;
696 // We first collect all declarations that should not throw but not declared
697 // with noexcept. We then sort them based on the location before printing.
698 // This is to avoid emitting the same note multiple times on the same
699 // declaration, and also provide a deterministic order for the messages.
700 checkNoThrow(*this, FinalSuspend, ThrowingDecls);
12
Calling 'checkNoThrow'
701 auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(),
702 ThrowingDecls.end()};
703 sort(SortedDecls, [](const Decl *A, const Decl *B) {
704 return A->getEndLoc() < B->getEndLoc();
705 });
706 for (const auto *D : SortedDecls) {
707 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
708 }
709 return ThrowingDecls.empty();
710}
711
712bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
713 StringRef Keyword) {
714 if (!checkCoroutineContext(*this, KWLoc, Keyword))
2
Taking false branch
715 return false;
716 auto *ScopeInfo = getCurFunction();
717 assert(ScopeInfo->CoroutinePromise)(static_cast <bool> (ScopeInfo->CoroutinePromise) ? void
(0) : __assert_fail ("ScopeInfo->CoroutinePromise", "clang/lib/Sema/SemaCoroutine.cpp"
, 717, __extension__ __PRETTY_FUNCTION__))
;
3
Assuming field 'CoroutinePromise' is non-null
4
'?' condition is true
718
719 // If we have existing coroutine statements then we have already built
720 // the initial and final suspend points.
721 if (!ScopeInfo->NeedsCoroutineSuspends)
5
Assuming field 'NeedsCoroutineSuspends' is true
6
Taking false branch
722 return true;
723
724 ScopeInfo->setNeedsCoroutineSuspends(false);
725
726 auto *Fn = cast<FunctionDecl>(CurContext);
7
Field 'CurContext' is a 'FunctionDecl'
727 SourceLocation Loc = Fn->getLocation();
728 // Build the initial suspend point
729 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
730 ExprResult Suspend =
731 buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, None);
732 if (Suspend.isInvalid())
733 return StmtError();
734 Suspend = buildOperatorCoawaitCall(*this, SC, Loc, Suspend.get());
735 if (Suspend.isInvalid())
736 return StmtError();
737 Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
738 /*IsImplicit*/ true);
739 Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
740 if (Suspend.isInvalid()) {
741 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
742 << ((Name == "initial_suspend") ? 0 : 1);
743 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
744 return StmtError();
745 }
746 return cast<Stmt>(Suspend.get());
747 };
748
749 StmtResult InitSuspend = buildSuspends("initial_suspend");
750 if (InitSuspend.isInvalid())
8
Assuming the condition is false
9
Taking false branch
751 return true;
752
753 StmtResult FinalSuspend = buildSuspends("final_suspend");
754 if (FinalSuspend.isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.get()))
10
Assuming the condition is false
11
Calling 'Sema::checkFinalSuspendNoThrow'
755 return true;
756
757 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
758
759 return true;
760}
761
762// Recursively walks up the scope hierarchy until either a 'catch' or a function
763// scope is found, whichever comes first.
764static bool isWithinCatchScope(Scope *S) {
765 // 'co_await' and 'co_yield' keywords are disallowed within catch blocks, but
766 // lambdas that use 'co_await' are allowed. The loop below ends when a
767 // function scope is found in order to ensure the following behavior:
768 //
769 // void foo() { // <- function scope
770 // try { //
771 // co_await x; // <- 'co_await' is OK within a function scope
772 // } catch { // <- catch scope
773 // co_await x; // <- 'co_await' is not OK within a catch scope
774 // []() { // <- function scope
775 // co_await x; // <- 'co_await' is OK within a function scope
776 // }();
777 // }
778 // }
779 while (S && !(S->getFlags() & Scope::FnScope)) {
780 if (S->getFlags() & Scope::CatchScope)
781 return true;
782 S = S->getParent();
783 }
784 return false;
785}
786
787// [expr.await]p2, emphasis added: "An await-expression shall appear only in
788// a *potentially evaluated* expression within the compound-statement of a
789// function-body *outside of a handler* [...] A context within a function
790// where an await-expression can appear is called a suspension context of the
791// function."
792static void checkSuspensionContext(Sema &S, SourceLocation Loc,
793 StringRef Keyword) {
794 // First emphasis of [expr.await]p2: must be a potentially evaluated context.
795 // That is, 'co_await' and 'co_yield' cannot appear in subexpressions of
796 // \c sizeof.
797 if (S.isUnevaluatedContext())
798 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
799
800 // Second emphasis of [expr.await]p2: must be outside of an exception handler.
801 if (isWithinCatchScope(S.getCurScope()))
802 S.Diag(Loc, diag::err_coroutine_within_handler) << Keyword;
803}
804
805ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
806 if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
807 CorrectDelayedTyposInExpr(E);
808 return ExprError();
809 }
810
811 checkSuspensionContext(*this, Loc, "co_await");
812
813 if (E->hasPlaceholderType()) {
814 ExprResult R = CheckPlaceholderExpr(E);
815 if (R.isInvalid()) return ExprError();
816 E = R.get();
817 }
818 ExprResult Lookup = buildOperatorCoawaitLookupExpr(*this, S, Loc);
819 if (Lookup.isInvalid())
820 return ExprError();
821 return BuildUnresolvedCoawaitExpr(Loc, E,
822 cast<UnresolvedLookupExpr>(Lookup.get()));
823}
824
825ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
826 UnresolvedLookupExpr *Lookup) {
827 auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
828 if (!FSI)
829 return ExprError();
830
831 if (E->hasPlaceholderType()) {
832 ExprResult R = CheckPlaceholderExpr(E);
833 if (R.isInvalid())
834 return ExprError();
835 E = R.get();
836 }
837
838 auto *Promise = FSI->CoroutinePromise;
839 if (Promise->getType()->isDependentType()) {
840 Expr *Res =
841 new (Context) DependentCoawaitExpr(Loc, Context.DependentTy, E, Lookup);
842 return Res;
843 }
844
845 auto *RD = Promise->getType()->getAsCXXRecordDecl();
846 if (lookupMember(*this, "await_transform", RD, Loc)) {
847 ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E);
848 if (R.isInvalid()) {
849 Diag(Loc,
850 diag::note_coroutine_promise_implicit_await_transform_required_here)
851 << E->getSourceRange();
852 return ExprError();
853 }
854 E = R.get();
855 }
856 ExprResult Awaitable = buildOperatorCoawaitCall(*this, Loc, E, Lookup);
857 if (Awaitable.isInvalid())
858 return ExprError();
859
860 return BuildResolvedCoawaitExpr(Loc, Awaitable.get());
861}
862
863ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
864 bool IsImplicit) {
865 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
866 if (!Coroutine)
867 return ExprError();
868
869 if (E->hasPlaceholderType()) {
870 ExprResult R = CheckPlaceholderExpr(E);
871 if (R.isInvalid()) return ExprError();
872 E = R.get();
873 }
874
875 if (E->getType()->isDependentType()) {
876 Expr *Res = new (Context)
877 CoawaitExpr(Loc, Context.DependentTy, E, IsImplicit);
878 return Res;
879 }
880
881 // If the expression is a temporary, materialize it as an lvalue so that we
882 // can use it multiple times.
883 if (E->isPRValue())
884 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
885
886 // The location of the `co_await` token cannot be used when constructing
887 // the member call expressions since it's before the location of `Expr`, which
888 // is used as the start of the member call expression.
889 SourceLocation CallLoc = E->getExprLoc();
890
891 // Build the await_ready, await_suspend, await_resume calls.
892 ReadySuspendResumeResult RSS = buildCoawaitCalls(
893 *this, Coroutine->CoroutinePromise, CallLoc, E);
894 if (RSS.IsInvalid)
895 return ExprError();
896
897 Expr *Res =
898 new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
899 RSS.Results[2], RSS.OpaqueValue, IsImplicit);
900
901 return Res;
902}
903
904ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
905 if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
906 CorrectDelayedTyposInExpr(E);
907 return ExprError();
908 }
909
910 checkSuspensionContext(*this, Loc, "co_yield");
911
912 // Build yield_value call.
913 ExprResult Awaitable = buildPromiseCall(
914 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
915 if (Awaitable.isInvalid())
916 return ExprError();
917
918 // Build 'operator co_await' call.
919 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
920 if (Awaitable.isInvalid())
921 return ExprError();
922
923 return BuildCoyieldExpr(Loc, Awaitable.get());
924}
925ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
926 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
927 if (!Coroutine)
928 return ExprError();
929
930 if (E->hasPlaceholderType()) {
931 ExprResult R = CheckPlaceholderExpr(E);
932 if (R.isInvalid()) return ExprError();
933 E = R.get();
934 }
935
936 if (E->getType()->isDependentType()) {
937 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
938 return Res;
939 }
940
941 // If the expression is a temporary, materialize it as an lvalue so that we
942 // can use it multiple times.
943 if (E->isPRValue())
944 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
945
946 // Build the await_ready, await_suspend, await_resume calls.
947 ReadySuspendResumeResult RSS = buildCoawaitCalls(
948 *this, Coroutine->CoroutinePromise, Loc, E);
949 if (RSS.IsInvalid)
950 return ExprError();
951
952 Expr *Res =
953 new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
954 RSS.Results[2], RSS.OpaqueValue);
955
956 return Res;
957}
958
959StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
960 if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
1
Calling 'Sema::ActOnCoroutineBodyStart'
961 CorrectDelayedTyposInExpr(E);
962 return StmtError();
963 }
964 return BuildCoreturnStmt(Loc, E);
965}
966
967StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
968 bool IsImplicit) {
969 auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
970 if (!FSI)
971 return StmtError();
972
973 if (E && E->hasPlaceholderType() &&
974 !E->hasPlaceholderType(BuiltinType::Overload)) {
975 ExprResult R = CheckPlaceholderExpr(E);
976 if (R.isInvalid()) return StmtError();
977 E = R.get();
978 }
979
980 VarDecl *Promise = FSI->CoroutinePromise;
981 ExprResult PC;
982 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
983 getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn);
984 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
985 } else {
986 E = MakeFullDiscardedValueExpr(E).get();
987 PC = buildPromiseCall(*this, Promise, Loc, "return_void", None);
988 }
989 if (PC.isInvalid())
990 return StmtError();
991
992 Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
993
994 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
995 return Res;
996}
997
998/// Look up the std::nothrow object.
999static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) {
1000 NamespaceDecl *Std = S.getStdNamespace();
1001 assert(Std && "Should already be diagnosed")(static_cast <bool> (Std && "Should already be diagnosed"
) ? void (0) : __assert_fail ("Std && \"Should already be diagnosed\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1001, __extension__ __PRETTY_FUNCTION__
))
;
1002
1003 LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc,
1004 Sema::LookupOrdinaryName);
1005 if (!S.LookupQualifiedName(Result, Std)) {
1006 // <coroutine> is not requred to include <new>, so we couldn't omit
1007 // the check here.
1008 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
1009 return nullptr;
1010 }
1011
1012 auto *VD = Result.getAsSingle<VarDecl>();
1013 if (!VD) {
1014 Result.suppressDiagnostics();
1015 // We found something weird. Complain about the first thing we found.
1016 NamedDecl *Found = *Result.begin();
1017 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);
1018 return nullptr;
1019 }
1020
1021 ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc);
1022 if (DR.isInvalid())
1023 return nullptr;
1024
1025 return DR.get();
1026}
1027
1028// Find an appropriate delete for the promise.
1029static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
1030 QualType PromiseType) {
1031 FunctionDecl *OperatorDelete = nullptr;
1032
1033 DeclarationName DeleteName =
1034 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
1035
1036 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
1037 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type")(static_cast <bool> (PointeeRD && "PromiseType must be a CxxRecordDecl type"
) ? void (0) : __assert_fail ("PointeeRD && \"PromiseType must be a CxxRecordDecl type\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1037, __extension__ __PRETTY_FUNCTION__
))
;
1038
1039 // [dcl.fct.def.coroutine]p12
1040 // The deallocation function's name is looked up by searching for it in the
1041 // scope of the promise type. If nothing is found, a search is performed in
1042 // the global scope.
1043 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
1044 return nullptr;
1045
1046 // FIXME: We didn't implement following selection:
1047 // [dcl.fct.def.coroutine]p12
1048 // If both a usual deallocation function with only a pointer parameter and a
1049 // usual deallocation function with both a pointer parameter and a size
1050 // parameter are found, then the selected deallocation function shall be the
1051 // one with two parameters. Otherwise, the selected deallocation function
1052 // shall be the function with one parameter.
1053
1054 if (!OperatorDelete) {
1055 // Look for a global declaration.
1056 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
1057 const bool Overaligned = false;
1058 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
1059 Overaligned, DeleteName);
1060 }
1061 S.MarkFunctionReferenced(Loc, OperatorDelete);
1062 return OperatorDelete;
1063}
1064
1065
1066void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
1067 FunctionScopeInfo *Fn = getCurFunction();
1068 assert(Fn && Fn->isCoroutine() && "not a coroutine")(static_cast <bool> (Fn && Fn->isCoroutine()
&& "not a coroutine") ? void (0) : __assert_fail ("Fn && Fn->isCoroutine() && \"not a coroutine\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1068, __extension__ __PRETTY_FUNCTION__
))
;
1069 if (!Body) {
1070 assert(FD->isInvalidDecl() &&(static_cast <bool> (FD->isInvalidDecl() && "a null body is only allowed for invalid declarations"
) ? void (0) : __assert_fail ("FD->isInvalidDecl() && \"a null body is only allowed for invalid declarations\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1071, __extension__ __PRETTY_FUNCTION__
))
1071 "a null body is only allowed for invalid declarations")(static_cast <bool> (FD->isInvalidDecl() && "a null body is only allowed for invalid declarations"
) ? void (0) : __assert_fail ("FD->isInvalidDecl() && \"a null body is only allowed for invalid declarations\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1071, __extension__ __PRETTY_FUNCTION__
))
;
1072 return;
1073 }
1074 // We have a function that uses coroutine keywords, but we failed to build
1075 // the promise type.
1076 if (!Fn->CoroutinePromise)
1077 return FD->setInvalidDecl();
1078
1079 if (isa<CoroutineBodyStmt>(Body)) {
1080 // Nothing todo. the body is already a transformed coroutine body statement.
1081 return;
1082 }
1083
1084 // The always_inline attribute doesn't reliably apply to a coroutine,
1085 // because the coroutine will be split into pieces and some pieces
1086 // might be called indirectly, as in a virtual call. Even the ramp
1087 // function cannot be inlined at -O0, due to pipeline ordering
1088 // problems (see https://llvm.org/PR53413). Tell the user about it.
1089 if (FD->hasAttr<AlwaysInlineAttr>())
1090 Diag(FD->getLocation(), diag::warn_always_inline_coroutine);
1091
1092 // [stmt.return.coroutine]p1:
1093 // A coroutine shall not enclose a return statement ([stmt.return]).
1094 if (Fn->FirstReturnLoc.isValid()) {
1095 assert(Fn->FirstCoroutineStmtLoc.isValid() &&(static_cast <bool> (Fn->FirstCoroutineStmtLoc.isValid
() && "first coroutine location not set") ? void (0) :
__assert_fail ("Fn->FirstCoroutineStmtLoc.isValid() && \"first coroutine location not set\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1096, __extension__ __PRETTY_FUNCTION__
))
1096 "first coroutine location not set")(static_cast <bool> (Fn->FirstCoroutineStmtLoc.isValid
() && "first coroutine location not set") ? void (0) :
__assert_fail ("Fn->FirstCoroutineStmtLoc.isValid() && \"first coroutine location not set\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1096, __extension__ __PRETTY_FUNCTION__
))
;
1097 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
1098 Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1099 << Fn->getFirstCoroutineStmtKeyword();
1100 }
1101 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
1102 if (Builder.isInvalid() || !Builder.buildStatements())
1103 return FD->setInvalidDecl();
1104
1105 // Build body for the coroutine wrapper statement.
1106 Body = CoroutineBodyStmt::Create(Context, Builder);
1107}
1108
1109CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
1110 sema::FunctionScopeInfo &Fn,
1111 Stmt *Body)
1112 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1113 IsPromiseDependentType(
1114 !Fn.CoroutinePromise ||
1115 Fn.CoroutinePromise->getType()->isDependentType()) {
1116 this->Body = Body;
1117
1118 for (auto KV : Fn.CoroutineParameterMoves)
1119 this->ParamMovesVector.push_back(KV.second);
1120 this->ParamMoves = this->ParamMovesVector;
1121
1122 if (!IsPromiseDependentType) {
1123 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
1124 assert(PromiseRecordDecl && "Type should have already been checked")(static_cast <bool> (PromiseRecordDecl && "Type should have already been checked"
) ? void (0) : __assert_fail ("PromiseRecordDecl && \"Type should have already been checked\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1124, __extension__ __PRETTY_FUNCTION__
))
;
1125 }
1126 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1127}
1128
1129bool CoroutineStmtBuilder::buildStatements() {
1130 assert(this->IsValid && "coroutine already invalid")(static_cast <bool> (this->IsValid && "coroutine already invalid"
) ? void (0) : __assert_fail ("this->IsValid && \"coroutine already invalid\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1130, __extension__ __PRETTY_FUNCTION__
))
;
1131 this->IsValid = makeReturnObject();
1132 if (this->IsValid && !IsPromiseDependentType)
1133 buildDependentStatements();
1134 return this->IsValid;
1135}
1136
1137bool CoroutineStmtBuilder::buildDependentStatements() {
1138 assert(this->IsValid && "coroutine already invalid")(static_cast <bool> (this->IsValid && "coroutine already invalid"
) ? void (0) : __assert_fail ("this->IsValid && \"coroutine already invalid\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1138, __extension__ __PRETTY_FUNCTION__
))
;
1139 assert(!this->IsPromiseDependentType &&(static_cast <bool> (!this->IsPromiseDependentType &&
"coroutine cannot have a dependent promise type") ? void (0)
: __assert_fail ("!this->IsPromiseDependentType && \"coroutine cannot have a dependent promise type\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1140, __extension__ __PRETTY_FUNCTION__
))
1140 "coroutine cannot have a dependent promise type")(static_cast <bool> (!this->IsPromiseDependentType &&
"coroutine cannot have a dependent promise type") ? void (0)
: __assert_fail ("!this->IsPromiseDependentType && \"coroutine cannot have a dependent promise type\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1140, __extension__ __PRETTY_FUNCTION__
))
;
1141 this->IsValid = makeOnException() && makeOnFallthrough() &&
1142 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1143 makeNewAndDeleteExpr();
1144 return this->IsValid;
1145}
1146
1147bool CoroutineStmtBuilder::makePromiseStmt() {
1148 // Form a declaration statement for the promise declaration, so that AST
1149 // visitors can more easily find it.
1150 StmtResult PromiseStmt =
1151 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc);
1152 if (PromiseStmt.isInvalid())
1153 return false;
1154
1155 this->Promise = PromiseStmt.get();
1156 return true;
1157}
1158
1159bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1160 if (Fn.hasInvalidCoroutineSuspends())
1161 return false;
1162 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first);
1163 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
1164 return true;
1165}
1166
1167static bool diagReturnOnAllocFailure(Sema &S, Expr *E,
1168 CXXRecordDecl *PromiseRecordDecl,
1169 FunctionScopeInfo &Fn) {
1170 auto Loc = E->getExprLoc();
1171 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1172 auto *Decl = DeclRef->getDecl();
1173 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) {
1174 if (Method->isStatic())
1175 return true;
1176 else
1177 Loc = Decl->getLocation();
1178 }
1179 }
1180
1181 S.Diag(
1182 Loc,
1183 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1184 << PromiseRecordDecl;
1185 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1186 << Fn.getFirstCoroutineStmtKeyword();
1187 return false;
1188}
1189
1190bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1191 assert(!IsPromiseDependentType &&(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1192, __extension__ __PRETTY_FUNCTION__
))
1192 "cannot make statement while the promise type is dependent")(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1192, __extension__ __PRETTY_FUNCTION__
))
;
1193
1194 // [dcl.fct.def.coroutine]p10
1195 // If a search for the name get_return_object_on_allocation_failure in
1196 // the scope of the promise type ([class.member.lookup]) finds any
1197 // declarations, then the result of a call to an allocation function used to
1198 // obtain storage for the coroutine state is assumed to return nullptr if it
1199 // fails to obtain storage, ... If the allocation function returns nullptr,
1200 // ... and the return value is obtained by a call to
1201 // T::get_return_object_on_allocation_failure(), where T is the
1202 // promise type.
1203 DeclarationName DN =
1204 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");
1205 LookupResult Found(S, DN, Loc, Sema::LookupMemberName);
1206 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))
1207 return true;
1208
1209 CXXScopeSpec SS;
1210 ExprResult DeclNameExpr =
1211 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
1212 if (DeclNameExpr.isInvalid())
1213 return false;
1214
1215 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn))
1216 return false;
1217
1218 ExprResult ReturnObjectOnAllocationFailure =
1219 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
1220 if (ReturnObjectOnAllocationFailure.isInvalid())
1221 return false;
1222
1223 StmtResult ReturnStmt =
1224 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
1225 if (ReturnStmt.isInvalid()) {
1226 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1227 << DN;
1228 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1229 << Fn.getFirstCoroutineStmtKeyword();
1230 return false;
1231 }
1232
1233 this->ReturnStmtOnAllocFailure = ReturnStmt.get();
1234 return true;
1235}
1236
1237bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1238 // Form and check allocation and deallocation calls.
1239 assert(!IsPromiseDependentType &&(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1240, __extension__ __PRETTY_FUNCTION__
))
1240 "cannot make statement while the promise type is dependent")(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1240, __extension__ __PRETTY_FUNCTION__
))
;
1241 QualType PromiseType = Fn.CoroutinePromise->getType();
1242
1243 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
1244 return false;
1245
1246 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
1247
1248 // According to [dcl.fct.def.coroutine]p9, Lookup allocation functions using a
1249 // parameter list composed of the requested size of the coroutine state being
1250 // allocated, followed by the coroutine function's arguments. If a matching
1251 // allocation function exists, use it. Otherwise, use an allocation function
1252 // that just takes the requested size.
1253
1254 FunctionDecl *OperatorNew = nullptr;
1255 FunctionDecl *OperatorDelete = nullptr;
1256 FunctionDecl *UnusedResult = nullptr;
1257 bool PassAlignment = false;
1258 SmallVector<Expr *, 1> PlacementArgs;
1259
1260 // [dcl.fct.def.coroutine]p9
1261 // An implementation may need to allocate additional storage for a
1262 // coroutine.
1263 // This storage is known as the coroutine state and is obtained by calling a
1264 // non-array allocation function ([basic.stc.dynamic.allocation]). The
1265 // allocation function's name is looked up by searching for it in the scope of
1266 // the promise type.
1267 // - If any declarations are found, overload resolution is performed on a
1268 // function call created by assembling an argument list. The first argument is
1269 // the amount of space requested, and has type std::size_t. The
1270 // lvalues p1 ... pn are the succeeding arguments.
1271 //
1272 // ...where "p1 ... pn" are defined earlier as:
1273 //
1274 // [dcl.fct.def.coroutine]p3
1275 // The promise type of a coroutine is `std::coroutine_traits<R, P1, ...,
1276 // Pn>`
1277 // , where R is the return type of the function, and `P1, ..., Pn` are the
1278 // sequence of types of the non-object function parameters, preceded by the
1279 // type of the object parameter ([dcl.fct]) if the coroutine is a non-static
1280 // member function. [dcl.fct.def.coroutine]p4 In the following, p_i is an
1281 // lvalue of type P_i, where p1 denotes the object parameter and p_i+1 denotes
1282 // the i-th non-object function parameter for a non-static member function,
1283 // and p_i denotes the i-th function parameter otherwise. For a non-static
1284 // member function, q_1 is an lvalue that denotes *this; any other q_i is an
1285 // lvalue that denotes the parameter copy corresponding to p_i.
1286 if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1287 if (MD->isInstance() && !isLambdaCallOperator(MD)) {
1288 ExprResult ThisExpr = S.ActOnCXXThis(Loc);
1289 if (ThisExpr.isInvalid())
1290 return false;
1291 ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
1292 if (ThisExpr.isInvalid())
1293 return false;
1294 PlacementArgs.push_back(ThisExpr.get());
1295 }
1296 }
1297 for (auto *PD : FD.parameters()) {
1298 if (PD->getType()->isDependentType())
1299 continue;
1300
1301 // Build a reference to the parameter.
1302 auto PDLoc = PD->getLocation();
1303 ExprResult PDRefExpr =
1304 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
1305 ExprValueKind::VK_LValue, PDLoc);
1306 if (PDRefExpr.isInvalid())
1307 return false;
1308
1309 PlacementArgs.push_back(PDRefExpr.get());
1310 }
1311 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
1312 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1313 /*isArray*/ false, PassAlignment, PlacementArgs,
1314 OperatorNew, UnusedResult, /*Diagnose*/ false);
1315
1316 // [dcl.fct.def.coroutine]p9
1317 // If no viable function is found ([over.match.viable]), overload resolution
1318 // is performed again on a function call created by passing just the amount of
1319 // space required as an argument of type std::size_t.
1320 if (!OperatorNew && !PlacementArgs.empty()) {
1321 PlacementArgs.clear();
1322 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
1323 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1324 /*isArray*/ false, PassAlignment, PlacementArgs,
1325 OperatorNew, UnusedResult, /*Diagnose*/ false);
1326 }
1327
1328 // [dcl.fct.def.coroutine]p9
1329 // The allocation function's name is looked up by searching for it in the
1330 // scope of the promise type.
1331 // - If any declarations are found, ...
1332 // - Otherwise, a search is performed in the global scope.
1333 if (!OperatorNew) {
1334 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Global,
1335 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1336 /*isArray*/ false, PassAlignment, PlacementArgs,
1337 OperatorNew, UnusedResult);
1338 }
1339
1340 bool IsGlobalOverload =
1341 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
1342 // If we didn't find a class-local new declaration and non-throwing new
1343 // was is required then we need to lookup the non-throwing global operator
1344 // instead.
1345 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
1346 auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc);
1347 if (!StdNoThrow)
1348 return false;
1349 PlacementArgs = {StdNoThrow};
1350 OperatorNew = nullptr;
1351 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
1352 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1353 /*isArray*/ false, PassAlignment, PlacementArgs,
1354 OperatorNew, UnusedResult);
1355 }
1356
1357 if (!OperatorNew)
1358 return false;
1359
1360 if (RequiresNoThrowAlloc) {
1361 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();
1362 if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
1363 S.Diag(OperatorNew->getLocation(),
1364 diag::err_coroutine_promise_new_requires_nothrow)
1365 << OperatorNew;
1366 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1367 << OperatorNew;
1368 return false;
1369 }
1370 }
1371
1372 if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr) {
1373 // FIXME: We should add an error here. According to:
1374 // [dcl.fct.def.coroutine]p12
1375 // If no usual deallocation function is found, the program is ill-formed.
1376 return false;
1377 }
1378
1379 Expr *FramePtr =
1380 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
1381
1382 Expr *FrameSize =
1383 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
1384
1385 // Make new call.
1386
1387 ExprResult NewRef =
1388 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
1389 if (NewRef.isInvalid())
1390 return false;
1391
1392 SmallVector<Expr *, 2> NewArgs(1, FrameSize);
1393 for (auto Arg : PlacementArgs)
1394 NewArgs.push_back(Arg);
1395
1396 ExprResult NewExpr =
1397 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
1398 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
1399 if (NewExpr.isInvalid())
1400 return false;
1401
1402 // Make delete call.
1403
1404 QualType OpDeleteQualType = OperatorDelete->getType();
1405
1406 ExprResult DeleteRef =
1407 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
1408 if (DeleteRef.isInvalid())
1409 return false;
1410
1411 Expr *CoroFree =
1412 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
1413
1414 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
1415
1416 // [dcl.fct.def.coroutine]p12
1417 // The selected deallocation function shall be called with the address of
1418 // the block of storage to be reclaimed as its first argument. If a
1419 // deallocation function with a parameter of type std::size_t is
1420 // used, the size of the block is passed as the corresponding argument.
1421 const auto *OpDeleteType =
1422 OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
1423 if (OpDeleteType->getNumParams() > 1)
1424 DeleteArgs.push_back(FrameSize);
1425
1426 ExprResult DeleteExpr =
1427 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
1428 DeleteExpr =
1429 S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
1430 if (DeleteExpr.isInvalid())
1431 return false;
1432
1433 this->Allocate = NewExpr.get();
1434 this->Deallocate = DeleteExpr.get();
1435
1436 return true;
1437}
1438
1439bool CoroutineStmtBuilder::makeOnFallthrough() {
1440 assert(!IsPromiseDependentType &&(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1441, __extension__ __PRETTY_FUNCTION__
))
1441 "cannot make statement while the promise type is dependent")(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1441, __extension__ __PRETTY_FUNCTION__
))
;
1442
1443 // [dcl.fct.def.coroutine]/p6
1444 // If searches for the names return_void and return_value in the scope of
1445 // the promise type each find any declarations, the program is ill-formed.
1446 // [Note 1: If return_void is found, flowing off the end of a coroutine is
1447 // equivalent to a co_return with no operand. Otherwise, flowing off the end
1448 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
1449 // end note]
1450 bool HasRVoid, HasRValue;
1451 LookupResult LRVoid =
1452 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
1453 LookupResult LRValue =
1454 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
1455
1456 StmtResult Fallthrough;
1457 if (HasRVoid && HasRValue) {
1458 // FIXME Improve this diagnostic
1459 S.Diag(FD.getLocation(),
1460 diag::err_coroutine_promise_incompatible_return_functions)
1461 << PromiseRecordDecl;
1462 S.Diag(LRVoid.getRepresentativeDecl()->getLocation(),
1463 diag::note_member_first_declared_here)
1464 << LRVoid.getLookupName();
1465 S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
1466 diag::note_member_first_declared_here)
1467 << LRValue.getLookupName();
1468 return false;
1469 } else if (!HasRVoid && !HasRValue) {
1470 // We need to set 'Fallthrough'. Otherwise the other analysis part might
1471 // think the coroutine has defined a return_value method. So it might emit
1472 // **false** positive warning. e.g.,
1473 //
1474 // promise_without_return_func foo() {
1475 // co_await something();
1476 // }
1477 //
1478 // Then AnalysisBasedWarning would emit a warning about `foo()` lacking a
1479 // co_return statements, which isn't correct.
1480 Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());
1481 if (Fallthrough.isInvalid())
1482 return false;
1483 } else if (HasRVoid) {
1484 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
1485 /*IsImplicit*/false);
1486 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
1487 if (Fallthrough.isInvalid())
1488 return false;
1489 }
1490
1491 this->OnFallthrough = Fallthrough.get();
1492 return true;
1493}
1494
1495bool CoroutineStmtBuilder::makeOnException() {
1496 // Try to form 'p.unhandled_exception();'
1497 assert(!IsPromiseDependentType &&(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1498, __extension__ __PRETTY_FUNCTION__
))
1498 "cannot make statement while the promise type is dependent")(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1498, __extension__ __PRETTY_FUNCTION__
))
;
1499
1500 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
1501
1502 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
1503 auto DiagID =
1504 RequireUnhandledException
1505 ? diag::err_coroutine_promise_unhandled_exception_required
1506 : diag::
1507 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1508 S.Diag(Loc, DiagID) << PromiseRecordDecl;
1509 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1510 << PromiseRecordDecl;
1511 return !RequireUnhandledException;
1512 }
1513
1514 // If exceptions are disabled, don't try to build OnException.
1515 if (!S.getLangOpts().CXXExceptions)
1516 return true;
1517
1518 ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
1519 "unhandled_exception", None);
1520 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
1521 /*DiscardedValue*/ false);
1522 if (UnhandledException.isInvalid())
1523 return false;
1524
1525 // Since the body of the coroutine will be wrapped in try-catch, it will
1526 // be incompatible with SEH __try if present in a function.
1527 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
1528 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
1529 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1530 << Fn.getFirstCoroutineStmtKeyword();
1531 return false;
1532 }
1533
1534 this->OnException = UnhandledException.get();
1535 return true;
1536}
1537
1538bool CoroutineStmtBuilder::makeReturnObject() {
1539 // [dcl.fct.def.coroutine]p7
1540 // The expression promise.get_return_object() is used to initialize the
1541 // returned reference or prvalue result object of a call to a coroutine.
1542 ExprResult ReturnObject =
1543 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
1544 if (ReturnObject.isInvalid())
1545 return false;
1546
1547 this->ReturnValue = ReturnObject.get();
1548 return true;
1549}
1550
1551static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn) {
1552 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1553 auto *MethodDecl = MbrRef->getMethodDecl();
1554 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1555 << MethodDecl;
1556 }
1557 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1558 << Fn.getFirstCoroutineStmtKeyword();
1559}
1560
1561bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1562 assert(!IsPromiseDependentType &&(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1563, __extension__ __PRETTY_FUNCTION__
))
1563 "cannot make statement while the promise type is dependent")(static_cast <bool> (!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent")
? void (0) : __assert_fail ("!IsPromiseDependentType && \"cannot make statement while the promise type is dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1563, __extension__ __PRETTY_FUNCTION__
))
;
1564 assert(this->ReturnValue && "ReturnValue must be already formed")(static_cast <bool> (this->ReturnValue && "ReturnValue must be already formed"
) ? void (0) : __assert_fail ("this->ReturnValue && \"ReturnValue must be already formed\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1564, __extension__ __PRETTY_FUNCTION__
))
;
1565
1566 QualType const GroType = this->ReturnValue->getType();
1567 assert(!GroType->isDependentType() &&(static_cast <bool> (!GroType->isDependentType() &&
"get_return_object type must no longer be dependent") ? void
(0) : __assert_fail ("!GroType->isDependentType() && \"get_return_object type must no longer be dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1568, __extension__ __PRETTY_FUNCTION__
))
1568 "get_return_object type must no longer be dependent")(static_cast <bool> (!GroType->isDependentType() &&
"get_return_object type must no longer be dependent") ? void
(0) : __assert_fail ("!GroType->isDependentType() && \"get_return_object type must no longer be dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1568, __extension__ __PRETTY_FUNCTION__
))
;
1569
1570 QualType const FnRetType = FD.getReturnType();
1571 assert(!FnRetType->isDependentType() &&(static_cast <bool> (!FnRetType->isDependentType() &&
"get_return_object type must no longer be dependent") ? void
(0) : __assert_fail ("!FnRetType->isDependentType() && \"get_return_object type must no longer be dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1572, __extension__ __PRETTY_FUNCTION__
))
1572 "get_return_object type must no longer be dependent")(static_cast <bool> (!FnRetType->isDependentType() &&
"get_return_object type must no longer be dependent") ? void
(0) : __assert_fail ("!FnRetType->isDependentType() && \"get_return_object type must no longer be dependent\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1572, __extension__ __PRETTY_FUNCTION__
))
;
1573
1574 if (FnRetType->isVoidType()) {
1575 ExprResult Res =
1576 S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
1577 if (Res.isInvalid())
1578 return false;
1579
1580 this->ResultDecl = Res.get();
1581 return true;
1582 }
1583
1584 if (GroType->isVoidType()) {
1585 // Trigger a nice error message.
1586 InitializedEntity Entity =
1587 InitializedEntity::InitializeResult(Loc, FnRetType);
1588 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1589 noteMemberDeclaredHere(S, ReturnValue, Fn);
1590 return false;
1591 }
1592
1593 auto *GroDecl = VarDecl::Create(
1594 S.Context, &FD, FD.getLocation(), FD.getLocation(),
1595 &S.PP.getIdentifierTable().get("__coro_gro"), GroType,
1596 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
1597 GroDecl->setImplicit();
1598
1599 S.CheckVariableDeclarationType(GroDecl);
1600 if (GroDecl->isInvalidDecl())
1601 return false;
1602
1603 InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
1604 ExprResult Res =
1605 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1606 if (Res.isInvalid())
1607 return false;
1608
1609 Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
1610 if (Res.isInvalid())
1611 return false;
1612
1613 S.AddInitializerToDecl(GroDecl, Res.get(),
1614 /*DirectInit=*/false);
1615
1616 S.FinalizeDeclaration(GroDecl);
1617
1618 // Form a declaration statement for the return declaration, so that AST
1619 // visitors can more easily find it.
1620 StmtResult GroDeclStmt =
1621 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
1622 if (GroDeclStmt.isInvalid())
1623 return false;
1624
1625 this->ResultDecl = GroDeclStmt.get();
1626
1627 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
1628 if (declRef.isInvalid())
1629 return false;
1630
1631 StmtResult ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
1632 if (ReturnStmt.isInvalid()) {
1633 noteMemberDeclaredHere(S, ReturnValue, Fn);
1634 return false;
1635 }
1636 if (cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
1637 GroDecl->setNRVOVariable(true);
1638
1639 this->ReturnStmt = ReturnStmt.get();
1640 return true;
1641}
1642
1643// Create a static_cast\<T&&>(expr).
1644static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
1645 if (T.isNull())
1646 T = E->getType();
1647 QualType TargetType = S.BuildReferenceType(
1648 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
1649 SourceLocation ExprLoc = E->getBeginLoc();
1650 TypeSourceInfo *TargetLoc =
1651 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
1652
1653 return S
1654 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
1655 SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
1656 .get();
1657}
1658
1659/// Build a variable declaration for move parameter.
1660static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type,
1661 IdentifierInfo *II) {
1662 TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc);
1663 VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
1664 TInfo, SC_None);
1665 Decl->setImplicit();
1666 return Decl;
1667}
1668
1669// Build statements that move coroutine function parameters to the coroutine
1670// frame, and store them on the function scope info.
1671bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
1672 assert(isa<FunctionDecl>(CurContext) && "not in a function scope")(static_cast <bool> (isa<FunctionDecl>(CurContext
) && "not in a function scope") ? void (0) : __assert_fail
("isa<FunctionDecl>(CurContext) && \"not in a function scope\""
, "clang/lib/Sema/SemaCoroutine.cpp", 1672, __extension__ __PRETTY_FUNCTION__
))
;
1673 auto *FD = cast<FunctionDecl>(CurContext);
1674
1675 auto *ScopeInfo = getCurFunction();
1676 if (!ScopeInfo->CoroutineParameterMoves.empty())
1677 return false;
1678
1679 // [dcl.fct.def.coroutine]p13
1680 // When a coroutine is invoked, after initializing its parameters
1681 // ([expr.call]), a copy is created for each coroutine parameter. For a
1682 // parameter of type cv T, the copy is a variable of type cv T with
1683 // automatic storage duration that is direct-initialized from an xvalue of
1684 // type T referring to the parameter.
1685 for (auto *PD : FD->parameters()) {
1686 if (PD->getType()->isDependentType())
1687 continue;
1688
1689 ExprResult PDRefExpr =
1690 BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
1691 ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1692 if (PDRefExpr.isInvalid())
1693 return false;
1694
1695 Expr *CExpr = nullptr;
1696 if (PD->getType()->getAsCXXRecordDecl() ||
1697 PD->getType()->isRValueReferenceType())
1698 CExpr = castForMoving(*this, PDRefExpr.get());
1699 else
1700 CExpr = PDRefExpr.get();
1701 // [dcl.fct.def.coroutine]p13
1702 // The initialization and destruction of each parameter copy occurs in the
1703 // context of the called coroutine.
1704 auto D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
1705 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
1706
1707 // Convert decl to a statement.
1708 StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc, Loc);
1709 if (Stmt.isInvalid())
1710 return false;
1711
1712 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
1713 }
1714 return true;
1715}
1716
1717StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
1718 CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args);
1719 if (!Res)
1720 return StmtError();
1721 return Res;
1722}
1723
1724ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
1725 SourceLocation FuncLoc,
1726 NamespaceDecl *&Namespace) {
1727 if (!StdCoroutineTraitsCache) {
1728 // Because coroutines moved from std::experimental in the TS to std in
1729 // C++20, we look in both places to give users time to transition their
1730 // TS-specific code to C++20. Diagnostics are given when the TS usage is
1731 // discovered.
1732 // TODO: Become stricter when <experimental/coroutine> is removed.
1733
1734 auto const &TraitIdent = PP.getIdentifierTable().get("coroutine_traits");
1735
1736 NamespaceDecl *StdSpace = getStdNamespace();
1737 LookupResult ResStd(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
1738 bool InStd = StdSpace && LookupQualifiedName(ResStd, StdSpace);
1739
1740 NamespaceDecl *ExpSpace = lookupStdExperimentalNamespace();
1741 LookupResult ResExp(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
1742 bool InExp = ExpSpace && LookupQualifiedName(ResExp, ExpSpace);
1743
1744 if (!InStd && !InExp) {
1745 // The goggles, they found nothing!
1746 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
1747 << "std::coroutine_traits";
1748 return nullptr;
1749 }
1750
1751 // Prefer ::std to std::experimental.
1752 auto &Result = InStd ? ResStd : ResExp;
1753 CoroTraitsNamespaceCache = InStd ? StdSpace : ExpSpace;
1754
1755 // coroutine_traits is required to be a class template.
1756 StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>();
1757 if (!StdCoroutineTraitsCache) {
1758 Result.suppressDiagnostics();
1759 NamedDecl *Found = *Result.begin();
1760 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
1761 return nullptr;
1762 }
1763
1764 if (InExp) {
1765 // Found in std::experimental
1766 Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
1767 << "coroutine_traits";
1768 ResExp.suppressDiagnostics();
1769 auto *Found = *ResExp.begin();
1770 Diag(Found->getLocation(), diag::note_entity_declared_at) << Found;
1771
1772 if (InStd &&
1773 StdCoroutineTraitsCache != ResExp.getAsSingle<ClassTemplateDecl>()) {
1774 // Also found something different in std
1775 Diag(KwLoc,
1776 diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
1777 Diag(StdCoroutineTraitsCache->getLocation(),
1778 diag::note_entity_declared_at)
1779 << StdCoroutineTraitsCache;
1780
1781 return nullptr;
1782 }
1783 }
1784 }
1785 Namespace = CoroTraitsNamespaceCache;
1786 return StdCoroutineTraitsCache;
1787}