diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-23 22:50:49 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-23 22:50:49 +0000 |
commit | 8f5e3dd32e443768d9dbbad7191e123e6733750c (patch) | |
tree | 91499ffda788228d2b75b1780257b5e7fce81f4c /include/clang/AST/StmtObjC.h | |
parent | ec951e0c2fc0db00c36bc60c900331dde32c1b43 (diff) | |
download | clang-8f5e3dd32e443768d9dbbad7191e123e6733750c.tar.gz |
Improve the AST representation of Objective-C @try/@catch/@finally
statements. Instead of the @try having a single @catch, where all of
the @catch's were chained (using an O(n^2) algorithm nonetheless),
@try just holds an array of its @catch blocks. The resulting AST is
slightly more compact (not important) and better represents the actual
language semantics (good).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102221 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/AST/StmtObjC.h')
-rw-r--r-- | include/clang/AST/StmtObjC.h | 127 |
1 files changed, 82 insertions, 45 deletions
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 3fd8f1672d..6cb2b1f18a 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -71,30 +71,23 @@ public: /// ObjCAtCatchStmt - This represents objective-c's @catch statement. class ObjCAtCatchStmt : public Stmt { private: - enum { BODY, NEXT_CATCH, END_EXPR }; ParmVarDecl *ExceptionDecl; - Stmt *SubExprs[END_EXPR]; + Stmt *Body; SourceLocation AtCatchLoc, RParenLoc; public: ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, ParmVarDecl *catchVarDecl, - Stmt *atCatchStmt, Stmt *atCatchList); + Stmt *atCatchStmt) + : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl), + Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { } explicit ObjCAtCatchStmt(EmptyShell Empty) : Stmt(ObjCAtCatchStmtClass, Empty) { } - const Stmt *getCatchBody() const { return SubExprs[BODY]; } - Stmt *getCatchBody() { return SubExprs[BODY]; } - void setCatchBody(Stmt *S) { SubExprs[BODY] = S; } - - const ObjCAtCatchStmt *getNextCatchStmt() const { - return static_cast<const ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); - } - ObjCAtCatchStmt *getNextCatchStmt() { - return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); - } - void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; } + const Stmt *getCatchBody() const { return Body; } + Stmt *getCatchBody() { return Body; } + void setCatchBody(Stmt *S) { Body = S; } const ParmVarDecl *getCatchParamDecl() const { return ExceptionDecl; @@ -110,7 +103,7 @@ public: void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } virtual SourceRange getSourceRange() const { - return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd()); + return SourceRange(AtCatchLoc, Body->getLocEnd()); } bool hasEllipsis() const { return getCatchParamDecl() == 0; } @@ -160,50 +153,94 @@ public: /// @try ... @catch ... @finally statement. class ObjCAtTryStmt : public Stmt { private: - enum { TRY, CATCH, FINALLY, END_EXPR }; - Stmt* SubStmts[END_EXPR]; - + // The location of the SourceLocation AtTryLoc; -public: + + // The number of catch blocks in this statement. + unsigned NumCatchStmts : 16; + + // Whether this statement has a @finally statement. + bool HasFinally : 1; + + /// \brief Retrieve the statements that are stored after this @try statement. + /// + /// The order of the statements in memory follows the order in the source, + /// with the @try body first, followed by the @catch statements (if any) and, + /// finally, the @finally (if it exists). + Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } + const Stmt* const *getStmts() const { + return reinterpret_cast<const Stmt * const*> (this + 1); + } + ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt *atCatchStmt, - Stmt *atFinallyStmt) - : Stmt(ObjCAtTryStmtClass) { - SubStmts[TRY] = atTryStmt; - SubStmts[CATCH] = atCatchStmt; - SubStmts[FINALLY] = atFinallyStmt; - AtTryLoc = atTryLoc; - } - explicit ObjCAtTryStmt(EmptyShell Empty) : - Stmt(ObjCAtTryStmtClass, Empty) { } + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + + explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts, + bool HasFinally) + : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts), + HasFinally(HasFinally) { } +public: + static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc, + Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + static ObjCAtTryStmt *CreateEmpty(ASTContext &Context, + unsigned NumCatchStmts, + bool HasFinally); + + /// \brief Retrieve the location of the @ in the @try. SourceLocation getAtTryLoc() const { return AtTryLoc; } void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } - const Stmt *getTryBody() const { return SubStmts[TRY]; } - Stmt *getTryBody() { return SubStmts[TRY]; } - void setTryBody(Stmt *S) { SubStmts[TRY] = S; } - - const ObjCAtCatchStmt *getCatchStmts() const { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + /// \brief Retrieve the @try body. + const Stmt *getTryBody() const { return getStmts()[0]; } + Stmt *getTryBody() { return getStmts()[0]; } + void setTryBody(Stmt *S) { getStmts()[0] = S; } + + /// \brief Retrieve the number of @catch statements in this try-catch-finally + /// block. + unsigned getNumCatchStmts() const { return NumCatchStmts; } + + /// \brief Retrieve a @catch statement. + const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - ObjCAtCatchStmt *getCatchStmts() { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + + /// \brief Retrieve a @catch statement. + ObjCAtCatchStmt *getCatchStmt(unsigned I) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - void setCatchStmts(Stmt *S) { SubStmts[CATCH] = S; } - + + /// \brief Set a particular catch statement. + void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + getStmts()[I + 1] = S; + } + + /// Retrieve the @finally statement, if any. const ObjCAtFinallyStmt *getFinallyStmt() const { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } ObjCAtFinallyStmt *getFinallyStmt() { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } - void setFinallyStmt(Stmt *S) { SubStmts[FINALLY] = S; } - - virtual SourceRange getSourceRange() const { - return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd()); + void setFinallyStmt(Stmt *S) { + assert(HasFinally && "@try does not have a @finally slot!"); + getStmts()[1 + NumCatchStmts] = S; } + virtual SourceRange getSourceRange() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; } |