summaryrefslogtreecommitdiff
path: root/include/clang/AST/StmtCXX.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/StmtCXX.h')
-rw-r--r--include/clang/AST/StmtCXX.h108
1 files changed, 76 insertions, 32 deletions
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 8eef34cb21b3c..56bfce987f5bd 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -296,7 +296,9 @@ public:
/// \brief Represents the body of a coroutine. This wraps the normal function
/// body and holds the additional semantic context required to set up and tear
/// down the coroutine frame.
-class CoroutineBodyStmt : public Stmt {
+class CoroutineBodyStmt final
+ : public Stmt,
+ private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> {
enum SubStmt {
Body, ///< The body of the coroutine.
Promise, ///< The promise statement.
@@ -307,65 +309,100 @@ class CoroutineBodyStmt : public Stmt {
Allocate, ///< Coroutine frame memory allocation.
Deallocate, ///< Coroutine frame memory deallocation.
ReturnValue, ///< Return value for thunk function.
+ ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
FirstParamMove ///< First offset for move construction of parameter copies.
};
- Stmt *SubStmts[SubStmt::FirstParamMove];
+ unsigned NumParams;
friend class ASTStmtReader;
+ friend TrailingObjects;
+
+ Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
+
+ Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
+
+public:
+
+ struct CtorArgs {
+ Stmt *Body = nullptr;
+ Stmt *Promise = nullptr;
+ Expr *InitialSuspend = nullptr;
+ Expr *FinalSuspend = nullptr;
+ Stmt *OnException = nullptr;
+ Stmt *OnFallthrough = nullptr;
+ Expr *Allocate = nullptr;
+ Expr *Deallocate = nullptr;
+ Stmt *ReturnValue = nullptr;
+ Stmt *ReturnStmtOnAllocFailure = nullptr;
+ ArrayRef<Stmt *> ParamMoves;
+ };
+
+private:
+
+ CoroutineBodyStmt(CtorArgs const& Args);
+
public:
- CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
- Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
- Expr *Allocate, Stmt *Deallocate,
- Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
- : Stmt(CoroutineBodyStmtClass) {
- SubStmts[CoroutineBodyStmt::Body] = Body;
- SubStmts[CoroutineBodyStmt::Promise] = Promise;
- SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
- SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
- SubStmts[CoroutineBodyStmt::OnException] = OnException;
- SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
- SubStmts[CoroutineBodyStmt::Allocate] = Allocate;
- SubStmts[CoroutineBodyStmt::Deallocate] = Deallocate;
- SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
- // FIXME: Tail-allocate space for parameter move expressions and store them.
- assert(ParamMoves.empty() && "not implemented yet");
+ static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args);
+
+ bool hasDependentPromiseType() const {
+ return getPromiseDecl()->getType()->isDependentType();
}
/// \brief Retrieve the body of the coroutine as written. This will be either
/// a CompoundStmt or a TryStmt.
Stmt *getBody() const {
- return SubStmts[SubStmt::Body];
+ return getStoredStmts()[SubStmt::Body];
}
- Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
+ Stmt *getPromiseDeclStmt() const {
+ return getStoredStmts()[SubStmt::Promise];
+ }
VarDecl *getPromiseDecl() const {
return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
}
- Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
- Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
+ Stmt *getInitSuspendStmt() const {
+ return getStoredStmts()[SubStmt::InitSuspend];
+ }
+ Stmt *getFinalSuspendStmt() const {
+ return getStoredStmts()[SubStmt::FinalSuspend];
+ }
- Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
+ Stmt *getExceptionHandler() const {
+ return getStoredStmts()[SubStmt::OnException];
+ }
Stmt *getFallthroughHandler() const {
- return SubStmts[SubStmt::OnFallthrough];
+ return getStoredStmts()[SubStmt::OnFallthrough];
}
- Expr *getAllocate() const { return cast<Expr>(SubStmts[SubStmt::Allocate]); }
- Stmt *getDeallocate() const { return SubStmts[SubStmt::Deallocate]; }
+ Expr *getAllocate() const {
+ return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]);
+ }
+ Expr *getDeallocate() const {
+ return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
+ }
Expr *getReturnValueInit() const {
- return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
+ return cast_or_null<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
+ }
+ Stmt *getReturnStmtOnAllocFailure() const {
+ return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
+ }
+ ArrayRef<Stmt const *> getParamMoves() const {
+ return {getStoredStmts() + SubStmt::FirstParamMove, NumParams};
}
SourceLocation getLocStart() const LLVM_READONLY {
- return getBody()->getLocStart();
+ return getBody() ? getBody()->getLocStart()
+ : getPromiseDecl()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
- return getBody()->getLocEnd();
+ return getBody() ? getBody()->getLocEnd() : getPromiseDecl()->getLocEnd();
}
child_range children() {
- return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove);
+ return child_range(getStoredStmts(),
+ getStoredStmts() + SubStmt::FirstParamMove + NumParams);
}
static bool classof(const Stmt *T) {
@@ -390,10 +427,14 @@ class CoreturnStmt : public Stmt {
enum SubStmt { Operand, PromiseCall, Count };
Stmt *SubStmts[SubStmt::Count];
+ bool IsImplicit : 1;
+
friend class ASTStmtReader;
public:
- CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
- : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
+ CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall,
+ bool IsImplicit = false)
+ : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc),
+ IsImplicit(IsImplicit) {
SubStmts[SubStmt::Operand] = Operand;
SubStmts[SubStmt::PromiseCall] = PromiseCall;
}
@@ -411,6 +452,9 @@ public:
return static_cast<Expr*>(SubStmts[PromiseCall]);
}
+ bool isImplicit() const { return IsImplicit; }
+ void setIsImplicit(bool value = true) { IsImplicit = value; }
+
SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return getOperand() ? getOperand()->getLocEnd() : getLocStart();