1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_AST_STMTCXX_H |
14 | #define LLVM_CLANG_AST_STMTCXX_H |
15 | |
16 | #include "clang/AST/DeclarationName.h" |
17 | #include "clang/AST/Expr.h" |
18 | #include "clang/AST/NestedNameSpecifier.h" |
19 | #include "clang/AST/Stmt.h" |
20 | #include "llvm/Support/Compiler.h" |
21 | |
22 | namespace clang { |
23 | |
24 | class VarDecl; |
25 | |
26 | |
27 | |
28 | class CXXCatchStmt : public Stmt { |
29 | SourceLocation CatchLoc; |
30 | |
31 | VarDecl *ExceptionDecl; |
32 | |
33 | Stmt *HandlerBlock; |
34 | |
35 | public: |
36 | CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) |
37 | : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), |
38 | HandlerBlock(handlerBlock) {} |
39 | |
40 | CXXCatchStmt(EmptyShell Empty) |
41 | : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {} |
42 | |
43 | SourceLocation getBeginLoc() const LLVM_READONLY { return CatchLoc; } |
44 | SourceLocation getEndLoc() const LLVM_READONLY { |
45 | return HandlerBlock->getEndLoc(); |
46 | } |
47 | |
48 | SourceLocation getCatchLoc() const { return CatchLoc; } |
49 | VarDecl *getExceptionDecl() const { return ExceptionDecl; } |
50 | QualType getCaughtType() const; |
51 | Stmt *getHandlerBlock() const { return HandlerBlock; } |
52 | |
53 | static bool classof(const Stmt *T) { |
54 | return T->getStmtClass() == CXXCatchStmtClass; |
55 | } |
56 | |
57 | child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } |
58 | |
59 | friend class ASTStmtReader; |
60 | }; |
61 | |
62 | |
63 | |
64 | class CXXTryStmt final : public Stmt, |
65 | private llvm::TrailingObjects<CXXTryStmt, Stmt *> { |
66 | |
67 | friend TrailingObjects; |
68 | friend class ASTStmtReader; |
69 | |
70 | SourceLocation TryLoc; |
71 | unsigned NumHandlers; |
72 | size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; } |
73 | |
74 | CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); |
75 | CXXTryStmt(EmptyShell Empty, unsigned numHandlers) |
76 | : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } |
77 | |
78 | Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); } |
79 | Stmt **getStmts() { return getTrailingObjects<Stmt *>(); } |
80 | |
81 | public: |
82 | static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, |
83 | Stmt *tryBlock, ArrayRef<Stmt*> handlers); |
84 | |
85 | static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, |
86 | unsigned numHandlers); |
87 | |
88 | SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); } |
89 | |
90 | SourceLocation getTryLoc() const { return TryLoc; } |
91 | SourceLocation getEndLoc() const { |
92 | return getStmts()[NumHandlers]->getEndLoc(); |
93 | } |
94 | |
95 | CompoundStmt *getTryBlock() { |
96 | return cast<CompoundStmt>(getStmts()[0]); |
97 | } |
98 | const CompoundStmt *getTryBlock() const { |
99 | return cast<CompoundStmt>(getStmts()[0]); |
100 | } |
101 | |
102 | unsigned getNumHandlers() const { return NumHandlers; } |
103 | CXXCatchStmt *getHandler(unsigned i) { |
104 | return cast<CXXCatchStmt>(getStmts()[i + 1]); |
105 | } |
106 | const CXXCatchStmt *getHandler(unsigned i) const { |
107 | return cast<CXXCatchStmt>(getStmts()[i + 1]); |
108 | } |
109 | |
110 | static bool classof(const Stmt *T) { |
111 | return T->getStmtClass() == CXXTryStmtClass; |
112 | } |
113 | |
114 | child_range children() { |
115 | return child_range(getStmts(), getStmts() + getNumHandlers() + 1); |
116 | } |
117 | }; |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | class CXXForRangeStmt : public Stmt { |
127 | SourceLocation ForLoc; |
128 | enum { INIT, RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END }; |
129 | |
130 | |
131 | Stmt *SubExprs[END]; |
132 | SourceLocation CoawaitLoc; |
133 | SourceLocation ColonLoc; |
134 | SourceLocation RParenLoc; |
135 | |
136 | friend class ASTStmtReader; |
137 | public: |
138 | CXXForRangeStmt(Stmt *InitStmt, DeclStmt *Range, DeclStmt *Begin, |
139 | DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar, |
140 | Stmt *Body, SourceLocation FL, SourceLocation CAL, |
141 | SourceLocation CL, SourceLocation RPL); |
142 | CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } |
143 | |
144 | Stmt *getInit() { return SubExprs[INIT]; } |
145 | VarDecl *getLoopVariable(); |
146 | Expr *getRangeInit(); |
147 | |
148 | const Stmt *getInit() const { return SubExprs[INIT]; } |
149 | const VarDecl *getLoopVariable() const; |
150 | const Expr *getRangeInit() const; |
151 | |
152 | |
153 | DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } |
154 | DeclStmt *getBeginStmt() { |
155 | return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]); |
156 | } |
157 | DeclStmt *getEndStmt() { return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]); } |
158 | Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } |
159 | Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } |
160 | DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } |
161 | Stmt *getBody() { return SubExprs[BODY]; } |
162 | |
163 | const DeclStmt *getRangeStmt() const { |
164 | return cast<DeclStmt>(SubExprs[RANGE]); |
165 | } |
166 | const DeclStmt *getBeginStmt() const { |
167 | return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]); |
168 | } |
169 | const DeclStmt *getEndStmt() const { |
170 | return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]); |
171 | } |
172 | const Expr *getCond() const { |
173 | return cast_or_null<Expr>(SubExprs[COND]); |
174 | } |
175 | const Expr *getInc() const { |
176 | return cast_or_null<Expr>(SubExprs[INC]); |
177 | } |
178 | const DeclStmt *getLoopVarStmt() const { |
179 | return cast<DeclStmt>(SubExprs[LOOPVAR]); |
180 | } |
181 | const Stmt *getBody() const { return SubExprs[BODY]; } |
182 | |
183 | void setInit(Stmt *S) { SubExprs[INIT] = S; } |
184 | void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } |
185 | void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } |
186 | void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; } |
187 | void setEndStmt(Stmt *S) { SubExprs[ENDSTMT] = S; } |
188 | void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } |
189 | void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } |
190 | void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } |
191 | void setBody(Stmt *S) { SubExprs[BODY] = S; } |
192 | |
193 | SourceLocation getForLoc() const { return ForLoc; } |
194 | SourceLocation getCoawaitLoc() const { return CoawaitLoc; } |
195 | SourceLocation getColonLoc() const { return ColonLoc; } |
196 | SourceLocation getRParenLoc() const { return RParenLoc; } |
197 | |
198 | SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; } |
199 | SourceLocation getEndLoc() const LLVM_READONLY { |
200 | return SubExprs[BODY]->getEndLoc(); |
201 | } |
202 | |
203 | static bool classof(const Stmt *T) { |
204 | return T->getStmtClass() == CXXForRangeStmtClass; |
205 | } |
206 | |
207 | |
208 | child_range children() { |
209 | return child_range(&SubExprs[0], &SubExprs[END]); |
210 | } |
211 | }; |
212 | |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | |
238 | |
239 | |
240 | class MSDependentExistsStmt : public Stmt { |
241 | SourceLocation KeywordLoc; |
242 | bool IsIfExists; |
243 | NestedNameSpecifierLoc QualifierLoc; |
244 | DeclarationNameInfo NameInfo; |
245 | Stmt *SubStmt; |
246 | |
247 | friend class ASTReader; |
248 | friend class ASTStmtReader; |
249 | |
250 | public: |
251 | MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, |
252 | NestedNameSpecifierLoc QualifierLoc, |
253 | DeclarationNameInfo NameInfo, |
254 | CompoundStmt *SubStmt) |
255 | : Stmt(MSDependentExistsStmtClass), |
256 | KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), |
257 | QualifierLoc(QualifierLoc), NameInfo(NameInfo), |
258 | SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } |
259 | |
260 | |
261 | |
262 | SourceLocation getKeywordLoc() const { return KeywordLoc; } |
263 | |
264 | |
265 | bool isIfExists() const { return IsIfExists; } |
266 | |
267 | |
268 | bool isIfNotExists() const { return !IsIfExists; } |
269 | |
270 | |
271 | |
272 | NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } |
273 | |
274 | |
275 | |
276 | DeclarationNameInfo getNameInfo() const { return NameInfo; } |
277 | |
278 | |
279 | |
280 | CompoundStmt *getSubStmt() const { |
281 | return reinterpret_cast<CompoundStmt *>(SubStmt); |
282 | } |
283 | |
284 | SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } |
285 | SourceLocation getEndLoc() const LLVM_READONLY { |
286 | return SubStmt->getEndLoc(); |
287 | } |
288 | |
289 | child_range children() { |
290 | return child_range(&SubStmt, &SubStmt+1); |
291 | } |
292 | |
293 | static bool classof(const Stmt *T) { |
294 | return T->getStmtClass() == MSDependentExistsStmtClass; |
295 | } |
296 | }; |
297 | |
298 | |
299 | |
300 | |
301 | class CoroutineBodyStmt final |
302 | : public Stmt, |
303 | private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> { |
304 | enum SubStmt { |
305 | Body, |
306 | Promise, |
307 | InitSuspend, |
308 | FinalSuspend, |
309 | OnException, |
310 | OnFallthrough, |
311 | Allocate, |
312 | Deallocate, |
313 | ReturnValue, |
314 | ResultDecl, |
315 | ReturnStmt, |
316 | ReturnStmtOnAllocFailure, |
317 | FirstParamMove |
318 | }; |
319 | unsigned NumParams; |
320 | |
321 | friend class ASTStmtReader; |
322 | friend class ASTReader; |
323 | friend TrailingObjects; |
324 | |
325 | Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } |
326 | |
327 | Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } |
328 | |
329 | public: |
330 | |
331 | struct CtorArgs { |
332 | Stmt *Body = nullptr; |
333 | Stmt *Promise = nullptr; |
334 | Expr *InitialSuspend = nullptr; |
335 | Expr *FinalSuspend = nullptr; |
336 | Stmt *OnException = nullptr; |
337 | Stmt *OnFallthrough = nullptr; |
338 | Expr *Allocate = nullptr; |
339 | Expr *Deallocate = nullptr; |
340 | Expr *ReturnValue = nullptr; |
341 | Stmt *ResultDecl = nullptr; |
342 | Stmt *ReturnStmt = nullptr; |
343 | Stmt *ReturnStmtOnAllocFailure = nullptr; |
344 | ArrayRef<Stmt *> ParamMoves; |
345 | }; |
346 | |
347 | private: |
348 | |
349 | CoroutineBodyStmt(CtorArgs const& Args); |
350 | |
351 | public: |
352 | static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args); |
353 | static CoroutineBodyStmt *Create(const ASTContext &C, EmptyShell, |
354 | unsigned NumParams); |
355 | |
356 | bool hasDependentPromiseType() const { |
357 | return getPromiseDecl()->getType()->isDependentType(); |
358 | } |
359 | |
360 | |
361 | |
362 | Stmt *getBody() const { |
363 | return getStoredStmts()[SubStmt::Body]; |
364 | } |
365 | |
366 | Stmt *getPromiseDeclStmt() const { |
367 | return getStoredStmts()[SubStmt::Promise]; |
368 | } |
369 | VarDecl *getPromiseDecl() const { |
370 | return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); |
371 | } |
372 | |
373 | Stmt *getInitSuspendStmt() const { |
374 | return getStoredStmts()[SubStmt::InitSuspend]; |
375 | } |
376 | Stmt *getFinalSuspendStmt() const { |
377 | return getStoredStmts()[SubStmt::FinalSuspend]; |
378 | } |
379 | |
380 | Stmt *getExceptionHandler() const { |
381 | return getStoredStmts()[SubStmt::OnException]; |
382 | } |
383 | Stmt *getFallthroughHandler() const { |
384 | return getStoredStmts()[SubStmt::OnFallthrough]; |
385 | } |
386 | |
387 | Expr *getAllocate() const { |
388 | return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]); |
389 | } |
390 | Expr *getDeallocate() const { |
391 | return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]); |
392 | } |
393 | Expr *getReturnValueInit() const { |
394 | return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]); |
395 | } |
396 | Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; } |
397 | Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; } |
398 | Stmt *getReturnStmtOnAllocFailure() const { |
399 | return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure]; |
400 | } |
401 | ArrayRef<Stmt const *> getParamMoves() const { |
402 | return {getStoredStmts() + SubStmt::FirstParamMove, NumParams}; |
403 | } |
404 | |
405 | SourceLocation getBeginLoc() const LLVM_READONLY { |
406 | return getBody() ? getBody()->getBeginLoc() |
407 | : getPromiseDecl()->getBeginLoc(); |
408 | } |
409 | SourceLocation getEndLoc() const LLVM_READONLY { |
410 | return getBody() ? getBody()->getEndLoc() : getPromiseDecl()->getEndLoc(); |
411 | } |
412 | |
413 | child_range children() { |
414 | return child_range(getStoredStmts(), |
415 | getStoredStmts() + SubStmt::FirstParamMove + NumParams); |
416 | } |
417 | |
418 | static bool classof(const Stmt *T) { |
419 | return T->getStmtClass() == CoroutineBodyStmtClass; |
420 | } |
421 | }; |
422 | |
423 | |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | |
434 | class CoreturnStmt : public Stmt { |
435 | SourceLocation CoreturnLoc; |
436 | |
437 | enum SubStmt { Operand, PromiseCall, Count }; |
438 | Stmt *SubStmts[SubStmt::Count]; |
439 | |
440 | bool IsImplicit : 1; |
441 | |
442 | friend class ASTStmtReader; |
443 | public: |
444 | CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall, |
445 | bool IsImplicit = false) |
446 | : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc), |
447 | IsImplicit(IsImplicit) { |
448 | SubStmts[SubStmt::Operand] = Operand; |
449 | SubStmts[SubStmt::PromiseCall] = PromiseCall; |
450 | } |
451 | |
452 | CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {} |
453 | |
454 | SourceLocation getKeywordLoc() const { return CoreturnLoc; } |
455 | |
456 | |
457 | |
458 | Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } |
459 | |
460 | |
461 | |
462 | |
463 | Expr *getPromiseCall() const { |
464 | return static_cast<Expr*>(SubStmts[PromiseCall]); |
465 | } |
466 | |
467 | bool isImplicit() const { return IsImplicit; } |
468 | void setIsImplicit(bool value = true) { IsImplicit = value; } |
469 | |
470 | SourceLocation getBeginLoc() const LLVM_READONLY { return CoreturnLoc; } |
471 | SourceLocation getEndLoc() const LLVM_READONLY { |
472 | return getOperand() ? getOperand()->getEndLoc() : getBeginLoc(); |
473 | } |
474 | |
475 | child_range children() { |
476 | if (!getOperand()) |
477 | return child_range(SubStmts + SubStmt::PromiseCall, |
478 | SubStmts + SubStmt::Count); |
479 | return child_range(SubStmts, SubStmts + SubStmt::Count); |
480 | } |
481 | |
482 | static bool classof(const Stmt *T) { |
483 | return T->getStmtClass() == CoreturnStmtClass; |
484 | } |
485 | }; |
486 | |
487 | } |
488 | |
489 | #endif |
490 | |