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