aboutsummaryrefslogtreecommitdiff
path: root/include/clang/AST/StmtObjC.h
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-23 22:50:49 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-23 22:50:49 +0000
commit8f5e3dd32e443768d9dbbad7191e123e6733750c (patch)
tree91499ffda788228d2b75b1780257b5e7fce81f4c /include/clang/AST/StmtObjC.h
parentec951e0c2fc0db00c36bc60c900331dde32c1b43 (diff)
downloadclang-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.h127
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;
}