StmtCXX.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- StmtCXX.h - Classes for representing C++ statements ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the C++ statement AST node classes.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CLANG_AST_STMTCXX_H
  18. #define LLVM_CLANG_AST_STMTCXX_H
  19. #include "clang/AST/DeclarationName.h"
  20. #include "clang/AST/Expr.h"
  21. #include "clang/AST/NestedNameSpecifier.h"
  22. #include "clang/AST/Stmt.h"
  23. #include "llvm/Support/Compiler.h"
  24. namespace clang {
  25. class VarDecl;
  26. /// CXXCatchStmt - This represents a C++ catch block.
  27. ///
  28. class CXXCatchStmt : public Stmt {
  29. SourceLocation CatchLoc;
  30. /// The exception-declaration of the type.
  31. VarDecl *ExceptionDecl;
  32. /// The handler block.
  33. Stmt *HandlerBlock;
  34. public:
  35. CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
  36. : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
  37. HandlerBlock(handlerBlock) {}
  38. CXXCatchStmt(EmptyShell Empty)
  39. : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {}
  40. SourceLocation getBeginLoc() const LLVM_READONLY { return CatchLoc; }
  41. SourceLocation getEndLoc() const LLVM_READONLY {
  42. return HandlerBlock->getEndLoc();
  43. }
  44. SourceLocation getCatchLoc() const { return CatchLoc; }
  45. VarDecl *getExceptionDecl() const { return ExceptionDecl; }
  46. QualType getCaughtType() const;
  47. Stmt *getHandlerBlock() const { return HandlerBlock; }
  48. static bool classof(const Stmt *T) {
  49. return T->getStmtClass() == CXXCatchStmtClass;
  50. }
  51. child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
  52. const_child_range children() const {
  53. return const_child_range(&HandlerBlock, &HandlerBlock + 1);
  54. }
  55. friend class ASTStmtReader;
  56. };
  57. /// CXXTryStmt - A C++ try block, including all handlers.
  58. ///
  59. class CXXTryStmt final : public Stmt,
  60. private llvm::TrailingObjects<CXXTryStmt, Stmt *> {
  61. friend TrailingObjects;
  62. friend class ASTStmtReader;
  63. SourceLocation TryLoc;
  64. unsigned NumHandlers;
  65. size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; }
  66. CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers);
  67. CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
  68. : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
  69. Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); }
  70. Stmt **getStmts() { return getTrailingObjects<Stmt *>(); }
  71. public:
  72. static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc,
  73. Stmt *tryBlock, ArrayRef<Stmt*> handlers);
  74. static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty,
  75. unsigned numHandlers);
  76. SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); }
  77. SourceLocation getTryLoc() const { return TryLoc; }
  78. SourceLocation getEndLoc() const {
  79. return getStmts()[NumHandlers]->getEndLoc();
  80. }
  81. CompoundStmt *getTryBlock() {
  82. return cast<CompoundStmt>(getStmts()[0]);
  83. }
  84. const CompoundStmt *getTryBlock() const {
  85. return cast<CompoundStmt>(getStmts()[0]);
  86. }
  87. unsigned getNumHandlers() const { return NumHandlers; }
  88. CXXCatchStmt *getHandler(unsigned i) {
  89. return cast<CXXCatchStmt>(getStmts()[i + 1]);
  90. }
  91. const CXXCatchStmt *getHandler(unsigned i) const {
  92. return cast<CXXCatchStmt>(getStmts()[i + 1]);
  93. }
  94. static bool classof(const Stmt *T) {
  95. return T->getStmtClass() == CXXTryStmtClass;
  96. }
  97. child_range children() {
  98. return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
  99. }
  100. const_child_range children() const {
  101. return const_child_range(getStmts(), getStmts() + getNumHandlers() + 1);
  102. }
  103. };
  104. /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
  105. /// statement, represented as 'for (range-declarator : range-expression)'
  106. /// or 'for (init-statement range-declarator : range-expression)'.
  107. ///
  108. /// This is stored in a partially-desugared form to allow full semantic
  109. /// analysis of the constituent components. The original syntactic components
  110. /// can be extracted using getLoopVariable and getRangeInit.
  111. class CXXForRangeStmt : public Stmt {
  112. SourceLocation ForLoc;
  113. enum { INIT, RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END };
  114. // SubExprs[RANGE] is an expression or declstmt.
  115. // SubExprs[COND] and SubExprs[INC] are expressions.
  116. Stmt *SubExprs[END];
  117. SourceLocation CoawaitLoc;
  118. SourceLocation ColonLoc;
  119. SourceLocation RParenLoc;
  120. friend class ASTStmtReader;
  121. public:
  122. CXXForRangeStmt(Stmt *InitStmt, DeclStmt *Range, DeclStmt *Begin,
  123. DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
  124. Stmt *Body, SourceLocation FL, SourceLocation CAL,
  125. SourceLocation CL, SourceLocation RPL);
  126. CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
  127. Stmt *getInit() { return SubExprs[INIT]; }
  128. VarDecl *getLoopVariable();
  129. Expr *getRangeInit();
  130. const Stmt *getInit() const { return SubExprs[INIT]; }
  131. const VarDecl *getLoopVariable() const;
  132. const Expr *getRangeInit() const;
  133. DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); }
  134. DeclStmt *getBeginStmt() {
  135. return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]);
  136. }
  137. DeclStmt *getEndStmt() { return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]); }
  138. Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); }
  139. Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); }
  140. DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
  141. Stmt *getBody() { return SubExprs[BODY]; }
  142. const DeclStmt *getRangeStmt() const {
  143. return cast<DeclStmt>(SubExprs[RANGE]);
  144. }
  145. const DeclStmt *getBeginStmt() const {
  146. return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]);
  147. }
  148. const DeclStmt *getEndStmt() const {
  149. return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]);
  150. }
  151. const Expr *getCond() const {
  152. return cast_or_null<Expr>(SubExprs[COND]);
  153. }
  154. const Expr *getInc() const {
  155. return cast_or_null<Expr>(SubExprs[INC]);
  156. }
  157. const DeclStmt *getLoopVarStmt() const {
  158. return cast<DeclStmt>(SubExprs[LOOPVAR]);
  159. }
  160. const Stmt *getBody() const { return SubExprs[BODY]; }
  161. void setInit(Stmt *S) { SubExprs[INIT] = S; }
  162. void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); }
  163. void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; }
  164. void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; }
  165. void setEndStmt(Stmt *S) { SubExprs[ENDSTMT] = S; }
  166. void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
  167. void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
  168. void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
  169. void setBody(Stmt *S) { SubExprs[BODY] = S; }
  170. SourceLocation getForLoc() const { return ForLoc; }
  171. SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
  172. SourceLocation getColonLoc() const { return ColonLoc; }
  173. SourceLocation getRParenLoc() const { return RParenLoc; }
  174. SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; }
  175. SourceLocation getEndLoc() const LLVM_READONLY {
  176. return SubExprs[BODY]->getEndLoc();
  177. }
  178. static bool classof(const Stmt *T) {
  179. return T->getStmtClass() == CXXForRangeStmtClass;
  180. }
  181. // Iterators
  182. child_range children() {
  183. return child_range(&SubExprs[0], &SubExprs[END]);
  184. }
  185. const_child_range children() const {
  186. return const_child_range(&SubExprs[0], &SubExprs[END]);
  187. }
  188. };
  189. /// Representation of a Microsoft __if_exists or __if_not_exists
  190. /// statement with a dependent name.
  191. ///
  192. /// The __if_exists statement can be used to include a sequence of statements
  193. /// in the program only when a particular dependent name does not exist. For
  194. /// example:
  195. ///
  196. /// \code
  197. /// template<typename T>
  198. /// void call_foo(T &t) {
  199. /// __if_exists (T::foo) {
  200. /// t.foo(); // okay: only called when T::foo exists.
  201. /// }
  202. /// }
  203. /// \endcode
  204. ///
  205. /// Similarly, the __if_not_exists statement can be used to include the
  206. /// statements when a particular name does not exist.
  207. ///
  208. /// Note that this statement only captures __if_exists and __if_not_exists
  209. /// statements whose name is dependent. All non-dependent cases are handled
  210. /// directly in the parser, so that they don't introduce a new scope. Clang
  211. /// introduces scopes in the dependent case to keep names inside the compound
  212. /// statement from leaking out into the surround statements, which would
  213. /// compromise the template instantiation model. This behavior differs from
  214. /// Visual C++ (which never introduces a scope), but is a fairly reasonable
  215. /// approximation of the VC++ behavior.
  216. class MSDependentExistsStmt : public Stmt {
  217. SourceLocation KeywordLoc;
  218. bool IsIfExists;
  219. NestedNameSpecifierLoc QualifierLoc;
  220. DeclarationNameInfo NameInfo;
  221. Stmt *SubStmt;
  222. friend class ASTReader;
  223. friend class ASTStmtReader;
  224. public:
  225. MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists,
  226. NestedNameSpecifierLoc QualifierLoc,
  227. DeclarationNameInfo NameInfo,
  228. CompoundStmt *SubStmt)
  229. : Stmt(MSDependentExistsStmtClass),
  230. KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
  231. QualifierLoc(QualifierLoc), NameInfo(NameInfo),
  232. SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
  233. /// Retrieve the location of the __if_exists or __if_not_exists
  234. /// keyword.
  235. SourceLocation getKeywordLoc() const { return KeywordLoc; }
  236. /// Determine whether this is an __if_exists statement.
  237. bool isIfExists() const { return IsIfExists; }
  238. /// Determine whether this is an __if_exists statement.
  239. bool isIfNotExists() const { return !IsIfExists; }
  240. /// Retrieve the nested-name-specifier that qualifies this name, if
  241. /// any.
  242. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
  243. /// Retrieve the name of the entity we're testing for, along with
  244. /// location information
  245. DeclarationNameInfo getNameInfo() const { return NameInfo; }
  246. /// Retrieve the compound statement that will be included in the
  247. /// program only if the existence of the symbol matches the initial keyword.
  248. CompoundStmt *getSubStmt() const {
  249. return reinterpret_cast<CompoundStmt *>(SubStmt);
  250. }
  251. SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
  252. SourceLocation getEndLoc() const LLVM_READONLY {
  253. return SubStmt->getEndLoc();
  254. }
  255. child_range children() {
  256. return child_range(&SubStmt, &SubStmt+1);
  257. }
  258. const_child_range children() const {
  259. return const_child_range(&SubStmt, &SubStmt + 1);
  260. }
  261. static bool classof(const Stmt *T) {
  262. return T->getStmtClass() == MSDependentExistsStmtClass;
  263. }
  264. };
  265. /// Represents the body of a coroutine. This wraps the normal function
  266. /// body and holds the additional semantic context required to set up and tear
  267. /// down the coroutine frame.
  268. class CoroutineBodyStmt final
  269. : public Stmt,
  270. private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> {
  271. enum SubStmt {
  272. Body, ///< The body of the coroutine.
  273. Promise, ///< The promise statement.
  274. InitSuspend, ///< The initial suspend statement, run before the body.
  275. FinalSuspend, ///< The final suspend statement, run after the body.
  276. OnException, ///< Handler for exceptions thrown in the body.
  277. OnFallthrough, ///< Handler for control flow falling off the body.
  278. Allocate, ///< Coroutine frame memory allocation.
  279. Deallocate, ///< Coroutine frame memory deallocation.
  280. ReturnValue, ///< Return value for thunk function: p.get_return_object().
  281. ResultDecl, ///< Declaration holding the result of get_return_object.
  282. ReturnStmt, ///< Return statement for the thunk function.
  283. ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
  284. FirstParamMove ///< First offset for move construction of parameter copies.
  285. };
  286. unsigned NumParams;
  287. friend class ASTStmtReader;
  288. friend class ASTReader;
  289. friend TrailingObjects;
  290. Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
  291. Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
  292. public:
  293. struct CtorArgs {
  294. Stmt *Body = nullptr;
  295. Stmt *Promise = nullptr;
  296. Expr *InitialSuspend = nullptr;
  297. Expr *FinalSuspend = nullptr;
  298. Stmt *OnException = nullptr;
  299. Stmt *OnFallthrough = nullptr;
  300. Expr *Allocate = nullptr;
  301. Expr *Deallocate = nullptr;
  302. Expr *ReturnValue = nullptr;
  303. Stmt *ResultDecl = nullptr;
  304. Stmt *ReturnStmt = nullptr;
  305. Stmt *ReturnStmtOnAllocFailure = nullptr;
  306. ArrayRef<Stmt *> ParamMoves;
  307. };
  308. private:
  309. CoroutineBodyStmt(CtorArgs const& Args);
  310. public:
  311. static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args);
  312. static CoroutineBodyStmt *Create(const ASTContext &C, EmptyShell,
  313. unsigned NumParams);
  314. bool hasDependentPromiseType() const {
  315. return getPromiseDecl()->getType()->isDependentType();
  316. }
  317. /// Retrieve the body of the coroutine as written. This will be either
  318. /// a CompoundStmt or a TryStmt.
  319. Stmt *getBody() const {
  320. return getStoredStmts()[SubStmt::Body];
  321. }
  322. Stmt *getPromiseDeclStmt() const {
  323. return getStoredStmts()[SubStmt::Promise];
  324. }
  325. VarDecl *getPromiseDecl() const {
  326. return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
  327. }
  328. Stmt *getInitSuspendStmt() const {
  329. return getStoredStmts()[SubStmt::InitSuspend];
  330. }
  331. Stmt *getFinalSuspendStmt() const {
  332. return getStoredStmts()[SubStmt::FinalSuspend];
  333. }
  334. Stmt *getExceptionHandler() const {
  335. return getStoredStmts()[SubStmt::OnException];
  336. }
  337. Stmt *getFallthroughHandler() const {
  338. return getStoredStmts()[SubStmt::OnFallthrough];
  339. }
  340. Expr *getAllocate() const {
  341. return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]);
  342. }
  343. Expr *getDeallocate() const {
  344. return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
  345. }
  346. Expr *getReturnValueInit() const {
  347. return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
  348. }
  349. Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
  350. Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
  351. Stmt *getReturnStmtOnAllocFailure() const {
  352. return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
  353. }
  354. ArrayRef<Stmt const *> getParamMoves() const {
  355. return {getStoredStmts() + SubStmt::FirstParamMove, NumParams};
  356. }
  357. SourceLocation getBeginLoc() const LLVM_READONLY {
  358. return getBody() ? getBody()->getBeginLoc()
  359. : getPromiseDecl()->getBeginLoc();
  360. }
  361. SourceLocation getEndLoc() const LLVM_READONLY {
  362. return getBody() ? getBody()->getEndLoc() : getPromiseDecl()->getEndLoc();
  363. }
  364. child_range children() {
  365. return child_range(getStoredStmts(),
  366. getStoredStmts() + SubStmt::FirstParamMove + NumParams);
  367. }
  368. const_child_range children() const {
  369. return const_child_range(getStoredStmts(), getStoredStmts() +
  370. SubStmt::FirstParamMove +
  371. NumParams);
  372. }
  373. static bool classof(const Stmt *T) {
  374. return T->getStmtClass() == CoroutineBodyStmtClass;
  375. }
  376. };
  377. /// Represents a 'co_return' statement in the C++ Coroutines TS.
  378. ///
  379. /// This statament models the initialization of the coroutine promise
  380. /// (encapsulating the eventual notional return value) from an expression
  381. /// (or braced-init-list), followed by termination of the coroutine.
  382. ///
  383. /// This initialization is modeled by the evaluation of the operand
  384. /// followed by a call to one of:
  385. /// <promise>.return_value(<operand>)
  386. /// <promise>.return_void()
  387. /// which we name the "promise call".
  388. class CoreturnStmt : public Stmt {
  389. SourceLocation CoreturnLoc;
  390. enum SubStmt { Operand, PromiseCall, Count };
  391. Stmt *SubStmts[SubStmt::Count];
  392. bool IsImplicit : 1;
  393. friend class ASTStmtReader;
  394. public:
  395. CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall,
  396. bool IsImplicit = false)
  397. : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc),
  398. IsImplicit(IsImplicit) {
  399. SubStmts[SubStmt::Operand] = Operand;
  400. SubStmts[SubStmt::PromiseCall] = PromiseCall;
  401. }
  402. CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {}
  403. SourceLocation getKeywordLoc() const { return CoreturnLoc; }
  404. /// Retrieve the operand of the 'co_return' statement. Will be nullptr
  405. /// if none was specified.
  406. Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
  407. /// Retrieve the promise call that results from this 'co_return'
  408. /// statement. Will be nullptr if either the coroutine has not yet been
  409. /// finalized or the coroutine has no eventual return type.
  410. Expr *getPromiseCall() const {
  411. return static_cast<Expr*>(SubStmts[PromiseCall]);
  412. }
  413. bool isImplicit() const { return IsImplicit; }
  414. void setIsImplicit(bool value = true) { IsImplicit = value; }
  415. SourceLocation getBeginLoc() const LLVM_READONLY { return CoreturnLoc; }
  416. SourceLocation getEndLoc() const LLVM_READONLY {
  417. return getOperand() ? getOperand()->getEndLoc() : getBeginLoc();
  418. }
  419. child_range children() {
  420. if (!getOperand())
  421. return child_range(SubStmts + SubStmt::PromiseCall,
  422. SubStmts + SubStmt::Count);
  423. return child_range(SubStmts, SubStmts + SubStmt::Count);
  424. }
  425. const_child_range children() const {
  426. if (!getOperand())
  427. return const_child_range(SubStmts + SubStmt::PromiseCall,
  428. SubStmts + SubStmt::Count);
  429. return const_child_range(SubStmts, SubStmts + SubStmt::Count);
  430. }
  431. static bool classof(const Stmt *T) {
  432. return T->getStmtClass() == CoreturnStmtClass;
  433. }
  434. };
  435. } // end namespace clang
  436. #endif
  437. #ifdef __GNUC__
  438. #pragma GCC diagnostic pop
  439. #endif