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