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); ObjCForCollectionStmt(EmptyShell Empty)31 explicit ObjCForCollectionStmt(EmptyShell Empty) : 32 Stmt(ObjCForCollectionStmtClass, Empty) { } 33 getElement()34 Stmt *getElement() { return SubExprs[ELEM]; } getCollection()35 Expr *getCollection() { 36 return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); 37 } getBody()38 Stmt *getBody() { return SubExprs[BODY]; } 39 getElement()40 const Stmt *getElement() const { return SubExprs[ELEM]; } getCollection()41 const Expr *getCollection() const { 42 return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); 43 } getBody()44 const Stmt *getBody() const { return SubExprs[BODY]; } 45 setElement(Stmt * S)46 void setElement(Stmt *S) { SubExprs[ELEM] = S; } setCollection(Expr * E)47 void setCollection(Expr *E) { 48 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E); 49 } setBody(Stmt * S)50 void setBody(Stmt *S) { SubExprs[BODY] = S; } 51 getForLoc()52 SourceLocation getForLoc() const { return ForLoc; } setForLoc(SourceLocation Loc)53 void setForLoc(SourceLocation Loc) { ForLoc = Loc; } getRParenLoc()54 SourceLocation getRParenLoc() const { return RParenLoc; } setRParenLoc(SourceLocation Loc)55 void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } 56 getBeginLoc()57 SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; } getEndLoc()58 SourceLocation getEndLoc() const LLVM_READONLY { 59 return SubExprs[BODY]->getEndLoc(); 60 } 61 classof(const Stmt * T)62 static bool classof(const Stmt *T) { 63 return T->getStmtClass() == ObjCForCollectionStmtClass; 64 } 65 66 // Iterators children()67 child_range children() { 68 return child_range(&SubExprs[0], &SubExprs[END_EXPR]); 69 } 70 children()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: ObjCAtCatchStmt(SourceLocation atCatchLoc,SourceLocation rparenloc,VarDecl * catchVarDecl,Stmt * atCatchStmt)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 ObjCAtCatchStmt(EmptyShell Empty)90 explicit ObjCAtCatchStmt(EmptyShell Empty) : 91 Stmt(ObjCAtCatchStmtClass, Empty) { } 92 getCatchBody()93 const Stmt *getCatchBody() const { return Body; } getCatchBody()94 Stmt *getCatchBody() { return Body; } setCatchBody(Stmt * S)95 void setCatchBody(Stmt *S) { Body = S; } 96 getCatchParamDecl()97 const VarDecl *getCatchParamDecl() const { 98 return ExceptionDecl; 99 } getCatchParamDecl()100 VarDecl *getCatchParamDecl() { 101 return ExceptionDecl; 102 } setCatchParamDecl(VarDecl * D)103 void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } 104 getAtCatchLoc()105 SourceLocation getAtCatchLoc() const { return AtCatchLoc; } setAtCatchLoc(SourceLocation Loc)106 void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } getRParenLoc()107 SourceLocation getRParenLoc() const { return RParenLoc; } setRParenLoc(SourceLocation Loc)108 void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } 109 getBeginLoc()110 SourceLocation getBeginLoc() const LLVM_READONLY { return AtCatchLoc; } getEndLoc()111 SourceLocation getEndLoc() const LLVM_READONLY { return Body->getEndLoc(); } 112 hasEllipsis()113 bool hasEllipsis() const { return getCatchParamDecl() == nullptr; } 114 classof(const Stmt * T)115 static bool classof(const Stmt *T) { 116 return T->getStmtClass() == ObjCAtCatchStmtClass; 117 } 118 children()119 child_range children() { return child_range(&Body, &Body + 1); } 120 children()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: ObjCAtFinallyStmt(SourceLocation atFinallyLoc,Stmt * atFinallyStmt)132 ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) 133 : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc), 134 AtFinallyStmt(atFinallyStmt) {} 135 ObjCAtFinallyStmt(EmptyShell Empty)136 explicit ObjCAtFinallyStmt(EmptyShell Empty) : 137 Stmt(ObjCAtFinallyStmtClass, Empty) { } 138 getFinallyBody()139 const Stmt *getFinallyBody() const { return AtFinallyStmt; } getFinallyBody()140 Stmt *getFinallyBody() { return AtFinallyStmt; } setFinallyBody(Stmt * S)141 void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } 142 getBeginLoc()143 SourceLocation getBeginLoc() const LLVM_READONLY { return AtFinallyLoc; } getEndLoc()144 SourceLocation getEndLoc() const LLVM_READONLY { 145 return AtFinallyStmt->getEndLoc(); 146 } 147 getAtFinallyLoc()148 SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } setAtFinallyLoc(SourceLocation Loc)149 void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; } 150 classof(const Stmt * T)151 static bool classof(const Stmt *T) { 152 return T->getStmtClass() == ObjCAtFinallyStmtClass; 153 } 154 children()155 child_range children() { 156 return child_range(&AtFinallyStmt, &AtFinallyStmt+1); 157 } 158 children()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). getStmts()181 Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } getStmts()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 ObjCAtTryStmt(EmptyShell Empty,unsigned NumCatchStmts,bool HasFinally)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. getAtTryLoc()204 SourceLocation getAtTryLoc() const { return AtTryLoc; } setAtTryLoc(SourceLocation Loc)205 void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } 206 207 /// Retrieve the \@try body. getTryBody()208 const Stmt *getTryBody() const { return getStmts()[0]; } getTryBody()209 Stmt *getTryBody() { return getStmts()[0]; } setTryBody(Stmt * S)210 void setTryBody(Stmt *S) { getStmts()[0] = S; } 211 212 /// Retrieve the number of \@catch statements in this try-catch-finally 213 /// block. getNumCatchStmts()214 unsigned getNumCatchStmts() const { return NumCatchStmts; } 215 216 /// Retrieve a \@catch statement. getCatchStmt(unsigned I)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. getCatchStmt(unsigned I)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. setCatchStmt(unsigned I,ObjCAtCatchStmt * S)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. getFinallyStmt()235 const ObjCAtFinallyStmt *getFinallyStmt() const { 236 if (!HasFinally) 237 return nullptr; 238 239 return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); 240 } getFinallyStmt()241 ObjCAtFinallyStmt *getFinallyStmt() { 242 if (!HasFinally) 243 return nullptr; 244 245 return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); 246 } setFinallyStmt(Stmt * S)247 void setFinallyStmt(Stmt *S) { 248 assert(HasFinally && "@try does not have a @finally slot!"); 249 getStmts()[1 + NumCatchStmts] = S; 250 } 251 getBeginLoc()252 SourceLocation getBeginLoc() const LLVM_READONLY { return AtTryLoc; } 253 SourceLocation getEndLoc() const LLVM_READONLY; 254 classof(const Stmt * T)255 static bool classof(const Stmt *T) { 256 return T->getStmtClass() == ObjCAtTryStmtClass; 257 } 258 children()259 child_range children() { 260 return child_range(getStmts(), 261 getStmts() + 1 + NumCatchStmts + HasFinally); 262 } 263 children()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: ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc,Stmt * synchExpr,Stmt * synchBody)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 } ObjCAtSynchronizedStmt(EmptyShell Empty)291 explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : 292 Stmt(ObjCAtSynchronizedStmtClass, Empty) { } 293 getAtSynchronizedLoc()294 SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; } setAtSynchronizedLoc(SourceLocation Loc)295 void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; } 296 getSynchBody()297 const CompoundStmt *getSynchBody() const { 298 return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); 299 } getSynchBody()300 CompoundStmt *getSynchBody() { 301 return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); 302 } setSynchBody(Stmt * S)303 void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } 304 getSynchExpr()305 const Expr *getSynchExpr() const { 306 return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); 307 } getSynchExpr()308 Expr *getSynchExpr() { 309 return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); 310 } setSynchExpr(Stmt * S)311 void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } 312 getBeginLoc()313 SourceLocation getBeginLoc() const LLVM_READONLY { return AtSynchronizedLoc; } getEndLoc()314 SourceLocation getEndLoc() const LLVM_READONLY { 315 return getSynchBody()->getEndLoc(); 316 } 317 classof(const Stmt * T)318 static bool classof(const Stmt *T) { 319 return T->getStmtClass() == ObjCAtSynchronizedStmtClass; 320 } 321 children()322 child_range children() { 323 return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR); 324 } 325 children()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: ObjCAtThrowStmt(SourceLocation atThrowLoc,Stmt * throwExpr)337 ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr) 338 : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { 339 AtThrowLoc = atThrowLoc; 340 } ObjCAtThrowStmt(EmptyShell Empty)341 explicit ObjCAtThrowStmt(EmptyShell Empty) : 342 Stmt(ObjCAtThrowStmtClass, Empty) { } 343 getThrowExpr()344 const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); } getThrowExpr()345 Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); } setThrowExpr(Stmt * S)346 void setThrowExpr(Stmt *S) { Throw = S; } 347 getThrowLoc()348 SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; } setThrowLoc(SourceLocation Loc)349 void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } 350 getBeginLoc()351 SourceLocation getBeginLoc() const LLVM_READONLY { return AtThrowLoc; } getEndLoc()352 SourceLocation getEndLoc() const LLVM_READONLY { 353 return Throw ? Throw->getEndLoc() : AtThrowLoc; 354 } 355 classof(const Stmt * T)356 static bool classof(const Stmt *T) { 357 return T->getStmtClass() == ObjCAtThrowStmtClass; 358 } 359 children()360 child_range children() { return child_range(&Throw, &Throw+1); } 361 children()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: ObjCAutoreleasePoolStmt(SourceLocation atLoc,Stmt * subStmt)373 ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt) 374 : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {} 375 ObjCAutoreleasePoolStmt(EmptyShell Empty)376 explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) : 377 Stmt(ObjCAutoreleasePoolStmtClass, Empty) { } 378 getSubStmt()379 const Stmt *getSubStmt() const { return SubStmt; } getSubStmt()380 Stmt *getSubStmt() { return SubStmt; } setSubStmt(Stmt * S)381 void setSubStmt(Stmt *S) { SubStmt = S; } 382 getBeginLoc()383 SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } getEndLoc()384 SourceLocation getEndLoc() const LLVM_READONLY { 385 return SubStmt->getEndLoc(); 386 } 387 getAtLoc()388 SourceLocation getAtLoc() const { return AtLoc; } setAtLoc(SourceLocation Loc)389 void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } 390 classof(const Stmt * T)391 static bool classof(const Stmt *T) { 392 return T->getStmtClass() == ObjCAutoreleasePoolStmtClass; 393 } 394 children()395 child_range children() { return child_range(&SubStmt, &SubStmt + 1); } 396 children()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