diff options
Diffstat (limited to 'include/clang/Sema/ScopeInfo.h')
-rw-r--r-- | include/clang/Sema/ScopeInfo.h | 81 |
1 files changed, 73 insertions, 8 deletions
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index 4b54807ab660..4487c7c2ccb6 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -24,6 +24,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include <algorithm> namespace clang { @@ -135,6 +136,18 @@ public: /// false if there is an invocation of an initializer on 'self'. bool ObjCWarnForNoInitDelegation : 1; + /// \brief True only when this function has not already built, or attempted + /// to build, the initial and final coroutine suspend points + bool NeedsCoroutineSuspends : 1; + + /// \brief An enumeration represeting the kind of the first coroutine statement + /// in the function. One of co_return, co_await, or co_yield. + unsigned char FirstCoroutineStmtKind : 2; + + /// First coroutine statement in the current function. + /// (ex co_return, co_await, co_yield) + SourceLocation FirstCoroutineStmtLoc; + /// First 'return' statement in the current function. SourceLocation FirstReturnLoc; @@ -157,12 +170,10 @@ public: SmallVector<ReturnStmt*, 4> Returns; /// \brief The promise object for this coroutine, if any. - VarDecl *CoroutinePromise; + VarDecl *CoroutinePromise = nullptr; - /// \brief The list of coroutine control flow constructs (co_await, co_yield, - /// co_return) that occur within the function or block. Empty if and only if - /// this function or block is not (yet known to be) a coroutine. - SmallVector<Stmt*, 4> CoroutineStmts; + /// \brief The initial and final coroutine suspend points. + std::pair<Stmt *, Stmt *> CoroutineSuspends; /// \brief The stack of currently active compound stamement scopes in the /// function. @@ -376,7 +387,47 @@ public: (HasIndirectGoto || (HasBranchProtectedScope && HasBranchIntoScope)); } - + + void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) { + assert(FirstCoroutineStmtLoc.isInvalid() && + "first coroutine statement location already set"); + FirstCoroutineStmtLoc = Loc; + FirstCoroutineStmtKind = llvm::StringSwitch<unsigned char>(Keyword) + .Case("co_return", 0) + .Case("co_await", 1) + .Case("co_yield", 2); + } + + StringRef getFirstCoroutineStmtKeyword() const { + assert(FirstCoroutineStmtLoc.isValid() + && "no coroutine statement available"); + switch (FirstCoroutineStmtKind) { + case 0: return "co_return"; + case 1: return "co_await"; + case 2: return "co_yield"; + default: + llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); + }; + } + + void setNeedsCoroutineSuspends(bool value = true) { + assert((!value || CoroutineSuspends.first == nullptr) && + "we already have valid suspend points"); + NeedsCoroutineSuspends = value; + } + + bool hasInvalidCoroutineSuspends() const { + return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr; + } + + void setCoroutineSuspends(Stmt *Initial, Stmt *Final) { + assert(Initial && Final && "suspend points cannot be null"); + assert(CoroutineSuspends.first == nullptr && "suspend points already set"); + NeedsCoroutineSuspends = false; + CoroutineSuspends.first = Initial; + CoroutineSuspends.second = Final; + } + FunctionScopeInfo(DiagnosticsEngine &Diag) : Kind(SK_Function), HasBranchProtectedScope(false), @@ -391,6 +442,7 @@ public: ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), + NeedsCoroutineSuspends(true), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); @@ -452,6 +504,14 @@ public: /// non-static data member that would hold the capture. QualType CaptureType; + /// \brief Whether an explicit capture has been odr-used in the body of the + /// lambda. + bool ODRUsed; + + /// \brief Whether an explicit capture has been non-odr-used in the body of + /// the lambda. + bool NonODRUsed; + public: Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, SourceLocation Loc, SourceLocation EllipsisLoc, @@ -460,7 +520,8 @@ public: InitExprAndCaptureKind( Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy), - Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} + Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType), + ODRUsed(false), NonODRUsed(false) {} enum IsThisCapture { ThisCapture }; Capture(IsThisCapture, bool IsNested, SourceLocation Loc, @@ -468,7 +529,8 @@ public: : VarAndNestedAndThis( nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), - Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {} + Loc(Loc), EllipsisLoc(), CaptureType(CaptureType), ODRUsed(false), + NonODRUsed(false) {} bool isThisCapture() const { return VarAndNestedAndThis.getInt() & IsThisCaptured; @@ -491,6 +553,9 @@ public: bool isNested() const { return VarAndNestedAndThis.getInt() & IsNestedCapture; } + bool isODRUsed() const { return ODRUsed; } + bool isNonODRUsed() const { return NonODRUsed; } + void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } VarDecl *getVariable() const { return VarAndNestedAndThis.getPointer(); |