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