xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/StmtObjC.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 final
166     : public Stmt,
167       private llvm::TrailingObjects<ObjCAtTryStmt, Stmt *> {
168   friend TrailingObjects;
numTrailingObjects(OverloadToken<Stmt * >)169   size_t numTrailingObjects(OverloadToken<Stmt *>) const {
170     return 1 + NumCatchStmts + HasFinally;
171   }
172 
173   // The location of the @ in the \@try.
174   SourceLocation AtTryLoc;
175 
176   // The number of catch blocks in this statement.
177   unsigned NumCatchStmts : 16;
178 
179   // Whether this statement has a \@finally statement.
180   LLVM_PREFERRED_TYPE(bool)
181   unsigned HasFinally : 1;
182 
183   /// Retrieve the statements that are stored after this \@try statement.
184   ///
185   /// The order of the statements in memory follows the order in the source,
186   /// with the \@try body first, followed by the \@catch statements (if any)
187   /// and, finally, the \@finally (if it exists).
getStmts()188   Stmt **getStmts() { return getTrailingObjects<Stmt *>(); }
getStmts()189   Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); }
190 
191   ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
192                 Stmt **CatchStmts, unsigned NumCatchStmts,
193                 Stmt *atFinallyStmt);
194 
ObjCAtTryStmt(EmptyShell Empty,unsigned NumCatchStmts,bool HasFinally)195   explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts,
196                          bool HasFinally)
197     : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts),
198       HasFinally(HasFinally) { }
199 
200 public:
201   static ObjCAtTryStmt *Create(const ASTContext &Context,
202                                SourceLocation atTryLoc, Stmt *atTryStmt,
203                                Stmt **CatchStmts, unsigned NumCatchStmts,
204                                Stmt *atFinallyStmt);
205   static ObjCAtTryStmt *CreateEmpty(const ASTContext &Context,
206                                     unsigned NumCatchStmts, bool HasFinally);
207 
208   /// Retrieve the location of the @ in the \@try.
getAtTryLoc()209   SourceLocation getAtTryLoc() const { return AtTryLoc; }
setAtTryLoc(SourceLocation Loc)210   void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
211 
212   /// Retrieve the \@try body.
getTryBody()213   const Stmt *getTryBody() const { return getStmts()[0]; }
getTryBody()214   Stmt *getTryBody() { return getStmts()[0]; }
setTryBody(Stmt * S)215   void setTryBody(Stmt *S) { getStmts()[0] = S; }
216 
217   /// Retrieve the number of \@catch statements in this try-catch-finally
218   /// block.
getNumCatchStmts()219   unsigned getNumCatchStmts() const { return NumCatchStmts; }
220 
221   /// Retrieve a \@catch statement.
getCatchStmt(unsigned I)222   const ObjCAtCatchStmt *getCatchStmt(unsigned I) const {
223     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
224     return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
225   }
226 
227   /// Retrieve a \@catch statement.
getCatchStmt(unsigned I)228   ObjCAtCatchStmt *getCatchStmt(unsigned I) {
229     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
230     return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
231   }
232 
233   /// Set a particular catch statement.
setCatchStmt(unsigned I,ObjCAtCatchStmt * S)234   void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) {
235     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
236     getStmts()[I + 1] = S;
237   }
238 
239   /// Retrieve the \@finally statement, if any.
getFinallyStmt()240   const ObjCAtFinallyStmt *getFinallyStmt() const {
241     if (!HasFinally)
242       return nullptr;
243 
244     return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
245   }
getFinallyStmt()246   ObjCAtFinallyStmt *getFinallyStmt() {
247     if (!HasFinally)
248       return nullptr;
249 
250     return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
251   }
setFinallyStmt(Stmt * S)252   void setFinallyStmt(Stmt *S) {
253     assert(HasFinally && "@try does not have a @finally slot!");
254     getStmts()[1 + NumCatchStmts] = S;
255   }
256 
getBeginLoc()257   SourceLocation getBeginLoc() const LLVM_READONLY { return AtTryLoc; }
258   SourceLocation getEndLoc() const LLVM_READONLY;
259 
classof(const Stmt * T)260   static bool classof(const Stmt *T) {
261     return T->getStmtClass() == ObjCAtTryStmtClass;
262   }
263 
children()264   child_range children() {
265     return child_range(
266         getStmts(), getStmts() + numTrailingObjects(OverloadToken<Stmt *>()));
267   }
268 
children()269   const_child_range children() const {
270     return const_child_range(const_cast<ObjCAtTryStmt *>(this)->children());
271   }
272 
273   using catch_stmt_iterator = CastIterator<ObjCAtCatchStmt>;
274   using const_catch_stmt_iterator = ConstCastIterator<ObjCAtCatchStmt>;
275   using catch_range = llvm::iterator_range<catch_stmt_iterator>;
276   using catch_const_range = llvm::iterator_range<const_catch_stmt_iterator>;
277 
catch_stmts_begin()278   catch_stmt_iterator catch_stmts_begin() { return getStmts() + 1; }
catch_stmts_end()279   catch_stmt_iterator catch_stmts_end() {
280     return catch_stmts_begin() + NumCatchStmts;
281   }
catch_stmts()282   catch_range catch_stmts() {
283     return catch_range(catch_stmts_begin(), catch_stmts_end());
284   }
285 
catch_stmts_begin()286   const_catch_stmt_iterator catch_stmts_begin() const { return getStmts() + 1; }
catch_stmts_end()287   const_catch_stmt_iterator catch_stmts_end() const {
288     return catch_stmts_begin() + NumCatchStmts;
289   }
catch_stmts()290   catch_const_range catch_stmts() const {
291     return catch_const_range(catch_stmts_begin(), catch_stmts_end());
292   }
293 };
294 
295 /// Represents Objective-C's \@synchronized statement.
296 ///
297 /// Example:
298 /// \code
299 ///   @synchronized (sem) {
300 ///     do-something;
301 ///   }
302 /// \endcode
303 class ObjCAtSynchronizedStmt : public Stmt {
304 private:
305   SourceLocation AtSynchronizedLoc;
306   enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
307   Stmt* SubStmts[END_EXPR];
308 
309 public:
ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc,Stmt * synchExpr,Stmt * synchBody)310   ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
311                          Stmt *synchBody)
312   : Stmt(ObjCAtSynchronizedStmtClass) {
313     SubStmts[SYNC_EXPR] = synchExpr;
314     SubStmts[SYNC_BODY] = synchBody;
315     AtSynchronizedLoc = atSynchronizedLoc;
316   }
ObjCAtSynchronizedStmt(EmptyShell Empty)317   explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
318     Stmt(ObjCAtSynchronizedStmtClass, Empty) { }
319 
getAtSynchronizedLoc()320   SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; }
setAtSynchronizedLoc(SourceLocation Loc)321   void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; }
322 
getSynchBody()323   const CompoundStmt *getSynchBody() const {
324     return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
325   }
getSynchBody()326   CompoundStmt *getSynchBody() {
327     return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
328   }
setSynchBody(Stmt * S)329   void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; }
330 
getSynchExpr()331   const Expr *getSynchExpr() const {
332     return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
333   }
getSynchExpr()334   Expr *getSynchExpr() {
335     return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
336   }
setSynchExpr(Stmt * S)337   void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
338 
getBeginLoc()339   SourceLocation getBeginLoc() const LLVM_READONLY { return AtSynchronizedLoc; }
getEndLoc()340   SourceLocation getEndLoc() const LLVM_READONLY {
341     return getSynchBody()->getEndLoc();
342   }
343 
classof(const Stmt * T)344   static bool classof(const Stmt *T) {
345     return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
346   }
347 
children()348   child_range children() {
349     return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
350   }
351 
children()352   const_child_range children() const {
353     return const_child_range(&SubStmts[0], &SubStmts[0] + END_EXPR);
354   }
355 };
356 
357 /// Represents Objective-C's \@throw statement.
358 class ObjCAtThrowStmt : public Stmt {
359   SourceLocation AtThrowLoc;
360   Stmt *Throw;
361 
362 public:
ObjCAtThrowStmt(SourceLocation atThrowLoc,Stmt * throwExpr)363   ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
364   : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
365     AtThrowLoc = atThrowLoc;
366   }
ObjCAtThrowStmt(EmptyShell Empty)367   explicit ObjCAtThrowStmt(EmptyShell Empty) :
368     Stmt(ObjCAtThrowStmtClass, Empty) { }
369 
getThrowExpr()370   const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); }
getThrowExpr()371   Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
setThrowExpr(Stmt * S)372   void setThrowExpr(Stmt *S) { Throw = S; }
373 
getThrowLoc()374   SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; }
setThrowLoc(SourceLocation Loc)375   void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
376 
getBeginLoc()377   SourceLocation getBeginLoc() const LLVM_READONLY { return AtThrowLoc; }
getEndLoc()378   SourceLocation getEndLoc() const LLVM_READONLY {
379     return Throw ? Throw->getEndLoc() : AtThrowLoc;
380   }
381 
classof(const Stmt * T)382   static bool classof(const Stmt *T) {
383     return T->getStmtClass() == ObjCAtThrowStmtClass;
384   }
385 
children()386   child_range children() { return child_range(&Throw, &Throw+1); }
387 
children()388   const_child_range children() const {
389     return const_child_range(&Throw, &Throw + 1);
390   }
391 };
392 
393 /// Represents Objective-C's \@autoreleasepool Statement
394 class ObjCAutoreleasePoolStmt : public Stmt {
395   SourceLocation AtLoc;
396   Stmt *SubStmt;
397 
398 public:
ObjCAutoreleasePoolStmt(SourceLocation atLoc,Stmt * subStmt)399   ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt)
400       : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {}
401 
ObjCAutoreleasePoolStmt(EmptyShell Empty)402   explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
403     Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
404 
getSubStmt()405   const Stmt *getSubStmt() const { return SubStmt; }
getSubStmt()406   Stmt *getSubStmt() { return SubStmt; }
setSubStmt(Stmt * S)407   void setSubStmt(Stmt *S) { SubStmt = S; }
408 
getBeginLoc()409   SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
getEndLoc()410   SourceLocation getEndLoc() const LLVM_READONLY {
411     return SubStmt->getEndLoc();
412   }
413 
getAtLoc()414   SourceLocation getAtLoc() const { return AtLoc; }
setAtLoc(SourceLocation Loc)415   void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
416 
classof(const Stmt * T)417   static bool classof(const Stmt *T) {
418     return T->getStmtClass() == ObjCAutoreleasePoolStmtClass;
419   }
420 
children()421   child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
422 
children()423   const_child_range children() const {
424     return const_child_range(&SubStmt, &SubStmt + 1);
425   }
426 };
427 
428 }  // end namespace clang
429 
430 #endif
431