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