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-14~++20220125101009+ceec4383681c/build-llvm -resource-dir /usr/lib/llvm-14/lib/clang/14.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-14~++20220125101009+ceec4383681c/clang/lib/Sema -I /build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/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-14/lib/clang/14.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-14~++20220125101009+ceec4383681c/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/= -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-14~++20220125101009+ceec4383681c/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/= -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-01-25-232935-20746-1 -x c++ /build/llvm-toolchain-snapshot-14~++20220125101009+ceec4383681c/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->getType()->isPlaceholderType()) {
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->getType()->isPlaceholderType()) {
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->getType()->isPlaceholderType()) {
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->getType()->isPlaceholderType()) {
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->getType()->isPlaceholderType() &&
974 !E->getType()->isSpecificPlaceholderType(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 // [stmt.return.coroutine]p1:
1085 // A coroutine shall not enclose a return statement ([stmt.return]).
1086 if (Fn->FirstReturnLoc.isValid()) {
1087 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", 1088, __extension__ __PRETTY_FUNCTION__
))
1088 "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", 1088, __extension__ __PRETTY_FUNCTION__
))
;
1089 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
1090 Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1091 << Fn->getFirstCoroutineStmtKeyword();
1092 }
1093 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
1094 if (Builder.isInvalid() || !Builder.buildStatements())
1095 return FD->setInvalidDecl();
1096
1097 // Build body for the coroutine wrapper statement.
1098 Body = CoroutineBodyStmt::Create(Context, Builder);
1099}
1100
1101CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
1102 sema::FunctionScopeInfo &Fn,
1103 Stmt *Body)
1104 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1105 IsPromiseDependentType(
1106 !Fn.CoroutinePromise ||
1107 Fn.CoroutinePromise->getType()->isDependentType()) {
1108 this->Body = Body;
1109
1110 for (auto KV : Fn.CoroutineParameterMoves)
1111 this->ParamMovesVector.push_back(KV.second);
1112 this->ParamMoves = this->ParamMovesVector;
1113
1114 if (!IsPromiseDependentType) {
1115 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
1116 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", 1116, __extension__ __PRETTY_FUNCTION__
))
;
1117 }
1118 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1119}
1120
1121bool CoroutineStmtBuilder::buildStatements() {
1122 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", 1122, __extension__ __PRETTY_FUNCTION__
))
;
1123 this->IsValid = makeReturnObject();
1124 if (this->IsValid && !IsPromiseDependentType)
1125 buildDependentStatements();
1126 return this->IsValid;
1127}
1128
1129bool CoroutineStmtBuilder::buildDependentStatements() {
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 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", 1132, __extension__ __PRETTY_FUNCTION__
))
1132 "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", 1132, __extension__ __PRETTY_FUNCTION__
))
;
1133 this->IsValid = makeOnException() && makeOnFallthrough() &&
1134 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1135 makeNewAndDeleteExpr();
1136 return this->IsValid;
1137}
1138
1139bool CoroutineStmtBuilder::makePromiseStmt() {
1140 // Form a declaration statement for the promise declaration, so that AST
1141 // visitors can more easily find it.
1142 StmtResult PromiseStmt =
1143 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc);
1144 if (PromiseStmt.isInvalid())
1145 return false;
1146
1147 this->Promise = PromiseStmt.get();
1148 return true;
1149}
1150
1151bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1152 if (Fn.hasInvalidCoroutineSuspends())
1153 return false;
1154 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first);
1155 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
1156 return true;
1157}
1158
1159static bool diagReturnOnAllocFailure(Sema &S, Expr *E,
1160 CXXRecordDecl *PromiseRecordDecl,
1161 FunctionScopeInfo &Fn) {
1162 auto Loc = E->getExprLoc();
1163 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1164 auto *Decl = DeclRef->getDecl();
1165 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) {
1166 if (Method->isStatic())
1167 return true;
1168 else
1169 Loc = Decl->getLocation();
1170 }
1171 }
1172
1173 S.Diag(
1174 Loc,
1175 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1176 << PromiseRecordDecl;
1177 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1178 << Fn.getFirstCoroutineStmtKeyword();
1179 return false;
1180}
1181
1182bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1183 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", 1184, __extension__ __PRETTY_FUNCTION__
))
1184 "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", 1184, __extension__ __PRETTY_FUNCTION__
))
;
1185
1186 // [dcl.fct.def.coroutine]p10
1187 // If a search for the name get_return_object_on_allocation_failure in
1188 // the scope of the promise type ([class.member.lookup]) finds any
1189 // declarations, then the result of a call to an allocation function used to
1190 // obtain storage for the coroutine state is assumed to return nullptr if it
1191 // fails to obtain storage, ... If the allocation function returns nullptr,
1192 // ... and the return value is obtained by a call to
1193 // T::get_return_object_on_allocation_failure(), where T is the
1194 // promise type.
1195 DeclarationName DN =
1196 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");
1197 LookupResult Found(S, DN, Loc, Sema::LookupMemberName);
1198 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))
1199 return true;
1200
1201 CXXScopeSpec SS;
1202 ExprResult DeclNameExpr =
1203 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
1204 if (DeclNameExpr.isInvalid())
1205 return false;
1206
1207 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn))
1208 return false;
1209
1210 ExprResult ReturnObjectOnAllocationFailure =
1211 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
1212 if (ReturnObjectOnAllocationFailure.isInvalid())
1213 return false;
1214
1215 StmtResult ReturnStmt =
1216 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
1217 if (ReturnStmt.isInvalid()) {
1218 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1219 << DN;
1220 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1221 << Fn.getFirstCoroutineStmtKeyword();
1222 return false;
1223 }
1224
1225 this->ReturnStmtOnAllocFailure = ReturnStmt.get();
1226 return true;
1227}
1228
1229bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1230 // Form and check allocation and deallocation calls.
1231 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", 1232, __extension__ __PRETTY_FUNCTION__
))
1232 "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", 1232, __extension__ __PRETTY_FUNCTION__
))
;
1233 QualType PromiseType = Fn.CoroutinePromise->getType();
1234
1235 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
1236 return false;
1237
1238 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
1239
1240 // According to [dcl.fct.def.coroutine]p9, Lookup allocation functions using a
1241 // parameter list composed of the requested size of the coroutine state being
1242 // allocated, followed by the coroutine function's arguments. If a matching
1243 // allocation function exists, use it. Otherwise, use an allocation function
1244 // that just takes the requested size.
1245
1246 FunctionDecl *OperatorNew = nullptr;
1247 FunctionDecl *OperatorDelete = nullptr;
1248 FunctionDecl *UnusedResult = nullptr;
1249 bool PassAlignment = false;
1250 SmallVector<Expr *, 1> PlacementArgs;
1251
1252 // [dcl.fct.def.coroutine]p9
1253 // An implementation may need to allocate additional storage for a
1254 // coroutine.
1255 // This storage is known as the coroutine state and is obtained by calling a
1256 // non-array allocation function ([basic.stc.dynamic.allocation]). The
1257 // allocation function's name is looked up by searching for it in the scope of
1258 // the promise type.
1259 // - If any declarations are found, overload resolution is performed on a
1260 // function call created by assembling an argument list. The first argument is
1261 // the amount of space requested, and has type std::size_t. The
1262 // lvalues p1 ... pn are the succeeding arguments.
1263 //
1264 // ...where "p1 ... pn" are defined earlier as:
1265 //
1266 // [dcl.fct.def.coroutine]p3
1267 // The promise type of a coroutine is `std::coroutine_traits<R, P1, ...,
1268 // Pn>`
1269 // , where R is the return type of the function, and `P1, ..., Pn` are the
1270 // sequence of types of the non-object function parameters, preceded by the
1271 // type of the object parameter ([dcl.fct]) if the coroutine is a non-static
1272 // member function. [dcl.fct.def.coroutine]p4 In the following, p_i is an
1273 // lvalue of type P_i, where p1 denotes the object parameter and p_i+1 denotes
1274 // the i-th non-object function parameter for a non-static member function,
1275 // and p_i denotes the i-th function parameter otherwise. For a non-static
1276 // member function, q_1 is an lvalue that denotes *this; any other q_i is an
1277 // lvalue that denotes the parameter copy corresponding to p_i.
1278 if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1279 if (MD->isInstance() && !isLambdaCallOperator(MD)) {
1280 ExprResult ThisExpr = S.ActOnCXXThis(Loc);
1281 if (ThisExpr.isInvalid())
1282 return false;
1283 ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
1284 if (ThisExpr.isInvalid())
1285 return false;
1286 PlacementArgs.push_back(ThisExpr.get());
1287 }
1288 }
1289 for (auto *PD : FD.parameters()) {
1290 if (PD->getType()->isDependentType())
1291 continue;
1292
1293 // Build a reference to the parameter.
1294 auto PDLoc = PD->getLocation();
1295 ExprResult PDRefExpr =
1296 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
1297 ExprValueKind::VK_LValue, PDLoc);
1298 if (PDRefExpr.isInvalid())
1299 return false;
1300
1301 PlacementArgs.push_back(PDRefExpr.get());
1302 }
1303 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
1304 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1305 /*isArray*/ false, PassAlignment, PlacementArgs,
1306 OperatorNew, UnusedResult, /*Diagnose*/ false);
1307
1308 // [dcl.fct.def.coroutine]p9
1309 // If no viable function is found ([over.match.viable]), overload resolution
1310 // is performed again on a function call created by passing just the amount of
1311 // space required as an argument of type std::size_t.
1312 if (!OperatorNew && !PlacementArgs.empty()) {
1313 PlacementArgs.clear();
1314 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
1315 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1316 /*isArray*/ false, PassAlignment, PlacementArgs,
1317 OperatorNew, UnusedResult, /*Diagnose*/ false);
1318 }
1319
1320 // [dcl.fct.def.coroutine]p9
1321 // The allocation function's name is looked up by searching for it in the
1322 // scope of the promise type.
1323 // - If any declarations are found, ...
1324 // - Otherwise, a search is performed in the global scope.
1325 if (!OperatorNew) {
1326 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Global,
1327 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1328 /*isArray*/ false, PassAlignment, PlacementArgs,
1329 OperatorNew, UnusedResult);
1330 }
1331
1332 bool IsGlobalOverload =
1333 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
1334 // If we didn't find a class-local new declaration and non-throwing new
1335 // was is required then we need to lookup the non-throwing global operator
1336 // instead.
1337 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
1338 auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc);
1339 if (!StdNoThrow)
1340 return false;
1341 PlacementArgs = {StdNoThrow};
1342 OperatorNew = nullptr;
1343 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
1344 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1345 /*isArray*/ false, PassAlignment, PlacementArgs,
1346 OperatorNew, UnusedResult);
1347 }
1348
1349 if (!OperatorNew)
1350 return false;
1351
1352 if (RequiresNoThrowAlloc) {
1353 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();
1354 if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
1355 S.Diag(OperatorNew->getLocation(),
1356 diag::err_coroutine_promise_new_requires_nothrow)
1357 << OperatorNew;
1358 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1359 << OperatorNew;
1360 return false;
1361 }
1362 }
1363
1364 if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr) {
1365 // FIXME: We should add an error here. According to:
1366 // [dcl.fct.def.coroutine]p12
1367 // If no usual deallocation function is found, the program is ill-formed.
1368 return false;
1369 }
1370
1371 Expr *FramePtr =
1372 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
1373
1374 Expr *FrameSize =
1375 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
1376
1377 // Make new call.
1378
1379 ExprResult NewRef =
1380 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
1381 if (NewRef.isInvalid())
1382 return false;
1383
1384 SmallVector<Expr *, 2> NewArgs(1, FrameSize);
1385 for (auto Arg : PlacementArgs)
1386 NewArgs.push_back(Arg);
1387
1388 ExprResult NewExpr =
1389 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
1390 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
1391 if (NewExpr.isInvalid())
1392 return false;
1393
1394 // Make delete call.
1395
1396 QualType OpDeleteQualType = OperatorDelete->getType();
1397
1398 ExprResult DeleteRef =
1399 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
1400 if (DeleteRef.isInvalid())
1401 return false;
1402
1403 Expr *CoroFree =
1404 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
1405
1406 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
1407
1408 // [dcl.fct.def.coroutine]p12
1409 // The selected deallocation function shall be called with the address of
1410 // the block of storage to be reclaimed as its first argument. If a
1411 // deallocation function with a parameter of type std::size_t is
1412 // used, the size of the block is passed as the corresponding argument.
1413 const auto *OpDeleteType =
1414 OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
1415 if (OpDeleteType->getNumParams() > 1)
1416 DeleteArgs.push_back(FrameSize);
1417
1418 ExprResult DeleteExpr =
1419 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
1420 DeleteExpr =
1421 S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
1422 if (DeleteExpr.isInvalid())
1423 return false;
1424
1425 this->Allocate = NewExpr.get();
1426 this->Deallocate = DeleteExpr.get();
1427
1428 return true;
1429}
1430
1431bool CoroutineStmtBuilder::makeOnFallthrough() {
1432 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", 1433, __extension__ __PRETTY_FUNCTION__
))
1433 "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", 1433, __extension__ __PRETTY_FUNCTION__
))
;
1434
1435 // [dcl.fct.def.coroutine]/p6
1436 // If searches for the names return_void and return_value in the scope of
1437 // the promise type each find any declarations, the program is ill-formed.
1438 // [Note 1: If return_void is found, flowing off the end of a coroutine is
1439 // equivalent to a co_return with no operand. Otherwise, flowing off the end
1440 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
1441 // end note]
1442 bool HasRVoid, HasRValue;
1443 LookupResult LRVoid =
1444 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
1445 LookupResult LRValue =
1446 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
1447
1448 StmtResult Fallthrough;
1449 if (HasRVoid && HasRValue) {
1450 // FIXME Improve this diagnostic
1451 S.Diag(FD.getLocation(),
1452 diag::err_coroutine_promise_incompatible_return_functions)
1453 << PromiseRecordDecl;
1454 S.Diag(LRVoid.getRepresentativeDecl()->getLocation(),
1455 diag::note_member_first_declared_here)
1456 << LRVoid.getLookupName();
1457 S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
1458 diag::note_member_first_declared_here)
1459 << LRValue.getLookupName();
1460 return false;
1461 } else if (!HasRVoid && !HasRValue) {
1462 // We need to set 'Fallthrough'. Otherwise the other analysis part might
1463 // think the coroutine has defined a return_value method. So it might emit
1464 // **false** positive warning. e.g.,
1465 //
1466 // promise_without_return_func foo() {
1467 // co_await something();
1468 // }
1469 //
1470 // Then AnalysisBasedWarning would emit a warning about `foo()` lacking a
1471 // co_return statements, which isn't correct.
1472 Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());
1473 if (Fallthrough.isInvalid())
1474 return false;
1475 } else if (HasRVoid) {
1476 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
1477 /*IsImplicit*/false);
1478 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
1479 if (Fallthrough.isInvalid())
1480 return false;
1481 }
1482
1483 this->OnFallthrough = Fallthrough.get();
1484 return true;
1485}
1486
1487bool CoroutineStmtBuilder::makeOnException() {
1488 // Try to form 'p.unhandled_exception();'
1489 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", 1490, __extension__ __PRETTY_FUNCTION__
))
1490 "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", 1490, __extension__ __PRETTY_FUNCTION__
))
;
1491
1492 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
1493
1494 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
1495 auto DiagID =
1496 RequireUnhandledException
1497 ? diag::err_coroutine_promise_unhandled_exception_required
1498 : diag::
1499 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1500 S.Diag(Loc, DiagID) << PromiseRecordDecl;
1501 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1502 << PromiseRecordDecl;
1503 return !RequireUnhandledException;
1504 }
1505
1506 // If exceptions are disabled, don't try to build OnException.
1507 if (!S.getLangOpts().CXXExceptions)
1508 return true;
1509
1510 ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
1511 "unhandled_exception", None);
1512 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
1513 /*DiscardedValue*/ false);
1514 if (UnhandledException.isInvalid())
1515 return false;
1516
1517 // Since the body of the coroutine will be wrapped in try-catch, it will
1518 // be incompatible with SEH __try if present in a function.
1519 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
1520 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
1521 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1522 << Fn.getFirstCoroutineStmtKeyword();
1523 return false;
1524 }
1525
1526 this->OnException = UnhandledException.get();
1527 return true;
1528}
1529
1530bool CoroutineStmtBuilder::makeReturnObject() {
1531 // [dcl.fct.def.coroutine]p7
1532 // The expression promise.get_return_object() is used to initialize the
1533 // returned reference or prvalue result object of a call to a coroutine.
1534 ExprResult ReturnObject =
1535 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
1536 if (ReturnObject.isInvalid())
1537 return false;
1538
1539 this->ReturnValue = ReturnObject.get();
1540 return true;
1541}
1542
1543static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn) {
1544 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1545 auto *MethodDecl = MbrRef->getMethodDecl();
1546 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1547 << MethodDecl;
1548 }
1549 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1550 << Fn.getFirstCoroutineStmtKeyword();
1551}
1552
1553bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1554 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", 1555, __extension__ __PRETTY_FUNCTION__
))
1555 "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", 1555, __extension__ __PRETTY_FUNCTION__
))
;
1556 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", 1556, __extension__ __PRETTY_FUNCTION__
))
;
1557
1558 QualType const GroType = this->ReturnValue->getType();
1559 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", 1560, __extension__ __PRETTY_FUNCTION__
))
1560 "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", 1560, __extension__ __PRETTY_FUNCTION__
))
;
1561
1562 QualType const FnRetType = FD.getReturnType();
1563 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", 1564, __extension__ __PRETTY_FUNCTION__
))
1564 "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", 1564, __extension__ __PRETTY_FUNCTION__
))
;
1565
1566 if (FnRetType->isVoidType()) {
1567 ExprResult Res =
1568 S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
1569 if (Res.isInvalid())
1570 return false;
1571
1572 this->ResultDecl = Res.get();
1573 return true;
1574 }
1575
1576 if (GroType->isVoidType()) {
1577 // Trigger a nice error message.
1578 InitializedEntity Entity =
1579 InitializedEntity::InitializeResult(Loc, FnRetType);
1580 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1581 noteMemberDeclaredHere(S, ReturnValue, Fn);
1582 return false;
1583 }
1584
1585 auto *GroDecl = VarDecl::Create(
1586 S.Context, &FD, FD.getLocation(), FD.getLocation(),
1587 &S.PP.getIdentifierTable().get("__coro_gro"), GroType,
1588 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
1589 GroDecl->setImplicit();
1590
1591 S.CheckVariableDeclarationType(GroDecl);
1592 if (GroDecl->isInvalidDecl())
1593 return false;
1594
1595 InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
1596 ExprResult Res =
1597 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1598 if (Res.isInvalid())
1599 return false;
1600
1601 Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
1602 if (Res.isInvalid())
1603 return false;
1604
1605 S.AddInitializerToDecl(GroDecl, Res.get(),
1606 /*DirectInit=*/false);
1607
1608 S.FinalizeDeclaration(GroDecl);
1609
1610 // Form a declaration statement for the return declaration, so that AST
1611 // visitors can more easily find it.
1612 StmtResult GroDeclStmt =
1613 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
1614 if (GroDeclStmt.isInvalid())
1615 return false;
1616
1617 this->ResultDecl = GroDeclStmt.get();
1618
1619 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
1620 if (declRef.isInvalid())
1621 return false;
1622
1623 StmtResult ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
1624 if (ReturnStmt.isInvalid()) {
1625 noteMemberDeclaredHere(S, ReturnValue, Fn);
1626 return false;
1627 }
1628 if (cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
1629 GroDecl->setNRVOVariable(true);
1630
1631 this->ReturnStmt = ReturnStmt.get();
1632 return true;
1633}
1634
1635// Create a static_cast\<T&&>(expr).
1636static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
1637 if (T.isNull())
1638 T = E->getType();
1639 QualType TargetType = S.BuildReferenceType(
1640 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
1641 SourceLocation ExprLoc = E->getBeginLoc();
1642 TypeSourceInfo *TargetLoc =
1643 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
1644
1645 return S
1646 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
1647 SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
1648 .get();
1649}
1650
1651/// Build a variable declaration for move parameter.
1652static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type,
1653 IdentifierInfo *II) {
1654 TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc);
1655 VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
1656 TInfo, SC_None);
1657 Decl->setImplicit();
1658 return Decl;
1659}
1660
1661// Build statements that move coroutine function parameters to the coroutine
1662// frame, and store them on the function scope info.
1663bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
1664 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", 1664, __extension__ __PRETTY_FUNCTION__
))
;
1665 auto *FD = cast<FunctionDecl>(CurContext);
1666
1667 auto *ScopeInfo = getCurFunction();
1668 if (!ScopeInfo->CoroutineParameterMoves.empty())
1669 return false;
1670
1671 // [dcl.fct.def.coroutine]p13
1672 // When a coroutine is invoked, after initializing its parameters
1673 // ([expr.call]), a copy is created for each coroutine parameter. For a
1674 // parameter of type cv T, the copy is a variable of type cv T with
1675 // automatic storage duration that is direct-initialized from an xvalue of
1676 // type T referring to the parameter.
1677 for (auto *PD : FD->parameters()) {
1678 if (PD->getType()->isDependentType())
1679 continue;
1680
1681 ExprResult PDRefExpr =
1682 BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
1683 ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1684 if (PDRefExpr.isInvalid())
1685 return false;
1686
1687 Expr *CExpr = nullptr;
1688 if (PD->getType()->getAsCXXRecordDecl() ||
1689 PD->getType()->isRValueReferenceType())
1690 CExpr = castForMoving(*this, PDRefExpr.get());
1691 else
1692 CExpr = PDRefExpr.get();
1693 // [dcl.fct.def.coroutine]p13
1694 // The initialization and destruction of each parameter copy occurs in the
1695 // context of the called coroutine.
1696 auto D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
1697 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
1698
1699 // Convert decl to a statement.
1700 StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc, Loc);
1701 if (Stmt.isInvalid())
1702 return false;
1703
1704 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
1705 }
1706 return true;
1707}
1708
1709StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
1710 CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args);
1711 if (!Res)
1712 return StmtError();
1713 return Res;
1714}
1715
1716ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
1717 SourceLocation FuncLoc,
1718 NamespaceDecl *&Namespace) {
1719 if (!StdCoroutineTraitsCache) {
1720 // Because coroutines moved from std::experimental in the TS to std in
1721 // C++20, we look in both places to give users time to transition their
1722 // TS-specific code to C++20. Diagnostics are given when the TS usage is
1723 // discovered.
1724 // TODO: Become stricter when <experimental/coroutine> is removed.
1725
1726 auto const &TraitIdent = PP.getIdentifierTable().get("coroutine_traits");
1727
1728 NamespaceDecl *StdSpace = getStdNamespace();
1729 LookupResult ResStd(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
1730 bool InStd = StdSpace && LookupQualifiedName(ResStd, StdSpace);
1731
1732 NamespaceDecl *ExpSpace = lookupStdExperimentalNamespace();
1733 LookupResult ResExp(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
1734 bool InExp = ExpSpace && LookupQualifiedName(ResExp, ExpSpace);
1735
1736 if (!InStd && !InExp) {
1737 // The goggles, they found nothing!
1738 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
1739 << "std::coroutine_traits";
1740 return nullptr;
1741 }
1742
1743 // Prefer ::std to std::experimental.
1744 auto &Result = InStd ? ResStd : ResExp;
1745 CoroTraitsNamespaceCache = InStd ? StdSpace : ExpSpace;
1746
1747 // coroutine_traits is required to be a class template.
1748 StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>();
1749 if (!StdCoroutineTraitsCache) {
1750 Result.suppressDiagnostics();
1751 NamedDecl *Found = *Result.begin();
1752 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
1753 return nullptr;
1754 }
1755
1756 if (InExp) {
1757 // Found in std::experimental
1758 Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
1759 << "coroutine_traits";
1760 ResExp.suppressDiagnostics();
1761 auto *Found = *ResExp.begin();
1762 Diag(Found->getLocation(), diag::note_entity_declared_at) << Found;
1763
1764 if (InStd &&
1765 StdCoroutineTraitsCache != ResExp.getAsSingle<ClassTemplateDecl>()) {
1766 // Also found something different in std
1767 Diag(KwLoc,
1768 diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
1769 Diag(StdCoroutineTraitsCache->getLocation(),
1770 diag::note_entity_declared_at)
1771 << StdCoroutineTraitsCache;
1772
1773 return nullptr;
1774 }
1775 }
1776 }
1777 Namespace = CoroTraitsNamespaceCache;
1778 return StdCoroutineTraitsCache;
1779}