Home | History | Annotate | Download | only in AST
      1 //===--- StmtObjC.h - Classes for representing ObjC statements --*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines the Objective-C statement AST node classes.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_AST_STMTOBJC_H
     15 #define LLVM_CLANG_AST_STMTOBJC_H
     16 
     17 #include "clang/AST/Stmt.h"
     18 #include "llvm/Support/Compiler.h"
     19 
     20 namespace clang {
     21 
     22 /// ObjCForCollectionStmt - This represents Objective-c's collection statement;
     23 /// represented as 'for (element 'in' collection-expression)' stmt.
     24 ///
     25 class ObjCForCollectionStmt : public Stmt {
     26   enum { ELEM, COLLECTION, BODY, END_EXPR };
     27   Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
     28   SourceLocation ForLoc;
     29   SourceLocation RParenLoc;
     30 public:
     31   ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
     32                         SourceLocation FCL, SourceLocation RPL);
     33   explicit ObjCForCollectionStmt(EmptyShell Empty) :
     34     Stmt(ObjCForCollectionStmtClass, Empty) { }
     35 
     36   Stmt *getElement() { return SubExprs[ELEM]; }
     37   Expr *getCollection() {
     38     return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
     39   }
     40   Stmt *getBody() { return SubExprs[BODY]; }
     41 
     42   const Stmt *getElement() const { return SubExprs[ELEM]; }
     43   const Expr *getCollection() const {
     44     return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
     45   }
     46   const Stmt *getBody() const { return SubExprs[BODY]; }
     47 
     48   void setElement(Stmt *S) { SubExprs[ELEM] = S; }
     49   void setCollection(Expr *E) {
     50     SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E);
     51   }
     52   void setBody(Stmt *S) { SubExprs[BODY] = S; }
     53 
     54   SourceLocation getForLoc() const { return ForLoc; }
     55   void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
     56   SourceLocation getRParenLoc() const { return RParenLoc; }
     57   void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
     58 
     59   SourceRange getSourceRange() const LLVM_READONLY {
     60     return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
     61   }
     62   static bool classof(const Stmt *T) {
     63     return T->getStmtClass() == ObjCForCollectionStmtClass;
     64   }
     65   static bool classof(const ObjCForCollectionStmt *) { return true; }
     66 
     67   // Iterators
     68   child_range children() {
     69     return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
     70   }
     71 };
     72 
     73 /// ObjCAtCatchStmt - This represents objective-c's @catch statement.
     74 class ObjCAtCatchStmt : public Stmt {
     75 private:
     76   VarDecl *ExceptionDecl;
     77   Stmt *Body;
     78   SourceLocation AtCatchLoc, RParenLoc;
     79 
     80 public:
     81   ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
     82                   VarDecl *catchVarDecl,
     83                   Stmt *atCatchStmt)
     84     : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl),
     85     Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { }
     86 
     87   explicit ObjCAtCatchStmt(EmptyShell Empty) :
     88     Stmt(ObjCAtCatchStmtClass, Empty) { }
     89 
     90   const Stmt *getCatchBody() const { return Body; }
     91   Stmt *getCatchBody() { return Body; }
     92   void setCatchBody(Stmt *S) { Body = S; }
     93 
     94   const VarDecl *getCatchParamDecl() const {
     95     return ExceptionDecl;
     96   }
     97   VarDecl *getCatchParamDecl() {
     98     return ExceptionDecl;
     99   }
    100   void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; }
    101 
    102   SourceLocation getAtCatchLoc() const { return AtCatchLoc; }
    103   void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; }
    104   SourceLocation getRParenLoc() const { return RParenLoc; }
    105   void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
    106 
    107   SourceRange getSourceRange() const LLVM_READONLY {
    108     return SourceRange(AtCatchLoc, Body->getLocEnd());
    109   }
    110 
    111   bool hasEllipsis() const { return getCatchParamDecl() == 0; }
    112 
    113   static bool classof(const Stmt *T) {
    114     return T->getStmtClass() == ObjCAtCatchStmtClass;
    115   }
    116   static bool classof(const ObjCAtCatchStmt *) { return true; }
    117 
    118   child_range children() { return child_range(&Body, &Body + 1); }
    119 };
    120 
    121 /// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
    122 class ObjCAtFinallyStmt : public Stmt {
    123   Stmt *AtFinallyStmt;
    124   SourceLocation AtFinallyLoc;
    125 public:
    126   ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
    127   : Stmt(ObjCAtFinallyStmtClass),
    128     AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
    129 
    130   explicit ObjCAtFinallyStmt(EmptyShell Empty) :
    131     Stmt(ObjCAtFinallyStmtClass, Empty) { }
    132 
    133   const Stmt *getFinallyBody() const { return AtFinallyStmt; }
    134   Stmt *getFinallyBody() { return AtFinallyStmt; }
    135   void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
    136 
    137   SourceRange getSourceRange() const LLVM_READONLY {
    138     return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
    139   }
    140 
    141   SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
    142   void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; }
    143 
    144   static bool classof(const Stmt *T) {
    145     return T->getStmtClass() == ObjCAtFinallyStmtClass;
    146   }
    147   static bool classof(const ObjCAtFinallyStmt *) { return true; }
    148 
    149   child_range children() {
    150     return child_range(&AtFinallyStmt, &AtFinallyStmt+1);
    151   }
    152 };
    153 
    154 /// ObjCAtTryStmt - This represent objective-c's over-all
    155 /// @try ... @catch ... @finally statement.
    156 class ObjCAtTryStmt : public Stmt {
    157 private:
    158   // The location of the
    159   SourceLocation AtTryLoc;
    160 
    161   // The number of catch blocks in this statement.
    162   unsigned NumCatchStmts : 16;
    163 
    164   // Whether this statement has a @finally statement.
    165   bool HasFinally : 1;
    166 
    167   /// \brief Retrieve the statements that are stored after this @try statement.
    168   ///
    169   /// The order of the statements in memory follows the order in the source,
    170   /// with the @try body first, followed by the @catch statements (if any) and,
    171   /// finally, the @finally (if it exists).
    172   Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); }
    173   const Stmt* const *getStmts() const {
    174     return reinterpret_cast<const Stmt * const*> (this + 1);
    175   }
    176 
    177   ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
    178                 Stmt **CatchStmts, unsigned NumCatchStmts,
    179                 Stmt *atFinallyStmt);
    180 
    181   explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts,
    182                          bool HasFinally)
    183     : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts),
    184       HasFinally(HasFinally) { }
    185 
    186 public:
    187   static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc,
    188                                Stmt *atTryStmt,
    189                                Stmt **CatchStmts, unsigned NumCatchStmts,
    190                                Stmt *atFinallyStmt);
    191   static ObjCAtTryStmt *CreateEmpty(ASTContext &Context,
    192                                     unsigned NumCatchStmts,
    193                                     bool HasFinally);
    194 
    195   /// \brief Retrieve the location of the @ in the @try.
    196   SourceLocation getAtTryLoc() const { return AtTryLoc; }
    197   void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
    198 
    199   /// \brief Retrieve the @try body.
    200   const Stmt *getTryBody() const { return getStmts()[0]; }
    201   Stmt *getTryBody() { return getStmts()[0]; }
    202   void setTryBody(Stmt *S) { getStmts()[0] = S; }
    203 
    204   /// \brief Retrieve the number of @catch statements in this try-catch-finally
    205   /// block.
    206   unsigned getNumCatchStmts() const { return NumCatchStmts; }
    207 
    208   /// \brief Retrieve a @catch statement.
    209   const ObjCAtCatchStmt *getCatchStmt(unsigned I) const {
    210     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
    211     return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
    212   }
    213 
    214   /// \brief Retrieve a @catch statement.
    215   ObjCAtCatchStmt *getCatchStmt(unsigned I) {
    216     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
    217     return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
    218   }
    219 
    220   /// \brief Set a particular catch statement.
    221   void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) {
    222     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
    223     getStmts()[I + 1] = S;
    224   }
    225 
    226   /// Retrieve the @finally statement, if any.
    227   const ObjCAtFinallyStmt *getFinallyStmt() const {
    228     if (!HasFinally)
    229       return 0;
    230 
    231     return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
    232   }
    233   ObjCAtFinallyStmt *getFinallyStmt() {
    234     if (!HasFinally)
    235       return 0;
    236 
    237     return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
    238   }
    239   void setFinallyStmt(Stmt *S) {
    240     assert(HasFinally && "@try does not have a @finally slot!");
    241     getStmts()[1 + NumCatchStmts] = S;
    242   }
    243 
    244   SourceRange getSourceRange() const LLVM_READONLY;
    245 
    246   static bool classof(const Stmt *T) {
    247     return T->getStmtClass() == ObjCAtTryStmtClass;
    248   }
    249   static bool classof(const ObjCAtTryStmt *) { return true; }
    250 
    251   child_range children() {
    252     return child_range(getStmts(),
    253                        getStmts() + 1 + NumCatchStmts + HasFinally);
    254   }
    255 };
    256 
    257 /// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement.
    258 /// Example: @synchronized (sem) {
    259 ///             do-something;
    260 ///          }
    261 ///
    262 class ObjCAtSynchronizedStmt : public Stmt {
    263 private:
    264   enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
    265   Stmt* SubStmts[END_EXPR];
    266   SourceLocation AtSynchronizedLoc;
    267 
    268 public:
    269   ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
    270                          Stmt *synchBody)
    271   : Stmt(ObjCAtSynchronizedStmtClass) {
    272     SubStmts[SYNC_EXPR] = synchExpr;
    273     SubStmts[SYNC_BODY] = synchBody;
    274     AtSynchronizedLoc = atSynchronizedLoc;
    275   }
    276   explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
    277     Stmt(ObjCAtSynchronizedStmtClass, Empty) { }
    278 
    279   SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; }
    280   void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; }
    281 
    282   const CompoundStmt *getSynchBody() const {
    283     return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
    284   }
    285   CompoundStmt *getSynchBody() {
    286     return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
    287   }
    288   void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; }
    289 
    290   const Expr *getSynchExpr() const {
    291     return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
    292   }
    293   Expr *getSynchExpr() {
    294     return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
    295   }
    296   void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
    297 
    298   SourceRange getSourceRange() const LLVM_READONLY {
    299     return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
    300   }
    301 
    302   static bool classof(const Stmt *T) {
    303     return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
    304   }
    305   static bool classof(const ObjCAtSynchronizedStmt *) { return true; }
    306 
    307   child_range children() {
    308     return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
    309   }
    310 };
    311 
    312 /// ObjCAtThrowStmt - This represents objective-c's @throw statement.
    313 class ObjCAtThrowStmt : public Stmt {
    314   Stmt *Throw;
    315   SourceLocation AtThrowLoc;
    316 public:
    317   ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
    318   : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
    319     AtThrowLoc = atThrowLoc;
    320   }
    321   explicit ObjCAtThrowStmt(EmptyShell Empty) :
    322     Stmt(ObjCAtThrowStmtClass, Empty) { }
    323 
    324   const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); }
    325   Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
    326   void setThrowExpr(Stmt *S) { Throw = S; }
    327 
    328   SourceLocation getThrowLoc() { return AtThrowLoc; }
    329   void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
    330 
    331   SourceRange getSourceRange() const LLVM_READONLY {
    332     if (Throw)
    333       return SourceRange(AtThrowLoc, Throw->getLocEnd());
    334     else
    335       return SourceRange(AtThrowLoc);
    336   }
    337 
    338   static bool classof(const Stmt *T) {
    339     return T->getStmtClass() == ObjCAtThrowStmtClass;
    340   }
    341   static bool classof(const ObjCAtThrowStmt *) { return true; }
    342 
    343   child_range children() { return child_range(&Throw, &Throw+1); }
    344 };
    345 
    346 /// ObjCAutoreleasePoolStmt - This represent objective-c's
    347 /// @autoreleasepool Statement
    348 class ObjCAutoreleasePoolStmt : public Stmt {
    349   Stmt *SubStmt;
    350   SourceLocation AtLoc;
    351 public:
    352   ObjCAutoreleasePoolStmt(SourceLocation atLoc,
    353                             Stmt *subStmt)
    354   : Stmt(ObjCAutoreleasePoolStmtClass),
    355     SubStmt(subStmt), AtLoc(atLoc) {}
    356 
    357   explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
    358     Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
    359 
    360   const Stmt *getSubStmt() const { return SubStmt; }
    361   Stmt *getSubStmt() { return SubStmt; }
    362   void setSubStmt(Stmt *S) { SubStmt = S; }
    363 
    364   SourceRange getSourceRange() const LLVM_READONLY {
    365     return SourceRange(AtLoc, SubStmt->getLocEnd());
    366   }
    367 
    368   SourceLocation getAtLoc() const { return AtLoc; }
    369   void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
    370 
    371   static bool classof(const Stmt *T) {
    372     return T->getStmtClass() == ObjCAutoreleasePoolStmtClass;
    373   }
    374   static bool classof(const ObjCAutoreleasePoolStmt *) { return true; }
    375 
    376   child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
    377 };
    378 
    379 }  // end namespace clang
    380 
    381 #endif
    382