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