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); ObjCForCollectionStmt(EmptyShell Empty)33 explicit ObjCForCollectionStmt(EmptyShell Empty) : 34 Stmt(ObjCForCollectionStmtClass, Empty) { } 35 getElement()36 Stmt *getElement() { return SubExprs[ELEM]; } getCollection()37 Expr *getCollection() { 38 return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); 39 } getBody()40 Stmt *getBody() { return SubExprs[BODY]; } 41 getElement()42 const Stmt *getElement() const { return SubExprs[ELEM]; } getCollection()43 const Expr *getCollection() const { 44 return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); 45 } getBody()46 const Stmt *getBody() const { return SubExprs[BODY]; } 47 setElement(Stmt * S)48 void setElement(Stmt *S) { SubExprs[ELEM] = S; } setCollection(Expr * E)49 void setCollection(Expr *E) { 50 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E); 51 } setBody(Stmt * S)52 void setBody(Stmt *S) { SubExprs[BODY] = S; } 53 getForLoc()54 SourceLocation getForLoc() const { return ForLoc; } setForLoc(SourceLocation Loc)55 void setForLoc(SourceLocation Loc) { ForLoc = Loc; } getRParenLoc()56 SourceLocation getRParenLoc() const { return RParenLoc; } setRParenLoc(SourceLocation Loc)57 void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } 58 getSourceRange()59 SourceRange getSourceRange() const LLVM_READONLY { 60 return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); 61 } classof(const Stmt * T)62 static bool classof(const Stmt *T) { 63 return T->getStmtClass() == ObjCForCollectionStmtClass; 64 } classof(const ObjCForCollectionStmt *)65 static bool classof(const ObjCForCollectionStmt *) { return true; } 66 67 // Iterators children()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: ObjCAtCatchStmt(SourceLocation atCatchLoc,SourceLocation rparenloc,VarDecl * catchVarDecl,Stmt * atCatchStmt)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 ObjCAtCatchStmt(EmptyShell Empty)87 explicit ObjCAtCatchStmt(EmptyShell Empty) : 88 Stmt(ObjCAtCatchStmtClass, Empty) { } 89 getCatchBody()90 const Stmt *getCatchBody() const { return Body; } getCatchBody()91 Stmt *getCatchBody() { return Body; } setCatchBody(Stmt * S)92 void setCatchBody(Stmt *S) { Body = S; } 93 getCatchParamDecl()94 const VarDecl *getCatchParamDecl() const { 95 return ExceptionDecl; 96 } getCatchParamDecl()97 VarDecl *getCatchParamDecl() { 98 return ExceptionDecl; 99 } setCatchParamDecl(VarDecl * D)100 void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } 101 getAtCatchLoc()102 SourceLocation getAtCatchLoc() const { return AtCatchLoc; } setAtCatchLoc(SourceLocation Loc)103 void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } getRParenLoc()104 SourceLocation getRParenLoc() const { return RParenLoc; } setRParenLoc(SourceLocation Loc)105 void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } 106 getSourceRange()107 SourceRange getSourceRange() const LLVM_READONLY { 108 return SourceRange(AtCatchLoc, Body->getLocEnd()); 109 } 110 hasEllipsis()111 bool hasEllipsis() const { return getCatchParamDecl() == 0; } 112 classof(const Stmt * T)113 static bool classof(const Stmt *T) { 114 return T->getStmtClass() == ObjCAtCatchStmtClass; 115 } classof(const ObjCAtCatchStmt *)116 static bool classof(const ObjCAtCatchStmt *) { return true; } 117 children()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: ObjCAtFinallyStmt(SourceLocation atFinallyLoc,Stmt * atFinallyStmt)126 ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) 127 : Stmt(ObjCAtFinallyStmtClass), 128 AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {} 129 ObjCAtFinallyStmt(EmptyShell Empty)130 explicit ObjCAtFinallyStmt(EmptyShell Empty) : 131 Stmt(ObjCAtFinallyStmtClass, Empty) { } 132 getFinallyBody()133 const Stmt *getFinallyBody() const { return AtFinallyStmt; } getFinallyBody()134 Stmt *getFinallyBody() { return AtFinallyStmt; } setFinallyBody(Stmt * S)135 void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } 136 getSourceRange()137 SourceRange getSourceRange() const LLVM_READONLY { 138 return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); 139 } 140 getAtFinallyLoc()141 SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } setAtFinallyLoc(SourceLocation Loc)142 void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; } 143 classof(const Stmt * T)144 static bool classof(const Stmt *T) { 145 return T->getStmtClass() == ObjCAtFinallyStmtClass; 146 } classof(const ObjCAtFinallyStmt *)147 static bool classof(const ObjCAtFinallyStmt *) { return true; } 148 children()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). getStmts()172 Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } getStmts()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 ObjCAtTryStmt(EmptyShell Empty,unsigned NumCatchStmts,bool HasFinally)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. getAtTryLoc()196 SourceLocation getAtTryLoc() const { return AtTryLoc; } setAtTryLoc(SourceLocation Loc)197 void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } 198 199 /// \brief Retrieve the @try body. getTryBody()200 const Stmt *getTryBody() const { return getStmts()[0]; } getTryBody()201 Stmt *getTryBody() { return getStmts()[0]; } setTryBody(Stmt * S)202 void setTryBody(Stmt *S) { getStmts()[0] = S; } 203 204 /// \brief Retrieve the number of @catch statements in this try-catch-finally 205 /// block. getNumCatchStmts()206 unsigned getNumCatchStmts() const { return NumCatchStmts; } 207 208 /// \brief Retrieve a @catch statement. getCatchStmt(unsigned I)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. getCatchStmt(unsigned I)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. setCatchStmt(unsigned I,ObjCAtCatchStmt * S)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. getFinallyStmt()227 const ObjCAtFinallyStmt *getFinallyStmt() const { 228 if (!HasFinally) 229 return 0; 230 231 return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); 232 } getFinallyStmt()233 ObjCAtFinallyStmt *getFinallyStmt() { 234 if (!HasFinally) 235 return 0; 236 237 return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); 238 } setFinallyStmt(Stmt * S)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 classof(const Stmt * T)246 static bool classof(const Stmt *T) { 247 return T->getStmtClass() == ObjCAtTryStmtClass; 248 } classof(const ObjCAtTryStmt *)249 static bool classof(const ObjCAtTryStmt *) { return true; } 250 children()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: ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc,Stmt * synchExpr,Stmt * synchBody)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 } ObjCAtSynchronizedStmt(EmptyShell Empty)276 explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : 277 Stmt(ObjCAtSynchronizedStmtClass, Empty) { } 278 getAtSynchronizedLoc()279 SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; } setAtSynchronizedLoc(SourceLocation Loc)280 void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; } 281 getSynchBody()282 const CompoundStmt *getSynchBody() const { 283 return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); 284 } getSynchBody()285 CompoundStmt *getSynchBody() { 286 return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); 287 } setSynchBody(Stmt * S)288 void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } 289 getSynchExpr()290 const Expr *getSynchExpr() const { 291 return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); 292 } getSynchExpr()293 Expr *getSynchExpr() { 294 return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); 295 } setSynchExpr(Stmt * S)296 void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } 297 getSourceRange()298 SourceRange getSourceRange() const LLVM_READONLY { 299 return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); 300 } 301 classof(const Stmt * T)302 static bool classof(const Stmt *T) { 303 return T->getStmtClass() == ObjCAtSynchronizedStmtClass; 304 } classof(const ObjCAtSynchronizedStmt *)305 static bool classof(const ObjCAtSynchronizedStmt *) { return true; } 306 children()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: ObjCAtThrowStmt(SourceLocation atThrowLoc,Stmt * throwExpr)317 ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr) 318 : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { 319 AtThrowLoc = atThrowLoc; 320 } ObjCAtThrowStmt(EmptyShell Empty)321 explicit ObjCAtThrowStmt(EmptyShell Empty) : 322 Stmt(ObjCAtThrowStmtClass, Empty) { } 323 getThrowExpr()324 const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); } getThrowExpr()325 Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); } setThrowExpr(Stmt * S)326 void setThrowExpr(Stmt *S) { Throw = S; } 327 getThrowLoc()328 SourceLocation getThrowLoc() { return AtThrowLoc; } setThrowLoc(SourceLocation Loc)329 void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } 330 getSourceRange()331 SourceRange getSourceRange() const LLVM_READONLY { 332 if (Throw) 333 return SourceRange(AtThrowLoc, Throw->getLocEnd()); 334 else 335 return SourceRange(AtThrowLoc); 336 } 337 classof(const Stmt * T)338 static bool classof(const Stmt *T) { 339 return T->getStmtClass() == ObjCAtThrowStmtClass; 340 } classof(const ObjCAtThrowStmt *)341 static bool classof(const ObjCAtThrowStmt *) { return true; } 342 children()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: ObjCAutoreleasePoolStmt(SourceLocation atLoc,Stmt * subStmt)352 ObjCAutoreleasePoolStmt(SourceLocation atLoc, 353 Stmt *subStmt) 354 : Stmt(ObjCAutoreleasePoolStmtClass), 355 SubStmt(subStmt), AtLoc(atLoc) {} 356 ObjCAutoreleasePoolStmt(EmptyShell Empty)357 explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) : 358 Stmt(ObjCAutoreleasePoolStmtClass, Empty) { } 359 getSubStmt()360 const Stmt *getSubStmt() const { return SubStmt; } getSubStmt()361 Stmt *getSubStmt() { return SubStmt; } setSubStmt(Stmt * S)362 void setSubStmt(Stmt *S) { SubStmt = S; } 363 getSourceRange()364 SourceRange getSourceRange() const LLVM_READONLY { 365 return SourceRange(AtLoc, SubStmt->getLocEnd()); 366 } 367 getAtLoc()368 SourceLocation getAtLoc() const { return AtLoc; } setAtLoc(SourceLocation Loc)369 void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } 370 classof(const Stmt * T)371 static bool classof(const Stmt *T) { 372 return T->getStmtClass() == ObjCAutoreleasePoolStmtClass; 373 } classof(const ObjCAutoreleasePoolStmt *)374 static bool classof(const ObjCAutoreleasePoolStmt *) { return true; } 375 children()376 child_range children() { return child_range(&SubStmt, &SubStmt + 1); } 377 }; 378 379 } // end namespace clang 380 381 #endif 382