Bug Summary

File:clang/lib/Sema/SemaCoroutine.cpp
Warning:line 675, column 13
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 -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~++20211110111138+cffbfd01e37b/build-llvm -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D CLANG_ROUND_TRIP_CC1_ARGS=ON -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~++20211110111138+cffbfd01e37b/clang/lib/Sema -I /build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/llvm/include -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 -O2 -Wno-unused-command-line-argument -Wno-unknown-warning-option -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~++20211110111138+cffbfd01e37b/build-llvm -ferror-limit 19 -fvisibility-inlines-hidden -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-2021-11-10-160236-22541-1 -x c++ /build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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?\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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: "The parameter-declaration-clause of the
241 // coroutine shall not terminate with an ellipsis that is not part of a
242 // 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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", "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/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 // Attempt to initialize the promise type with the arguments.
583 // If that fails, fall back to the promise type's default constructor.
584 if (InitSeq) {
585 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
586 if (Result.isInvalid()) {
587 VD->setInvalidDecl();
588 } else if (Result.get()) {
589 VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
590 VD->setInitStyle(VarDecl::CallInit);
591 CheckCompleteVariableDeclaration(VD);
592 }
593 } else
594 ActOnUninitializedDecl(VD);
595 } else
596 ActOnUninitializedDecl(VD);
597
598 FD->addDecl(VD);
599 return VD;
600}
601
602/// Check that this is a context in which a coroutine suspension can appear.
603static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
604 StringRef Keyword,
605 bool IsImplicit = false) {
606 if (!isValidCoroutineContext(S, Loc, Keyword))
607 return nullptr;
608
609 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 609, __extension__ __PRETTY_FUNCTION__))
;
610
611 auto *ScopeInfo = S.getCurFunction();
612 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 612, __extension__ __PRETTY_FUNCTION__))
;
613
614 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
615 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
616
617 if (ScopeInfo->CoroutinePromise)
618 return ScopeInfo;
619
620 if (!S.buildCoroutineParameterMoves(Loc))
621 return nullptr;
622
623 ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
624 if (!ScopeInfo->CoroutinePromise)
625 return nullptr;
626
627 return ScopeInfo;
628}
629
630/// Recursively check \p E and all its children to see if any call target
631/// (including constructor call) is declared noexcept. Also any value returned
632/// from the call has a noexcept destructor.
633static void checkNoThrow(Sema &S, const Stmt *E,
634 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {
635 auto checkDeclNoexcept = [&](const Decl *D, bool IsDtor = false) {
636 // In the case of dtor, the call to dtor is implicit and hence we should
637 // pass nullptr to canCalleeThrow.
638 if (Sema::canCalleeThrow(S, IsDtor ? nullptr : cast<Expr>(E), D)) {
639 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
640 // co_await promise.final_suspend() could end up calling
641 // __builtin_coro_resume for symmetric transfer if await_suspend()
642 // returns a handle. In that case, even __builtin_coro_resume is not
643 // declared as noexcept and may throw, it does not throw _into_ the
644 // coroutine that just suspended, but rather throws back out from
645 // whoever called coroutine_handle::resume(), hence we claim that
646 // logically it does not throw.
647 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)
648 return;
649 }
650 if (ThrowingDecls.empty()) {
651 // First time seeing an error, emit the error message.
652 S.Diag(cast<FunctionDecl>(S.CurContext)->getLocation(),
653 diag::err_coroutine_promise_final_suspend_requires_nothrow);
654 }
655 ThrowingDecls.insert(D);
656 }
657 };
658 auto SC = E->getStmtClass();
659 if (SC == Expr::CXXConstructExprClass) {
13
Assuming 'SC' is not equal to CXXConstructExprClass
21
Assuming 'SC' is not equal to CXXConstructExprClass
660 auto const *Ctor = cast<CXXConstructExpr>(E)->getConstructor();
661 checkDeclNoexcept(Ctor);
662 // Check the corresponding destructor of the constructor.
663 checkDeclNoexcept(Ctor->getParent()->getDestructor(), true);
664 } else if (SC == Expr::CallExprClass || SC == Expr::CXXMemberCallExprClass ||
14
Assuming 'SC' is not equal to CallExprClass
15
Assuming 'SC' is not equal to CXXMemberCallExprClass
17
Taking false branch
22
Assuming 'SC' is equal to CallExprClass
665 SC == Expr::CXXOperatorCallExprClass) {
16
Assuming 'SC' is not equal to CXXOperatorCallExprClass
666 if (!cast<CallExpr>(E)->isTypeDependent()) {
23
'E' is a 'CallExpr'
24
Assuming the condition is true
25
Taking true branch
667 checkDeclNoexcept(cast<CallExpr>(E)->getCalleeDecl());
26
'E' is a 'CallExpr'
668 auto ReturnType = cast<CallExpr>(E)->getCallReturnType(S.getASTContext());
27
'E' is a 'CallExpr'
669 // Check the destructor of the call return type, if any.
670 if (ReturnType.isDestructedType() ==
28
Assuming the condition is true
29
Taking true branch
671 QualType::DestructionKind::DK_cxx_destructor) {
672 const auto *T =
673 cast<RecordType>(ReturnType.getCanonicalType().getTypePtr());
30
The object is a 'RecordType'
674 checkDeclNoexcept(
675 dyn_cast<CXXRecordDecl>(T->getDecl())->getDestructor(), true);
31
Assuming the object is not a 'CXXRecordDecl'
32
Called C++ object pointer is null
676 }
677 }
678 }
679 for (const auto *Child : E->children()) {
680 if (!Child)
18
Assuming 'Child' is non-null
19
Taking false branch
681 continue;
682 checkNoThrow(S, Child, ThrowingDecls);
20
Calling 'checkNoThrow'
683 }
684}
685
686bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
687 llvm::SmallPtrSet<const Decl *, 4> ThrowingDecls;
688 // We first collect all declarations that should not throw but not declared
689 // with noexcept. We then sort them based on the location before printing.
690 // This is to avoid emitting the same note multiple times on the same
691 // declaration, and also provide a deterministic order for the messages.
692 checkNoThrow(*this, FinalSuspend, ThrowingDecls);
12
Calling 'checkNoThrow'
693 auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(),
694 ThrowingDecls.end()};
695 sort(SortedDecls, [](const Decl *A, const Decl *B) {
696 return A->getEndLoc() < B->getEndLoc();
697 });
698 for (const auto *D : SortedDecls) {
699 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
700 }
701 return ThrowingDecls.empty();
702}
703
704bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
705 StringRef Keyword) {
706 if (!checkCoroutineContext(*this, KWLoc, Keyword))
2
Taking false branch
707 return false;
708 auto *ScopeInfo = getCurFunction();
709 assert(ScopeInfo->CoroutinePromise)(static_cast <bool> (ScopeInfo->CoroutinePromise) ? void
(0) : __assert_fail ("ScopeInfo->CoroutinePromise", "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 709, __extension__ __PRETTY_FUNCTION__))
;
3
Assuming field 'CoroutinePromise' is non-null
4
'?' condition is true
710
711 // If we have existing coroutine statements then we have already built
712 // the initial and final suspend points.
713 if (!ScopeInfo->NeedsCoroutineSuspends)
5
Assuming field 'NeedsCoroutineSuspends' is true
6
Taking false branch
714 return true;
715
716 ScopeInfo->setNeedsCoroutineSuspends(false);
717
718 auto *Fn = cast<FunctionDecl>(CurContext);
7
Field 'CurContext' is a 'FunctionDecl'
719 SourceLocation Loc = Fn->getLocation();
720 // Build the initial suspend point
721 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
722 ExprResult Suspend =
723 buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, None);
724 if (Suspend.isInvalid())
725 return StmtError();
726 Suspend = buildOperatorCoawaitCall(*this, SC, Loc, Suspend.get());
727 if (Suspend.isInvalid())
728 return StmtError();
729 Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
730 /*IsImplicit*/ true);
731 Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
732 if (Suspend.isInvalid()) {
733 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
734 << ((Name == "initial_suspend") ? 0 : 1);
735 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
736 return StmtError();
737 }
738 return cast<Stmt>(Suspend.get());
739 };
740
741 StmtResult InitSuspend = buildSuspends("initial_suspend");
742 if (InitSuspend.isInvalid())
8
Assuming the condition is false
9
Taking false branch
743 return true;
744
745 StmtResult FinalSuspend = buildSuspends("final_suspend");
746 if (FinalSuspend.isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.get()))
10
Assuming the condition is false
11
Calling 'Sema::checkFinalSuspendNoThrow'
747 return true;
748
749 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());
750
751 return true;
752}
753
754// Recursively walks up the scope hierarchy until either a 'catch' or a function
755// scope is found, whichever comes first.
756static bool isWithinCatchScope(Scope *S) {
757 // 'co_await' and 'co_yield' keywords are disallowed within catch blocks, but
758 // lambdas that use 'co_await' are allowed. The loop below ends when a
759 // function scope is found in order to ensure the following behavior:
760 //
761 // void foo() { // <- function scope
762 // try { //
763 // co_await x; // <- 'co_await' is OK within a function scope
764 // } catch { // <- catch scope
765 // co_await x; // <- 'co_await' is not OK within a catch scope
766 // []() { // <- function scope
767 // co_await x; // <- 'co_await' is OK within a function scope
768 // }();
769 // }
770 // }
771 while (S && !(S->getFlags() & Scope::FnScope)) {
772 if (S->getFlags() & Scope::CatchScope)
773 return true;
774 S = S->getParent();
775 }
776 return false;
777}
778
779// [expr.await]p2, emphasis added: "An await-expression shall appear only in
780// a *potentially evaluated* expression within the compound-statement of a
781// function-body *outside of a handler* [...] A context within a function
782// where an await-expression can appear is called a suspension context of the
783// function."
784static void checkSuspensionContext(Sema &S, SourceLocation Loc,
785 StringRef Keyword) {
786 // First emphasis of [expr.await]p2: must be a potentially evaluated context.
787 // That is, 'co_await' and 'co_yield' cannot appear in subexpressions of
788 // \c sizeof.
789 if (S.isUnevaluatedContext())
790 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
791
792 // Second emphasis of [expr.await]p2: must be outside of an exception handler.
793 if (isWithinCatchScope(S.getCurScope()))
794 S.Diag(Loc, diag::err_coroutine_within_handler) << Keyword;
795}
796
797ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
798 if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
799 CorrectDelayedTyposInExpr(E);
800 return ExprError();
801 }
802
803 checkSuspensionContext(*this, Loc, "co_await");
804
805 if (E->getType()->isPlaceholderType()) {
806 ExprResult R = CheckPlaceholderExpr(E);
807 if (R.isInvalid()) return ExprError();
808 E = R.get();
809 }
810 ExprResult Lookup = buildOperatorCoawaitLookupExpr(*this, S, Loc);
811 if (Lookup.isInvalid())
812 return ExprError();
813 return BuildUnresolvedCoawaitExpr(Loc, E,
814 cast<UnresolvedLookupExpr>(Lookup.get()));
815}
816
817ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
818 UnresolvedLookupExpr *Lookup) {
819 auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
820 if (!FSI)
821 return ExprError();
822
823 if (E->getType()->isPlaceholderType()) {
824 ExprResult R = CheckPlaceholderExpr(E);
825 if (R.isInvalid())
826 return ExprError();
827 E = R.get();
828 }
829
830 auto *Promise = FSI->CoroutinePromise;
831 if (Promise->getType()->isDependentType()) {
832 Expr *Res =
833 new (Context) DependentCoawaitExpr(Loc, Context.DependentTy, E, Lookup);
834 return Res;
835 }
836
837 auto *RD = Promise->getType()->getAsCXXRecordDecl();
838 if (lookupMember(*this, "await_transform", RD, Loc)) {
839 ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E);
840 if (R.isInvalid()) {
841 Diag(Loc,
842 diag::note_coroutine_promise_implicit_await_transform_required_here)
843 << E->getSourceRange();
844 return ExprError();
845 }
846 E = R.get();
847 }
848 ExprResult Awaitable = buildOperatorCoawaitCall(*this, Loc, E, Lookup);
849 if (Awaitable.isInvalid())
850 return ExprError();
851
852 return BuildResolvedCoawaitExpr(Loc, Awaitable.get());
853}
854
855ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
856 bool IsImplicit) {
857 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
858 if (!Coroutine)
859 return ExprError();
860
861 if (E->getType()->isPlaceholderType()) {
862 ExprResult R = CheckPlaceholderExpr(E);
863 if (R.isInvalid()) return ExprError();
864 E = R.get();
865 }
866
867 if (E->getType()->isDependentType()) {
868 Expr *Res = new (Context)
869 CoawaitExpr(Loc, Context.DependentTy, E, IsImplicit);
870 return Res;
871 }
872
873 // If the expression is a temporary, materialize it as an lvalue so that we
874 // can use it multiple times.
875 if (E->isPRValue())
876 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
877
878 // The location of the `co_await` token cannot be used when constructing
879 // the member call expressions since it's before the location of `Expr`, which
880 // is used as the start of the member call expression.
881 SourceLocation CallLoc = E->getExprLoc();
882
883 // Build the await_ready, await_suspend, await_resume calls.
884 ReadySuspendResumeResult RSS = buildCoawaitCalls(
885 *this, Coroutine->CoroutinePromise, CallLoc, E);
886 if (RSS.IsInvalid)
887 return ExprError();
888
889 Expr *Res =
890 new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
891 RSS.Results[2], RSS.OpaqueValue, IsImplicit);
892
893 return Res;
894}
895
896ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
897 if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
898 CorrectDelayedTyposInExpr(E);
899 return ExprError();
900 }
901
902 checkSuspensionContext(*this, Loc, "co_yield");
903
904 // Build yield_value call.
905 ExprResult Awaitable = buildPromiseCall(
906 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);
907 if (Awaitable.isInvalid())
908 return ExprError();
909
910 // Build 'operator co_await' call.
911 Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
912 if (Awaitable.isInvalid())
913 return ExprError();
914
915 return BuildCoyieldExpr(Loc, Awaitable.get());
916}
917ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
918 auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
919 if (!Coroutine)
920 return ExprError();
921
922 if (E->getType()->isPlaceholderType()) {
923 ExprResult R = CheckPlaceholderExpr(E);
924 if (R.isInvalid()) return ExprError();
925 E = R.get();
926 }
927
928 if (E->getType()->isDependentType()) {
929 Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
930 return Res;
931 }
932
933 // If the expression is a temporary, materialize it as an lvalue so that we
934 // can use it multiple times.
935 if (E->isPRValue())
936 E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
937
938 // Build the await_ready, await_suspend, await_resume calls.
939 ReadySuspendResumeResult RSS = buildCoawaitCalls(
940 *this, Coroutine->CoroutinePromise, Loc, E);
941 if (RSS.IsInvalid)
942 return ExprError();
943
944 Expr *Res =
945 new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
946 RSS.Results[2], RSS.OpaqueValue);
947
948 return Res;
949}
950
951StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
952 if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
1
Calling 'Sema::ActOnCoroutineBodyStart'
953 CorrectDelayedTyposInExpr(E);
954 return StmtError();
955 }
956 return BuildCoreturnStmt(Loc, E);
957}
958
959StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
960 bool IsImplicit) {
961 auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
962 if (!FSI)
963 return StmtError();
964
965 if (E && E->getType()->isPlaceholderType() &&
966 !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
967 ExprResult R = CheckPlaceholderExpr(E);
968 if (R.isInvalid()) return StmtError();
969 E = R.get();
970 }
971
972 VarDecl *Promise = FSI->CoroutinePromise;
973 ExprResult PC;
974 if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
975 getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn);
976 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
977 } else {
978 E = MakeFullDiscardedValueExpr(E).get();
979 PC = buildPromiseCall(*this, Promise, Loc, "return_void", None);
980 }
981 if (PC.isInvalid())
982 return StmtError();
983
984 Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
985
986 Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
987 return Res;
988}
989
990/// Look up the std::nothrow object.
991static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) {
992 NamespaceDecl *Std = S.getStdNamespace();
993 assert(Std && "Should already be diagnosed")(static_cast <bool> (Std && "Should already be diagnosed"
) ? void (0) : __assert_fail ("Std && \"Should already be diagnosed\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 993, __extension__ __PRETTY_FUNCTION__))
;
994
995 LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc,
996 Sema::LookupOrdinaryName);
997 if (!S.LookupQualifiedName(Result, Std)) {
998 // FIXME: <coroutine> should have been included already.
999 // If we require it to include <new> then this diagnostic is no longer
1000 // needed.
1001 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
1002 return nullptr;
1003 }
1004
1005 auto *VD = Result.getAsSingle<VarDecl>();
1006 if (!VD) {
1007 Result.suppressDiagnostics();
1008 // We found something weird. Complain about the first thing we found.
1009 NamedDecl *Found = *Result.begin();
1010 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);
1011 return nullptr;
1012 }
1013
1014 ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc);
1015 if (DR.isInvalid())
1016 return nullptr;
1017
1018 return DR.get();
1019}
1020
1021// Find an appropriate delete for the promise.
1022static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
1023 QualType PromiseType) {
1024 FunctionDecl *OperatorDelete = nullptr;
1025
1026 DeclarationName DeleteName =
1027 S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
1028
1029 auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
1030 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1030, __extension__ __PRETTY_FUNCTION__))
;
1031
1032 if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
1033 return nullptr;
1034
1035 if (!OperatorDelete) {
1036 // Look for a global declaration.
1037 const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
1038 const bool Overaligned = false;
1039 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
1040 Overaligned, DeleteName);
1041 }
1042 S.MarkFunctionReferenced(Loc, OperatorDelete);
1043 return OperatorDelete;
1044}
1045
1046
1047void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
1048 FunctionScopeInfo *Fn = getCurFunction();
1049 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1049, __extension__ __PRETTY_FUNCTION__))
;
1050 if (!Body) {
1051 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1052, __extension__ __PRETTY_FUNCTION__))
1052 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1052, __extension__ __PRETTY_FUNCTION__))
;
1053 return;
1054 }
1055 // We have a function that uses coroutine keywords, but we failed to build
1056 // the promise type.
1057 if (!Fn->CoroutinePromise)
1058 return FD->setInvalidDecl();
1059
1060 if (isa<CoroutineBodyStmt>(Body)) {
1061 // Nothing todo. the body is already a transformed coroutine body statement.
1062 return;
1063 }
1064
1065 // Coroutines [stmt.return]p1:
1066 // A return statement shall not appear in a coroutine.
1067 if (Fn->FirstReturnLoc.isValid()) {
1068 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1069, __extension__ __PRETTY_FUNCTION__))
1069 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1069, __extension__ __PRETTY_FUNCTION__))
;
1070 Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
1071 Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1072 << Fn->getFirstCoroutineStmtKeyword();
1073 }
1074 CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
1075 if (Builder.isInvalid() || !Builder.buildStatements())
1076 return FD->setInvalidDecl();
1077
1078 // Build body for the coroutine wrapper statement.
1079 Body = CoroutineBodyStmt::Create(Context, Builder);
1080}
1081
1082CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
1083 sema::FunctionScopeInfo &Fn,
1084 Stmt *Body)
1085 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
1086 IsPromiseDependentType(
1087 !Fn.CoroutinePromise ||
1088 Fn.CoroutinePromise->getType()->isDependentType()) {
1089 this->Body = Body;
1090
1091 for (auto KV : Fn.CoroutineParameterMoves)
1092 this->ParamMovesVector.push_back(KV.second);
1093 this->ParamMoves = this->ParamMovesVector;
1094
1095 if (!IsPromiseDependentType) {
1096 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
1097 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1097, __extension__ __PRETTY_FUNCTION__))
;
1098 }
1099 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
1100}
1101
1102bool CoroutineStmtBuilder::buildStatements() {
1103 assert(this->IsValid && "coroutine already invalid")(static_cast <bool> (this->IsValid && "coroutine already invalid"
) ? void (0) : __assert_fail ("this->IsValid && \"coroutine already invalid\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1103, __extension__ __PRETTY_FUNCTION__))
;
1104 this->IsValid = makeReturnObject();
1105 if (this->IsValid && !IsPromiseDependentType)
1106 buildDependentStatements();
1107 return this->IsValid;
1108}
1109
1110bool CoroutineStmtBuilder::buildDependentStatements() {
1111 assert(this->IsValid && "coroutine already invalid")(static_cast <bool> (this->IsValid && "coroutine already invalid"
) ? void (0) : __assert_fail ("this->IsValid && \"coroutine already invalid\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1111, __extension__ __PRETTY_FUNCTION__))
;
1112 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1113, __extension__ __PRETTY_FUNCTION__))
1113 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1113, __extension__ __PRETTY_FUNCTION__))
;
1114 this->IsValid = makeOnException() && makeOnFallthrough() &&
1115 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
1116 makeNewAndDeleteExpr();
1117 return this->IsValid;
1118}
1119
1120bool CoroutineStmtBuilder::makePromiseStmt() {
1121 // Form a declaration statement for the promise declaration, so that AST
1122 // visitors can more easily find it.
1123 StmtResult PromiseStmt =
1124 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc);
1125 if (PromiseStmt.isInvalid())
1126 return false;
1127
1128 this->Promise = PromiseStmt.get();
1129 return true;
1130}
1131
1132bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {
1133 if (Fn.hasInvalidCoroutineSuspends())
1134 return false;
1135 this->InitialSuspend = cast<Expr>(Fn.CoroutineSuspends.first);
1136 this->FinalSuspend = cast<Expr>(Fn.CoroutineSuspends.second);
1137 return true;
1138}
1139
1140static bool diagReturnOnAllocFailure(Sema &S, Expr *E,
1141 CXXRecordDecl *PromiseRecordDecl,
1142 FunctionScopeInfo &Fn) {
1143 auto Loc = E->getExprLoc();
1144 if (auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {
1145 auto *Decl = DeclRef->getDecl();
1146 if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl)) {
1147 if (Method->isStatic())
1148 return true;
1149 else
1150 Loc = Decl->getLocation();
1151 }
1152 }
1153
1154 S.Diag(
1155 Loc,
1156 diag::err_coroutine_promise_get_return_object_on_allocation_failure)
1157 << PromiseRecordDecl;
1158 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1159 << Fn.getFirstCoroutineStmtKeyword();
1160 return false;
1161}
1162
1163bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
1164 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1165, __extension__ __PRETTY_FUNCTION__))
1165 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1165, __extension__ __PRETTY_FUNCTION__))
;
1166
1167 // [dcl.fct.def.coroutine]/8
1168 // The unqualified-id get_return_object_on_allocation_failure is looked up in
1169 // the scope of class P by class member access lookup (3.4.5). ...
1170 // If an allocation function returns nullptr, ... the coroutine return value
1171 // is obtained by a call to ... get_return_object_on_allocation_failure().
1172
1173 DeclarationName DN =
1174 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");
1175 LookupResult Found(S, DN, Loc, Sema::LookupMemberName);
1176 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))
1177 return true;
1178
1179 CXXScopeSpec SS;
1180 ExprResult DeclNameExpr =
1181 S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false);
1182 if (DeclNameExpr.isInvalid())
1183 return false;
1184
1185 if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn))
1186 return false;
1187
1188 ExprResult ReturnObjectOnAllocationFailure =
1189 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
1190 if (ReturnObjectOnAllocationFailure.isInvalid())
1191 return false;
1192
1193 StmtResult ReturnStmt =
1194 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
1195 if (ReturnStmt.isInvalid()) {
1196 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
1197 << DN;
1198 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1199 << Fn.getFirstCoroutineStmtKeyword();
1200 return false;
1201 }
1202
1203 this->ReturnStmtOnAllocFailure = ReturnStmt.get();
1204 return true;
1205}
1206
1207bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
1208 // Form and check allocation and deallocation calls.
1209 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1210, __extension__ __PRETTY_FUNCTION__))
1210 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1210, __extension__ __PRETTY_FUNCTION__))
;
1211 QualType PromiseType = Fn.CoroutinePromise->getType();
1212
1213 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
1214 return false;
1215
1216 const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
1217
1218 // [dcl.fct.def.coroutine]/7
1219 // Lookup allocation functions using a parameter list composed of the
1220 // requested size of the coroutine state being allocated, followed by
1221 // the coroutine function's arguments. If a matching allocation function
1222 // exists, use it. Otherwise, use an allocation function that just takes
1223 // the requested size.
1224
1225 FunctionDecl *OperatorNew = nullptr;
1226 FunctionDecl *OperatorDelete = nullptr;
1227 FunctionDecl *UnusedResult = nullptr;
1228 bool PassAlignment = false;
1229 SmallVector<Expr *, 1> PlacementArgs;
1230
1231 // [dcl.fct.def.coroutine]/7
1232 // "The allocation function’s name is looked up in the scope of P.
1233 // [...] If the lookup finds an allocation function in the scope of P,
1234 // overload resolution is performed on a function call created by assembling
1235 // an argument list. The first argument is the amount of space requested,
1236 // and has type std::size_t. The lvalues p1 ... pn are the succeeding
1237 // arguments."
1238 //
1239 // ...where "p1 ... pn" are defined earlier as:
1240 //
1241 // [dcl.fct.def.coroutine]/3
1242 // "For a coroutine f that is a non-static member function, let P1 denote the
1243 // type of the implicit object parameter (13.3.1) and P2 ... Pn be the types
1244 // of the function parameters; otherwise let P1 ... Pn be the types of the
1245 // function parameters. Let p1 ... pn be lvalues denoting those objects."
1246 if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
1247 if (MD->isInstance() && !isLambdaCallOperator(MD)) {
1248 ExprResult ThisExpr = S.ActOnCXXThis(Loc);
1249 if (ThisExpr.isInvalid())
1250 return false;
1251 ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
1252 if (ThisExpr.isInvalid())
1253 return false;
1254 PlacementArgs.push_back(ThisExpr.get());
1255 }
1256 }
1257 for (auto *PD : FD.parameters()) {
1258 if (PD->getType()->isDependentType())
1259 continue;
1260
1261 // Build a reference to the parameter.
1262 auto PDLoc = PD->getLocation();
1263 ExprResult PDRefExpr =
1264 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
1265 ExprValueKind::VK_LValue, PDLoc);
1266 if (PDRefExpr.isInvalid())
1267 return false;
1268
1269 PlacementArgs.push_back(PDRefExpr.get());
1270 }
1271 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
1272 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1273 /*isArray*/ false, PassAlignment, PlacementArgs,
1274 OperatorNew, UnusedResult, /*Diagnose*/ false);
1275
1276 // [dcl.fct.def.coroutine]/7
1277 // "If no matching function is found, overload resolution is performed again
1278 // on a function call created by passing just the amount of space required as
1279 // an argument of type std::size_t."
1280 if (!OperatorNew && !PlacementArgs.empty()) {
1281 PlacementArgs.clear();
1282 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
1283 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1284 /*isArray*/ false, PassAlignment, PlacementArgs,
1285 OperatorNew, UnusedResult, /*Diagnose*/ false);
1286 }
1287
1288 // [dcl.fct.def.coroutine]/7
1289 // "The allocation function’s name is looked up in the scope of P. If this
1290 // lookup fails, the allocation function’s name is looked up in the global
1291 // scope."
1292 if (!OperatorNew) {
1293 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Global,
1294 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1295 /*isArray*/ false, PassAlignment, PlacementArgs,
1296 OperatorNew, UnusedResult);
1297 }
1298
1299 bool IsGlobalOverload =
1300 OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
1301 // If we didn't find a class-local new declaration and non-throwing new
1302 // was is required then we need to lookup the non-throwing global operator
1303 // instead.
1304 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
1305 auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc);
1306 if (!StdNoThrow)
1307 return false;
1308 PlacementArgs = {StdNoThrow};
1309 OperatorNew = nullptr;
1310 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
1311 /*DeleteScope*/ Sema::AFS_Both, PromiseType,
1312 /*isArray*/ false, PassAlignment, PlacementArgs,
1313 OperatorNew, UnusedResult);
1314 }
1315
1316 if (!OperatorNew)
1317 return false;
1318
1319 if (RequiresNoThrowAlloc) {
1320 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();
1321 if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
1322 S.Diag(OperatorNew->getLocation(),
1323 diag::err_coroutine_promise_new_requires_nothrow)
1324 << OperatorNew;
1325 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
1326 << OperatorNew;
1327 return false;
1328 }
1329 }
1330
1331 if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr)
1332 return false;
1333
1334 Expr *FramePtr =
1335 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
1336
1337 Expr *FrameSize =
1338 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
1339
1340 // Make new call.
1341
1342 ExprResult NewRef =
1343 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
1344 if (NewRef.isInvalid())
1345 return false;
1346
1347 SmallVector<Expr *, 2> NewArgs(1, FrameSize);
1348 for (auto Arg : PlacementArgs)
1349 NewArgs.push_back(Arg);
1350
1351 ExprResult NewExpr =
1352 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
1353 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
1354 if (NewExpr.isInvalid())
1355 return false;
1356
1357 // Make delete call.
1358
1359 QualType OpDeleteQualType = OperatorDelete->getType();
1360
1361 ExprResult DeleteRef =
1362 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
1363 if (DeleteRef.isInvalid())
1364 return false;
1365
1366 Expr *CoroFree =
1367 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
1368
1369 SmallVector<Expr *, 2> DeleteArgs{CoroFree};
1370
1371 // Check if we need to pass the size.
1372 const auto *OpDeleteType =
1373 OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
1374 if (OpDeleteType->getNumParams() > 1)
1375 DeleteArgs.push_back(FrameSize);
1376
1377 ExprResult DeleteExpr =
1378 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
1379 DeleteExpr =
1380 S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
1381 if (DeleteExpr.isInvalid())
1382 return false;
1383
1384 this->Allocate = NewExpr.get();
1385 this->Deallocate = DeleteExpr.get();
1386
1387 return true;
1388}
1389
1390bool CoroutineStmtBuilder::makeOnFallthrough() {
1391 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1392, __extension__ __PRETTY_FUNCTION__))
1392 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1392, __extension__ __PRETTY_FUNCTION__))
;
1393
1394 // [dcl.fct.def.coroutine]/4
1395 // The unqualified-ids 'return_void' and 'return_value' are looked up in
1396 // the scope of class P. If both are found, the program is ill-formed.
1397 bool HasRVoid, HasRValue;
1398 LookupResult LRVoid =
1399 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
1400 LookupResult LRValue =
1401 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
1402
1403 StmtResult Fallthrough;
1404 if (HasRVoid && HasRValue) {
1405 // FIXME Improve this diagnostic
1406 S.Diag(FD.getLocation(),
1407 diag::err_coroutine_promise_incompatible_return_functions)
1408 << PromiseRecordDecl;
1409 S.Diag(LRVoid.getRepresentativeDecl()->getLocation(),
1410 diag::note_member_first_declared_here)
1411 << LRVoid.getLookupName();
1412 S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
1413 diag::note_member_first_declared_here)
1414 << LRValue.getLookupName();
1415 return false;
1416 } else if (!HasRVoid && !HasRValue) {
1417 // FIXME: The PDTS currently specifies this case as UB, not ill-formed.
1418 // However we still diagnose this as an error since until the PDTS is fixed.
1419 S.Diag(FD.getLocation(),
1420 diag::err_coroutine_promise_requires_return_function)
1421 << PromiseRecordDecl;
1422 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1423 << PromiseRecordDecl;
1424 return false;
1425 } else if (HasRVoid) {
1426 // If the unqualified-id return_void is found, flowing off the end of a
1427 // coroutine is equivalent to a co_return with no operand. Otherwise,
1428 // flowing off the end of a coroutine results in undefined behavior.
1429 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,
1430 /*IsImplicit*/false);
1431 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());
1432 if (Fallthrough.isInvalid())
1433 return false;
1434 }
1435
1436 this->OnFallthrough = Fallthrough.get();
1437 return true;
1438}
1439
1440bool CoroutineStmtBuilder::makeOnException() {
1441 // Try to form 'p.unhandled_exception();'
1442 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1443, __extension__ __PRETTY_FUNCTION__))
1443 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1443, __extension__ __PRETTY_FUNCTION__))
;
1444
1445 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
1446
1447 if (!lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {
1448 auto DiagID =
1449 RequireUnhandledException
1450 ? diag::err_coroutine_promise_unhandled_exception_required
1451 : diag::
1452 warn_coroutine_promise_unhandled_exception_required_with_exceptions;
1453 S.Diag(Loc, DiagID) << PromiseRecordDecl;
1454 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
1455 << PromiseRecordDecl;
1456 return !RequireUnhandledException;
1457 }
1458
1459 // If exceptions are disabled, don't try to build OnException.
1460 if (!S.getLangOpts().CXXExceptions)
1461 return true;
1462
1463 ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
1464 "unhandled_exception", None);
1465 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
1466 /*DiscardedValue*/ false);
1467 if (UnhandledException.isInvalid())
1468 return false;
1469
1470 // Since the body of the coroutine will be wrapped in try-catch, it will
1471 // be incompatible with SEH __try if present in a function.
1472 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
1473 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
1474 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1475 << Fn.getFirstCoroutineStmtKeyword();
1476 return false;
1477 }
1478
1479 this->OnException = UnhandledException.get();
1480 return true;
1481}
1482
1483bool CoroutineStmtBuilder::makeReturnObject() {
1484 // Build implicit 'p.get_return_object()' expression and form initialization
1485 // of return type from it.
1486 ExprResult ReturnObject =
1487 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
1488 if (ReturnObject.isInvalid())
1489 return false;
1490
1491 this->ReturnValue = ReturnObject.get();
1492 return true;
1493}
1494
1495static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn) {
1496 if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
1497 auto *MethodDecl = MbrRef->getMethodDecl();
1498 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
1499 << MethodDecl;
1500 }
1501 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
1502 << Fn.getFirstCoroutineStmtKeyword();
1503}
1504
1505bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
1506 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1507, __extension__ __PRETTY_FUNCTION__))
1507 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1507, __extension__ __PRETTY_FUNCTION__))
;
1508 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1508, __extension__ __PRETTY_FUNCTION__))
;
1509
1510 QualType const GroType = this->ReturnValue->getType();
1511 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1512, __extension__ __PRETTY_FUNCTION__))
1512 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1512, __extension__ __PRETTY_FUNCTION__))
;
1513
1514 QualType const FnRetType = FD.getReturnType();
1515 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1516, __extension__ __PRETTY_FUNCTION__))
1516 "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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1516, __extension__ __PRETTY_FUNCTION__))
;
1517
1518 if (FnRetType->isVoidType()) {
1519 ExprResult Res =
1520 S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
1521 if (Res.isInvalid())
1522 return false;
1523
1524 this->ResultDecl = Res.get();
1525 return true;
1526 }
1527
1528 if (GroType->isVoidType()) {
1529 // Trigger a nice error message.
1530 InitializedEntity Entity =
1531 InitializedEntity::InitializeResult(Loc, FnRetType);
1532 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1533 noteMemberDeclaredHere(S, ReturnValue, Fn);
1534 return false;
1535 }
1536
1537 auto *GroDecl = VarDecl::Create(
1538 S.Context, &FD, FD.getLocation(), FD.getLocation(),
1539 &S.PP.getIdentifierTable().get("__coro_gro"), GroType,
1540 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
1541 GroDecl->setImplicit();
1542
1543 S.CheckVariableDeclarationType(GroDecl);
1544 if (GroDecl->isInvalidDecl())
1545 return false;
1546
1547 InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
1548 ExprResult Res =
1549 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
1550 if (Res.isInvalid())
1551 return false;
1552
1553 Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
1554 if (Res.isInvalid())
1555 return false;
1556
1557 S.AddInitializerToDecl(GroDecl, Res.get(),
1558 /*DirectInit=*/false);
1559
1560 S.FinalizeDeclaration(GroDecl);
1561
1562 // Form a declaration statement for the return declaration, so that AST
1563 // visitors can more easily find it.
1564 StmtResult GroDeclStmt =
1565 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
1566 if (GroDeclStmt.isInvalid())
1567 return false;
1568
1569 this->ResultDecl = GroDeclStmt.get();
1570
1571 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
1572 if (declRef.isInvalid())
1573 return false;
1574
1575 StmtResult ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
1576 if (ReturnStmt.isInvalid()) {
1577 noteMemberDeclaredHere(S, ReturnValue, Fn);
1578 return false;
1579 }
1580 if (cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
1581 GroDecl->setNRVOVariable(true);
1582
1583 this->ReturnStmt = ReturnStmt.get();
1584 return true;
1585}
1586
1587// Create a static_cast\<T&&>(expr).
1588static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
1589 if (T.isNull())
1590 T = E->getType();
1591 QualType TargetType = S.BuildReferenceType(
1592 T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
1593 SourceLocation ExprLoc = E->getBeginLoc();
1594 TypeSourceInfo *TargetLoc =
1595 S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
1596
1597 return S
1598 .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
1599 SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
1600 .get();
1601}
1602
1603/// Build a variable declaration for move parameter.
1604static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type,
1605 IdentifierInfo *II) {
1606 TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc);
1607 VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
1608 TInfo, SC_None);
1609 Decl->setImplicit();
1610 return Decl;
1611}
1612
1613// Build statements that move coroutine function parameters to the coroutine
1614// frame, and store them on the function scope info.
1615bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
1616 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\""
, "/build/llvm-toolchain-snapshot-14~++20211110111138+cffbfd01e37b/clang/lib/Sema/SemaCoroutine.cpp"
, 1616, __extension__ __PRETTY_FUNCTION__))
;
1617 auto *FD = cast<FunctionDecl>(CurContext);
1618
1619 auto *ScopeInfo = getCurFunction();
1620 if (!ScopeInfo->CoroutineParameterMoves.empty())
1621 return false;
1622
1623 for (auto *PD : FD->parameters()) {
1624 if (PD->getType()->isDependentType())
1625 continue;
1626
1627 ExprResult PDRefExpr =
1628 BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
1629 ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1630 if (PDRefExpr.isInvalid())
1631 return false;
1632
1633 Expr *CExpr = nullptr;
1634 if (PD->getType()->getAsCXXRecordDecl() ||
1635 PD->getType()->isRValueReferenceType())
1636 CExpr = castForMoving(*this, PDRefExpr.get());
1637 else
1638 CExpr = PDRefExpr.get();
1639
1640 auto D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
1641 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
1642
1643 // Convert decl to a statement.
1644 StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc, Loc);
1645 if (Stmt.isInvalid())
1646 return false;
1647
1648 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
1649 }
1650 return true;
1651}
1652
1653StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
1654 CoroutineBodyStmt *Res = CoroutineBodyStmt::Create(Context, Args);
1655 if (!Res)
1656 return StmtError();
1657 return Res;
1658}
1659
1660ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
1661 SourceLocation FuncLoc,
1662 NamespaceDecl *&Namespace) {
1663 if (!StdCoroutineTraitsCache) {
1664 NamespaceDecl *CoroNamespace = getStdNamespace();
1665 LookupResult Result(*this, &PP.getIdentifierTable().get("coroutine_traits"),
1666 FuncLoc, LookupOrdinaryName);
1667
1668 if (!CoroNamespace || !LookupQualifiedName(Result, CoroNamespace)) {
1669 /// Look up in namespace std::experimental, for compatibility.
1670 /// TODO: Remove this extra lookup when <experimental/coroutine> is
1671 /// removed.
1672 CoroNamespace = lookupStdExperimentalNamespace();
1673 if (!CoroNamespace || !LookupQualifiedName(Result, CoroNamespace)) {
1674 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
1675 << "std::coroutine_traits";
1676 return nullptr;
1677 }
1678 /// TODO: Add a warning about not including <experimental/coroutine>
1679 /// once we update libcxx.
1680 } else {
1681 /// When we found coroutine_traits in std namespace. Make sure there is no
1682 /// misleading definition in std::experimental namespace.
1683 NamespaceDecl *ExpNamespace = lookupStdExperimentalNamespace();
1684 LookupResult ExpResult(*this,
1685 &PP.getIdentifierTable().get("coroutine_traits"),
1686 FuncLoc, LookupOrdinaryName);
1687 if (ExpNamespace && LookupQualifiedName(ExpResult, ExpNamespace)) {
1688 Diag(KwLoc,
1689 diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
1690 return nullptr;
1691 }
1692 }
1693
1694 if (!(StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>())) {
1695 Result.suppressDiagnostics();
1696 NamedDecl *Found = *Result.begin();
1697 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
1698 return nullptr;
1699 }
1700 CoroTraitsNamespaceCache = CoroNamespace;
1701 }
1702 Namespace = CoroTraitsNamespaceCache;
1703 return StdCoroutineTraitsCache;
1704}