clang  3.9.0
SemaCoroutine.cpp
Go to the documentation of this file.
1 //===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements semantic analysis for C++ Coroutines.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/ExprCXX.h"
17 #include "clang/AST/StmtCXX.h"
18 #include "clang/Lex/Preprocessor.h"
20 #include "clang/Sema/Overload.h"
21 using namespace clang;
22 using namespace sema;
23 
24 /// Look up the std::coroutine_traits<...>::promise_type for the given
25 /// function type.
27  SourceLocation Loc) {
28  // FIXME: Cache std::coroutine_traits once we've found it.
29  NamespaceDecl *Std = S.getStdNamespace();
30  if (!Std) {
31  S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
32  return QualType();
33  }
34 
35  LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
37  if (!S.LookupQualifiedName(Result, Std)) {
38  S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
39  return QualType();
40  }
41 
42  ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
43  if (!CoroTraits) {
44  Result.suppressDiagnostics();
45  // We found something weird. Complain about the first thing we found.
46  NamedDecl *Found = *Result.begin();
47  S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
48  return QualType();
49  }
50 
51  // Form template argument list for coroutine_traits<R, P1, P2, ...>.
52  TemplateArgumentListInfo Args(Loc, Loc);
56  // FIXME: If the function is a non-static member function, add the type
57  // of the implicit object parameter before the formal parameters.
58  for (QualType T : FnType->getParamTypes())
61 
62  // Build the template-id.
63  QualType CoroTrait =
64  S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args);
65  if (CoroTrait.isNull())
66  return QualType();
67  if (S.RequireCompleteType(Loc, CoroTrait,
68  diag::err_coroutine_traits_missing_specialization))
69  return QualType();
70 
71  CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl();
72  assert(RD && "specialization of class template is not a class?");
73 
74  // Look up the ::promise_type member.
75  LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc,
77  S.LookupQualifiedName(R, RD);
78  auto *Promise = R.getAsSingle<TypeDecl>();
79  if (!Promise) {
80  S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
81  << RD;
82  return QualType();
83  }
84 
85  // The promise type is required to be a class type.
86  QualType PromiseType = S.Context.getTypeDeclType(Promise);
87  if (!PromiseType->getAsCXXRecordDecl()) {
88  // Use the fully-qualified name of the type.
89  auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std);
90  NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
91  CoroTrait.getTypePtr());
92  PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
93 
94  S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
95  << PromiseType;
96  return QualType();
97  }
98 
99  return PromiseType;
100 }
101 
102 /// Check that this is a context in which a coroutine suspension can appear.
103 static FunctionScopeInfo *
104 checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
105  // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
106  if (S.isUnevaluatedContext()) {
107  S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
108  return nullptr;
109  }
110 
111  // Any other usage must be within a function.
112  // FIXME: Reject a coroutine with a deduced return type.
113  auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
114  if (!FD) {
115  S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
116  ? diag::err_coroutine_objc_method
117  : diag::err_coroutine_outside_function) << Keyword;
118  } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
119  // Coroutines TS [special]/6:
120  // A special member function shall not be a coroutine.
121  //
122  // FIXME: We assume that this really means that a coroutine cannot
123  // be a constructor or destructor.
124  S.Diag(Loc, diag::err_coroutine_ctor_dtor)
125  << isa<CXXDestructorDecl>(FD) << Keyword;
126  } else if (FD->isConstexpr()) {
127  S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
128  } else if (FD->isVariadic()) {
129  S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
130  } else {
131  auto *ScopeInfo = S.getCurFunction();
132  assert(ScopeInfo && "missing function scope for function");
133 
134  // If we don't have a promise variable, build one now.
135  if (!ScopeInfo->CoroutinePromise) {
136  QualType T =
137  FD->getType()->isDependentType()
138  ? S.Context.DependentTy
139  : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(),
140  Loc);
141  if (T.isNull())
142  return nullptr;
143 
144  // Create and default-initialize the promise.
145  ScopeInfo->CoroutinePromise =
146  VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
147  &S.PP.getIdentifierTable().get("__promise"), T,
149  S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
150  if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
151  S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
152  }
153 
154  return ScopeInfo;
155  }
156 
157  return nullptr;
158 }
159 
160 /// Build a call to 'operator co_await' if there is a suitable operator for
161 /// the given expression.
163  SourceLocation Loc, Expr *E) {
164  UnresolvedSet<16> Functions;
165  SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
166  Functions);
167  return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
168 }
169 
171  bool IsInvalid;
172  Expr *Results[3];
173 };
174 
176  StringRef Name,
178  DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
179 
180  // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
181  CXXScopeSpec SS;
183  Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
184  SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
185  /*Scope=*/nullptr);
186  if (Result.isInvalid())
187  return ExprError();
188 
189  return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
190 }
191 
192 /// Build calls to await_ready, await_suspend, and await_resume for a co_await
193 /// expression.
195  Expr *E) {
196  // Assume invalid until we see otherwise.
197  ReadySuspendResumeResult Calls = {true, {}};
198 
199  const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
200  for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
201  Expr *Operand = new (S.Context) OpaqueValueExpr(
202  Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
203 
204  // FIXME: Pass coroutine handle to await_suspend.
205  ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
206  if (Result.isInvalid())
207  return Calls;
208  Calls.Results[I] = Result.get();
209  }
210 
211  Calls.IsInvalid = false;
212  return Calls;
213 }
214 
216  if (E->getType()->isPlaceholderType()) {
217  ExprResult R = CheckPlaceholderExpr(E);
218  if (R.isInvalid()) return ExprError();
219  E = R.get();
220  }
221 
222  ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
223  if (Awaitable.isInvalid())
224  return ExprError();
225  return BuildCoawaitExpr(Loc, Awaitable.get());
226 }
228  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
229  if (!Coroutine)
230  return ExprError();
231 
232  if (E->getType()->isPlaceholderType()) {
233  ExprResult R = CheckPlaceholderExpr(E);
234  if (R.isInvalid()) return ExprError();
235  E = R.get();
236  }
237 
238  if (E->getType()->isDependentType()) {
239  Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
240  Coroutine->CoroutineStmts.push_back(Res);
241  return Res;
242  }
243 
244  // If the expression is a temporary, materialize it as an lvalue so that we
245  // can use it multiple times.
246  if (E->getValueKind() == VK_RValue)
247  E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
248 
249  // Build the await_ready, await_suspend, await_resume calls.
250  ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
251  if (RSS.IsInvalid)
252  return ExprError();
253 
254  Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
255  RSS.Results[2]);
256  Coroutine->CoroutineStmts.push_back(Res);
257  return Res;
258 }
259 
261  SourceLocation Loc, StringRef Name,
263  assert(Coroutine->CoroutinePromise && "no promise for coroutine");
264 
265  // Form a reference to the promise.
266  auto *Promise = Coroutine->CoroutinePromise;
267  ExprResult PromiseRef = S.BuildDeclRefExpr(
268  Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
269  if (PromiseRef.isInvalid())
270  return ExprError();
271 
272  // Call 'yield_value', passing in E.
273  return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
274 }
275 
277  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
278  if (!Coroutine)
279  return ExprError();
280 
281  // Build yield_value call.
282  ExprResult Awaitable =
283  buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
284  if (Awaitable.isInvalid())
285  return ExprError();
286 
287  // Build 'operator co_await' call.
288  Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
289  if (Awaitable.isInvalid())
290  return ExprError();
291 
292  return BuildCoyieldExpr(Loc, Awaitable.get());
293 }
295  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
296  if (!Coroutine)
297  return ExprError();
298 
299  if (E->getType()->isPlaceholderType()) {
300  ExprResult R = CheckPlaceholderExpr(E);
301  if (R.isInvalid()) return ExprError();
302  E = R.get();
303  }
304 
305  if (E->getType()->isDependentType()) {
306  Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
307  Coroutine->CoroutineStmts.push_back(Res);
308  return Res;
309  }
310 
311  // If the expression is a temporary, materialize it as an lvalue so that we
312  // can use it multiple times.
313  if (E->getValueKind() == VK_RValue)
314  E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
315 
316  // Build the await_ready, await_suspend, await_resume calls.
317  ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
318  if (RSS.IsInvalid)
319  return ExprError();
320 
321  Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
322  RSS.Results[2]);
323  Coroutine->CoroutineStmts.push_back(Res);
324  return Res;
325 }
326 
328  return BuildCoreturnStmt(Loc, E);
329 }
331  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
332  if (!Coroutine)
333  return StmtError();
334 
335  if (E && E->getType()->isPlaceholderType() &&
336  !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
337  ExprResult R = CheckPlaceholderExpr(E);
338  if (R.isInvalid()) return StmtError();
339  E = R.get();
340  }
341 
342  // FIXME: If the operand is a reference to a variable that's about to go out
343  // of scope, we should treat the operand as an xvalue for this overload
344  // resolution.
345  ExprResult PC;
346  if (E && !E->getType()->isVoidType()) {
347  PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
348  } else {
349  E = MakeFullDiscardedValueExpr(E).get();
350  PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
351  }
352  if (PC.isInvalid())
353  return StmtError();
354 
355  Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
356 
357  Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
358  Coroutine->CoroutineStmts.push_back(Res);
359  return Res;
360 }
361 
363  FunctionScopeInfo *Fn = getCurFunction();
364  assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
365 
366  // Coroutines [stmt.return]p1:
367  // A return statement shall not appear in a coroutine.
368  if (Fn->FirstReturnLoc.isValid()) {
369  Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
370  auto *First = Fn->CoroutineStmts[0];
371  Diag(First->getLocStart(), diag::note_declared_coroutine_here)
372  << (isa<CoawaitExpr>(First) ? 0 :
373  isa<CoyieldExpr>(First) ? 1 : 2);
374  }
375 
376  bool AnyCoawaits = false;
377  bool AnyCoyields = false;
378  for (auto *CoroutineStmt : Fn->CoroutineStmts) {
379  AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
380  AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
381  }
382 
383  if (!AnyCoawaits && !AnyCoyields)
384  Diag(Fn->CoroutineStmts.front()->getLocStart(),
385  diag::ext_coroutine_without_co_await_co_yield);
386 
387  SourceLocation Loc = FD->getLocation();
388 
389  // Form a declaration statement for the promise declaration, so that AST
390  // visitors can more easily find it.
391  StmtResult PromiseStmt =
392  ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
393  if (PromiseStmt.isInvalid())
394  return FD->setInvalidDecl();
395 
396  // Form and check implicit 'co_await p.initial_suspend();' statement.
397  ExprResult InitialSuspend =
398  buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
399  // FIXME: Support operator co_await here.
400  if (!InitialSuspend.isInvalid())
401  InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
402  InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
403  if (InitialSuspend.isInvalid())
404  return FD->setInvalidDecl();
405 
406  // Form and check implicit 'co_await p.final_suspend();' statement.
407  ExprResult FinalSuspend =
408  buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
409  // FIXME: Support operator co_await here.
410  if (!FinalSuspend.isInvalid())
411  FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
412  FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
413  if (FinalSuspend.isInvalid())
414  return FD->setInvalidDecl();
415 
416  // FIXME: Perform analysis of set_exception call.
417 
418  // FIXME: Try to form 'p.return_void();' expression statement to handle
419  // control flowing off the end of the coroutine.
420 
421  // Build implicit 'p.get_return_object()' expression and form initialization
422  // of return type from it.
423  ExprResult ReturnObject =
424  buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
425  if (ReturnObject.isInvalid())
426  return FD->setInvalidDecl();
427  QualType RetType = FD->getReturnType();
428  if (!RetType->isDependentType()) {
429  InitializedEntity Entity =
430  InitializedEntity::InitializeResult(Loc, RetType, false);
431  ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
432  ReturnObject.get());
433  if (ReturnObject.isInvalid())
434  return FD->setInvalidDecl();
435  }
436  ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
437  if (ReturnObject.isInvalid())
438  return FD->setInvalidDecl();
439 
440  // FIXME: Perform move-initialization of parameters into frame-local copies.
441  SmallVector<Expr*, 16> ParamMoves;
442 
443  // Build body for the coroutine wrapper statement.
444  Body = new (Context) CoroutineBodyStmt(
445  Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
446  /*SetException*/nullptr, /*Fallthrough*/nullptr,
447  ReturnObject.get(), ParamMoves);
448 }
QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType) const
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:408
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1561
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
A (possibly-)qualified type.
Definition: Type.h:598
bool isInvalid() const
Definition: Ownership.h:160
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc...
Definition: Sema.h:2705
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition: StmtCXX.h:379
ExprResult BuildCoawaitExpr(SourceLocation KwLoc, Expr *E)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition: Sema.h:1139
PtrTy get() const
Definition: Ownership.h:164
NamespaceDecl - Represent a C++ namespace.
Definition: Decl.h:471
Retains information about a function, method, or block that is currently being parsed.
Definition: ScopeInfo.h:81
static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, IdentifierInfo *II)
Builds a specifier combining a prefix and an identifier.
StmtResult ActOnCoreturnStmt(SourceLocation KwLoc, Expr *E)
static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type, bool NRVO)
Create the initialization entity for the result of a function.
Defines the clang::Expr interface and subclasses for C++ expressions.
bool isVoidType() const
Definition: Type.h:5680
void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto)
Definition: SemaDecl.cpp:9988
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
Definition: SemaExpr.cpp:5115
static FunctionScopeInfo * checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword)
Check that this is a context in which a coroutine suspension can appear.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Definition: Type.h:4549
ArrayRef< QualType > getParamTypes() const
Definition: Type.h:3276
QualType getReturnType() const
Definition: Decl.h:2034
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *input)
Create a unary operation that may resolve to an overloaded operator.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1199
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:105
Represents the results of name lookup.
Definition: Sema/Lookup.h:30
bool isSpecificPlaceholderType(unsigned K) const
Test for a specific placeholder type.
Definition: Type.h:5667
A convenient class for passing around template argument information.
Definition: TemplateBase.h:523
QualType getReturnType() const
Definition: Type.h:3009
StmtResult StmtError()
Definition: Ownership.h:269
TypeDecl - Represents a declaration of a type.
Definition: Decl.h:2569
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:39
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:63
void CheckVariableDeclarationType(VarDecl *NewVD)
Definition: SemaDecl.cpp:6760
Preprocessor & PP
Definition: Sema.h:298
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:1800
ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs=nullptr)
detail::InMemoryDirectory::const_iterator I
bool isUnevaluatedContext() const
Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5...
Definition: Sema.h:6946
QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs)
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:263
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3073
ASTContext * Context
Expr - This represents one expression.
Definition: Expr.h:105
static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, SourceLocation Loc)
Look up the std::coroutine_traits<...>::promise_type for the given function type. ...
Defines the clang::Preprocessor interface.
Represents a C++ template name within the type system.
Definition: TemplateName.h:176
bool RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:6826
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:1774
The result type of a method or function.
VarDecl * CoroutinePromise
The promise object for this coroutine, if any.
Definition: ScopeInfo.h:156
static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, StringRef Name, MutableArrayRef< Expr * > Args)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
Definition: Expr.h:848
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:5259
SmallVector< Stmt *, 4 > CoroutineStmts
The list of coroutine control flow constructs (co_await, co_yield, co_return) that occur within the f...
Definition: ScopeInfo.h:161
bool isValid() const
Return true if this is a valid SourceLocation object.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location, which defaults to the empty location.
IdentifierTable & getIdentifierTable()
Definition: Preprocessor.h:697
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:1188
void addArgument(const TemplateArgumentLoc &Loc)
Definition: TemplateBase.h:563
QualType getType() const
Definition: Expr.h:126
Represents a template argument.
Definition: TemplateBase.h:40
static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine, SourceLocation Loc, StringRef Name, MutableArrayRef< Expr * > Args)
Represents a 'co_yield' expression.
Definition: ExprCXX.h:4228
A set of unresolved declarations.
detail::InMemoryDirectory::const_iterator E
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
SourceLocation FirstReturnLoc
First 'return' statement in the current function.
Definition: ScopeInfo.h:135
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, UnresolvedSetImpl &Functions)
Represents the body of a coroutine.
Definition: StmtCXX.h:299
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:427
ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)
CanQualType DependentTy
Definition: ASTContext.h:909
Represents a 'co_await' expression.
Definition: ExprCXX.h:4205
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1528
ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)
ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:1724
Represents a C++ struct/union/class.
Definition: DeclCXX.h:263
bool isPlaceholderType() const
Test for a type which does not represent an actual type-system type but is instead used as a placehol...
Definition: Type.h:5654
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:311
Declaration of a class template.
static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E)
Build a call to 'operator co_await' if there is a suitable operator for the given expression...
ExprResult ExprError()
Definition: Ownership.h:268
StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E)
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:401
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body)
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:109
ASTContext & Context
Definition: Sema.h:299
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
No keyword precedes the qualified type name.
Definition: Type.h:4372
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:665
Describes an entity that is being initialized.
NamespaceDecl * getStdNamespace() const
static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc, Expr *E)
Build calls to await_ready, await_suspend, and await_resume for a co_await expression.