| //===--- StmtObjC.h - Classes for representing ObjC statements --*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| /// \file |
| /// \brief Defines the Objective-C statement AST node classes. |
| |
| #ifndef LLVM_CLANG_AST_STMTOBJC_H |
| #define LLVM_CLANG_AST_STMTOBJC_H |
| |
| #include "clang/AST/Stmt.h" |
| #include "llvm/Support/Compiler.h" |
| |
| namespace clang { |
| |
| /// \brief Represents Objective-C's collection statement. |
| /// |
| /// This is represented as 'for (element 'in' collection-expression)' stmt. |
| class ObjCForCollectionStmt : public Stmt { |
| enum { ELEM, COLLECTION, BODY, END_EXPR }; |
| Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt. |
| SourceLocation ForLoc; |
| SourceLocation RParenLoc; |
| public: |
| ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, |
| SourceLocation FCL, SourceLocation RPL); |
| explicit ObjCForCollectionStmt(EmptyShell Empty) : |
| Stmt(ObjCForCollectionStmtClass, Empty) { } |
| |
| Stmt *getElement() { return SubExprs[ELEM]; } |
| Expr *getCollection() { |
| return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); |
| } |
| Stmt *getBody() { return SubExprs[BODY]; } |
| |
| const Stmt *getElement() const { return SubExprs[ELEM]; } |
| const Expr *getCollection() const { |
| return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); |
| } |
| const Stmt *getBody() const { return SubExprs[BODY]; } |
| |
| void setElement(Stmt *S) { SubExprs[ELEM] = S; } |
| void setCollection(Expr *E) { |
| SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E); |
| } |
| void setBody(Stmt *S) { SubExprs[BODY] = S; } |
| |
| SourceLocation getForLoc() const { return ForLoc; } |
| void setForLoc(SourceLocation Loc) { ForLoc = Loc; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return SubExprs[BODY]->getLocEnd(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCForCollectionStmtClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&SubExprs[0], &SubExprs[END_EXPR]); |
| } |
| }; |
| |
| /// \brief Represents Objective-C's \@catch statement. |
| class ObjCAtCatchStmt : public Stmt { |
| private: |
| VarDecl *ExceptionDecl; |
| Stmt *Body; |
| SourceLocation AtCatchLoc, RParenLoc; |
| |
| public: |
| ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, |
| VarDecl *catchVarDecl, |
| Stmt *atCatchStmt) |
| : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl), |
| Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { } |
| |
| explicit ObjCAtCatchStmt(EmptyShell Empty) : |
| Stmt(ObjCAtCatchStmtClass, Empty) { } |
| |
| const Stmt *getCatchBody() const { return Body; } |
| Stmt *getCatchBody() { return Body; } |
| void setCatchBody(Stmt *S) { Body = S; } |
| |
| const VarDecl *getCatchParamDecl() const { |
| return ExceptionDecl; |
| } |
| VarDecl *getCatchParamDecl() { |
| return ExceptionDecl; |
| } |
| void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } |
| |
| SourceLocation getAtCatchLoc() const { return AtCatchLoc; } |
| void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); } |
| |
| bool hasEllipsis() const { return getCatchParamDecl() == nullptr; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCAtCatchStmtClass; |
| } |
| |
| child_range children() { return child_range(&Body, &Body + 1); } |
| }; |
| |
| /// \brief Represents Objective-C's \@finally statement |
| class ObjCAtFinallyStmt : public Stmt { |
| SourceLocation AtFinallyLoc; |
| Stmt *AtFinallyStmt; |
| |
| public: |
| ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) |
| : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc), |
| AtFinallyStmt(atFinallyStmt) {} |
| |
| explicit ObjCAtFinallyStmt(EmptyShell Empty) : |
| Stmt(ObjCAtFinallyStmtClass, Empty) { } |
| |
| const Stmt *getFinallyBody() const { return AtFinallyStmt; } |
| Stmt *getFinallyBody() { return AtFinallyStmt; } |
| void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return AtFinallyLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return AtFinallyStmt->getLocEnd(); |
| } |
| |
| SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } |
| void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCAtFinallyStmtClass; |
| } |
| |
| child_range children() { |
| return child_range(&AtFinallyStmt, &AtFinallyStmt+1); |
| } |
| }; |
| |
| /// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement. |
| class ObjCAtTryStmt : public Stmt { |
| private: |
| // The location of the @ in the \@try. |
| SourceLocation AtTryLoc; |
| |
| // 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 **CatchStmts, unsigned NumCatchStmts, |
| Stmt *atFinallyStmt); |
| |
| explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts, |
| bool HasFinally) |
| : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts), |
| HasFinally(HasFinally) { } |
| |
| public: |
| static ObjCAtTryStmt *Create(const ASTContext &Context, |
| SourceLocation atTryLoc, Stmt *atTryStmt, |
| Stmt **CatchStmts, unsigned NumCatchStmts, |
| Stmt *atFinallyStmt); |
| static ObjCAtTryStmt *CreateEmpty(const 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; } |
| |
| /// \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]); |
| } |
| |
| /// \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]); |
| } |
| |
| /// \brief Set a particular catch statement. |
| void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { |
| assert(I < NumCatchStmts && "Out-of-bounds @catch index"); |
| getStmts()[I + 1] = S; |
| } |
| |
| /// \brief Retrieve the \@finally statement, if any. |
| const ObjCAtFinallyStmt *getFinallyStmt() const { |
| if (!HasFinally) |
| return nullptr; |
| |
| return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); |
| } |
| ObjCAtFinallyStmt *getFinallyStmt() { |
| if (!HasFinally) |
| return nullptr; |
| |
| return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); |
| } |
| void setFinallyStmt(Stmt *S) { |
| assert(HasFinally && "@try does not have a @finally slot!"); |
| getStmts()[1 + NumCatchStmts] = S; |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCAtTryStmtClass; |
| } |
| |
| child_range children() { |
| return child_range(getStmts(), |
| getStmts() + 1 + NumCatchStmts + HasFinally); |
| } |
| }; |
| |
| /// \brief Represents Objective-C's \@synchronized statement. |
| /// |
| /// Example: |
| /// \code |
| /// @synchronized (sem) { |
| /// do-something; |
| /// } |
| /// \endcode |
| class ObjCAtSynchronizedStmt : public Stmt { |
| private: |
| SourceLocation AtSynchronizedLoc; |
| enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; |
| Stmt* SubStmts[END_EXPR]; |
| |
| public: |
| ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr, |
| Stmt *synchBody) |
| : Stmt(ObjCAtSynchronizedStmtClass) { |
| SubStmts[SYNC_EXPR] = synchExpr; |
| SubStmts[SYNC_BODY] = synchBody; |
| AtSynchronizedLoc = atSynchronizedLoc; |
| } |
| explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : |
| Stmt(ObjCAtSynchronizedStmtClass, Empty) { } |
| |
| SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; } |
| void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; } |
| |
| const CompoundStmt *getSynchBody() const { |
| return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); |
| } |
| CompoundStmt *getSynchBody() { |
| return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); |
| } |
| void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } |
| |
| const Expr *getSynchExpr() const { |
| return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); |
| } |
| Expr *getSynchExpr() { |
| return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); |
| } |
| void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return AtSynchronizedLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return getSynchBody()->getLocEnd(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCAtSynchronizedStmtClass; |
| } |
| |
| child_range children() { |
| return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR); |
| } |
| }; |
| |
| /// \brief Represents Objective-C's \@throw statement. |
| class ObjCAtThrowStmt : public Stmt { |
| SourceLocation AtThrowLoc; |
| Stmt *Throw; |
| |
| public: |
| ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr) |
| : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { |
| AtThrowLoc = atThrowLoc; |
| } |
| explicit ObjCAtThrowStmt(EmptyShell Empty) : |
| Stmt(ObjCAtThrowStmtClass, Empty) { } |
| |
| const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); } |
| Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); } |
| void setThrowExpr(Stmt *S) { Throw = S; } |
| |
| SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; } |
| void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return Throw ? Throw->getLocEnd() : AtThrowLoc; |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCAtThrowStmtClass; |
| } |
| |
| child_range children() { return child_range(&Throw, &Throw+1); } |
| }; |
| |
| /// \brief Represents Objective-C's \@autoreleasepool Statement |
| class ObjCAutoreleasePoolStmt : public Stmt { |
| SourceLocation AtLoc; |
| Stmt *SubStmt; |
| |
| public: |
| ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt) |
| : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {} |
| |
| explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) : |
| Stmt(ObjCAutoreleasePoolStmtClass, Empty) { } |
| |
| const Stmt *getSubStmt() const { return SubStmt; } |
| Stmt *getSubStmt() { return SubStmt; } |
| void setSubStmt(Stmt *S) { SubStmt = S; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} |
| |
| SourceLocation getAtLoc() const { return AtLoc; } |
| void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ObjCAutoreleasePoolStmtClass; |
| } |
| |
| child_range children() { return child_range(&SubStmt, &SubStmt + 1); } |
| }; |
| |
| } // end namespace clang |
| |
| #endif |