RAIIObjectsForParser.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. //===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines and implements the some simple RAII objects that are used
  11. // by the parser to manage bits in recursion.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
  15. #define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
  16. #include "clang/Parse/ParseDiagnostic.h"
  17. #include "clang/Parse/Parser.h"
  18. #include "clang/Sema/DelayedDiagnostic.h"
  19. #include "clang/Sema/Sema.h"
  20. namespace clang {
  21. // TODO: move ParsingClassDefinition here.
  22. // TODO: move TentativeParsingAction here.
  23. /// \brief A RAII object used to temporarily suppress access-like
  24. /// checking. Access-like checks are those associated with
  25. /// controlling the use of a declaration, like C++ access control
  26. /// errors and deprecation warnings. They are contextually
  27. /// dependent, in that they can only be resolved with full
  28. /// information about what's being declared. They are also
  29. /// suppressed in certain contexts, like the template arguments of
  30. /// an explicit instantiation. However, those suppression contexts
  31. /// cannot necessarily be fully determined in advance; for
  32. /// example, something starting like this:
  33. /// template <> class std::vector<A::PrivateType>
  34. /// might be the entirety of an explicit instantiation:
  35. /// template <> class std::vector<A::PrivateType>;
  36. /// or just an elaborated type specifier:
  37. /// template <> class std::vector<A::PrivateType> make_vector<>();
  38. /// Therefore this class collects all the diagnostics and permits
  39. /// them to be re-delayed in a new context.
  40. class SuppressAccessChecks {
  41. Sema &S;
  42. sema::DelayedDiagnosticPool DiagnosticPool;
  43. Sema::ParsingDeclState State;
  44. bool Active;
  45. public:
  46. /// Begin suppressing access-like checks
  47. SuppressAccessChecks(Parser &P, bool activate = true)
  48. : S(P.getActions()), DiagnosticPool(nullptr) {
  49. if (activate) {
  50. State = S.PushParsingDeclaration(DiagnosticPool);
  51. Active = true;
  52. } else {
  53. Active = false;
  54. }
  55. }
  56. SuppressAccessChecks(SuppressAccessChecks &&Other)
  57. : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
  58. State(Other.State), Active(Other.Active) {
  59. Other.Active = false;
  60. }
  61. void operator=(SuppressAccessChecks &&Other) = delete;
  62. void done() {
  63. assert(Active && "trying to end an inactive suppression");
  64. S.PopParsingDeclaration(State, nullptr);
  65. Active = false;
  66. }
  67. void redelay() {
  68. assert(!Active && "redelaying without having ended first");
  69. if (!DiagnosticPool.pool_empty())
  70. S.redelayDiagnostics(DiagnosticPool);
  71. assert(DiagnosticPool.pool_empty());
  72. }
  73. ~SuppressAccessChecks() {
  74. if (Active) done();
  75. }
  76. };
  77. /// \brief RAII object used to inform the actions that we're
  78. /// currently parsing a declaration. This is active when parsing a
  79. /// variable's initializer, but not when parsing the body of a
  80. /// class or function definition.
  81. class ParsingDeclRAIIObject {
  82. Sema &Actions;
  83. sema::DelayedDiagnosticPool DiagnosticPool;
  84. Sema::ParsingDeclState State;
  85. bool Popped;
  86. ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
  87. void operator=(const ParsingDeclRAIIObject &) = delete;
  88. public:
  89. enum NoParent_t { NoParent };
  90. ParsingDeclRAIIObject(Parser &P, NoParent_t _)
  91. : Actions(P.getActions()), DiagnosticPool(nullptr) {
  92. push();
  93. }
  94. /// Creates a RAII object whose pool is optionally parented by another.
  95. ParsingDeclRAIIObject(Parser &P,
  96. const sema::DelayedDiagnosticPool *parentPool)
  97. : Actions(P.getActions()), DiagnosticPool(parentPool) {
  98. push();
  99. }
  100. /// Creates a RAII object and, optionally, initialize its
  101. /// diagnostics pool by stealing the diagnostics from another
  102. /// RAII object (which is assumed to be the current top pool).
  103. ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
  104. : Actions(P.getActions()),
  105. DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
  106. if (other) {
  107. DiagnosticPool.steal(other->DiagnosticPool);
  108. other->abort();
  109. }
  110. push();
  111. }
  112. ~ParsingDeclRAIIObject() {
  113. abort();
  114. }
  115. sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
  116. return DiagnosticPool;
  117. }
  118. const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
  119. return DiagnosticPool;
  120. }
  121. /// Resets the RAII object for a new declaration.
  122. void reset() {
  123. abort();
  124. push();
  125. }
  126. /// Signals that the context was completed without an appropriate
  127. /// declaration being parsed.
  128. void abort() {
  129. pop(nullptr);
  130. }
  131. void complete(Decl *D) {
  132. assert(!Popped && "ParsingDeclaration has already been popped!");
  133. pop(D);
  134. }
  135. /// Unregister this object from Sema, but remember all the
  136. /// diagnostics that were emitted into it.
  137. void abortAndRemember() {
  138. pop(nullptr);
  139. }
  140. private:
  141. void push() {
  142. State = Actions.PushParsingDeclaration(DiagnosticPool);
  143. Popped = false;
  144. }
  145. void pop(Decl *D) {
  146. if (!Popped) {
  147. Actions.PopParsingDeclaration(State, D);
  148. Popped = true;
  149. }
  150. }
  151. };
  152. /// A class for parsing a DeclSpec.
  153. class ParsingDeclSpec : public DeclSpec {
  154. ParsingDeclRAIIObject ParsingRAII;
  155. public:
  156. ParsingDeclSpec(Parser &P)
  157. : DeclSpec(P.getAttrFactory()),
  158. ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
  159. ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
  160. : DeclSpec(P.getAttrFactory()),
  161. ParsingRAII(P, RAII) {}
  162. const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
  163. return ParsingRAII.getDelayedDiagnosticPool();
  164. }
  165. void complete(Decl *D) {
  166. ParsingRAII.complete(D);
  167. }
  168. void abort() {
  169. ParsingRAII.abort();
  170. }
  171. };
  172. /// A class for parsing a declarator.
  173. class ParsingDeclarator : public Declarator {
  174. ParsingDeclRAIIObject ParsingRAII;
  175. public:
  176. ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
  177. : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
  178. }
  179. const ParsingDeclSpec &getDeclSpec() const {
  180. return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
  181. }
  182. ParsingDeclSpec &getMutableDeclSpec() const {
  183. return const_cast<ParsingDeclSpec&>(getDeclSpec());
  184. }
  185. void clear() {
  186. Declarator::clear();
  187. ParsingRAII.reset();
  188. }
  189. void complete(Decl *D) {
  190. ParsingRAII.complete(D);
  191. }
  192. };
  193. /// A class for parsing a field declarator.
  194. class ParsingFieldDeclarator : public FieldDeclarator {
  195. ParsingDeclRAIIObject ParsingRAII;
  196. public:
  197. ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
  198. : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
  199. }
  200. const ParsingDeclSpec &getDeclSpec() const {
  201. return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
  202. }
  203. ParsingDeclSpec &getMutableDeclSpec() const {
  204. return const_cast<ParsingDeclSpec&>(getDeclSpec());
  205. }
  206. void complete(Decl *D) {
  207. ParsingRAII.complete(D);
  208. }
  209. };
  210. /// ExtensionRAIIObject - This saves the state of extension warnings when
  211. /// constructed and disables them. When destructed, it restores them back to
  212. /// the way they used to be. This is used to handle __extension__ in the
  213. /// parser.
  214. class ExtensionRAIIObject {
  215. ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
  216. void operator=(const ExtensionRAIIObject &) = delete;
  217. DiagnosticsEngine &Diags;
  218. public:
  219. ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
  220. Diags.IncrementAllExtensionsSilenced();
  221. }
  222. ~ExtensionRAIIObject() {
  223. Diags.DecrementAllExtensionsSilenced();
  224. }
  225. };
  226. /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
  227. /// restores it when destroyed. This says that "foo:" should not be
  228. /// considered a possible typo for "foo::" for error recovery purposes.
  229. class ColonProtectionRAIIObject {
  230. Parser &P;
  231. bool OldVal;
  232. public:
  233. ColonProtectionRAIIObject(Parser &p, bool Value = true)
  234. : P(p), OldVal(P.ColonIsSacred) {
  235. P.ColonIsSacred = Value;
  236. }
  237. /// restore - This can be used to restore the state early, before the dtor
  238. /// is run.
  239. void restore() {
  240. P.ColonIsSacred = OldVal;
  241. }
  242. ~ColonProtectionRAIIObject() {
  243. restore();
  244. }
  245. };
  246. /// \brief RAII object that makes '>' behave either as an operator
  247. /// or as the closing angle bracket for a template argument list.
  248. class GreaterThanIsOperatorScope {
  249. bool &GreaterThanIsOperator;
  250. bool OldGreaterThanIsOperator;
  251. public:
  252. GreaterThanIsOperatorScope(bool &GTIO, bool Val)
  253. : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
  254. GreaterThanIsOperator = Val;
  255. }
  256. ~GreaterThanIsOperatorScope() {
  257. GreaterThanIsOperator = OldGreaterThanIsOperator;
  258. }
  259. };
  260. class InMessageExpressionRAIIObject {
  261. bool &InMessageExpression;
  262. bool OldValue;
  263. public:
  264. InMessageExpressionRAIIObject(Parser &P, bool Value)
  265. : InMessageExpression(P.InMessageExpression),
  266. OldValue(P.InMessageExpression) {
  267. InMessageExpression = Value;
  268. }
  269. ~InMessageExpressionRAIIObject() {
  270. InMessageExpression = OldValue;
  271. }
  272. };
  273. /// \brief RAII object that makes sure paren/bracket/brace count is correct
  274. /// after declaration/statement parsing, even when there's a parsing error.
  275. class ParenBraceBracketBalancer {
  276. Parser &P;
  277. unsigned short ParenCount, BracketCount, BraceCount;
  278. public:
  279. ParenBraceBracketBalancer(Parser &p)
  280. : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
  281. BraceCount(p.BraceCount) { }
  282. ~ParenBraceBracketBalancer() {
  283. P.ParenCount = ParenCount;
  284. P.BracketCount = BracketCount;
  285. P.BraceCount = BraceCount;
  286. }
  287. };
  288. class PoisonSEHIdentifiersRAIIObject {
  289. PoisonIdentifierRAIIObject Ident_AbnormalTermination;
  290. PoisonIdentifierRAIIObject Ident_GetExceptionCode;
  291. PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
  292. PoisonIdentifierRAIIObject Ident__abnormal_termination;
  293. PoisonIdentifierRAIIObject Ident__exception_code;
  294. PoisonIdentifierRAIIObject Ident__exception_info;
  295. PoisonIdentifierRAIIObject Ident___abnormal_termination;
  296. PoisonIdentifierRAIIObject Ident___exception_code;
  297. PoisonIdentifierRAIIObject Ident___exception_info;
  298. public:
  299. PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
  300. : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
  301. Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
  302. Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
  303. Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
  304. Ident__exception_code(Self.Ident__exception_code, NewValue),
  305. Ident__exception_info(Self.Ident__exception_info, NewValue),
  306. Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
  307. Ident___exception_code(Self.Ident___exception_code, NewValue),
  308. Ident___exception_info(Self.Ident___exception_info, NewValue) {
  309. }
  310. };
  311. /// \brief RAII class that helps handle the parsing of an open/close delimiter
  312. /// pair, such as braces { ... } or parentheses ( ... ).
  313. class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
  314. Parser& P;
  315. tok::TokenKind Kind, Close, FinalToken;
  316. SourceLocation (Parser::*Consumer)();
  317. SourceLocation LOpen, LClose;
  318. unsigned short &getDepth() {
  319. switch (Kind) {
  320. case tok::l_brace: return P.BraceCount;
  321. case tok::l_square: return P.BracketCount;
  322. case tok::l_paren: return P.ParenCount;
  323. default: llvm_unreachable("Wrong token kind");
  324. }
  325. }
  326. enum { MaxDepth = 256 };
  327. bool diagnoseOverflow();
  328. bool diagnoseMissingClose();
  329. public:
  330. BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
  331. tok::TokenKind FinalToken = tok::semi)
  332. : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
  333. P(p), Kind(k), FinalToken(FinalToken)
  334. {
  335. switch (Kind) {
  336. default: llvm_unreachable("Unexpected balanced token");
  337. case tok::l_brace:
  338. Close = tok::r_brace;
  339. Consumer = &Parser::ConsumeBrace;
  340. break;
  341. case tok::l_paren:
  342. Close = tok::r_paren;
  343. Consumer = &Parser::ConsumeParen;
  344. break;
  345. case tok::l_square:
  346. Close = tok::r_square;
  347. Consumer = &Parser::ConsumeBracket;
  348. break;
  349. }
  350. }
  351. SourceLocation getOpenLocation() const { return LOpen; }
  352. SourceLocation getCloseLocation() const { return LClose; }
  353. SourceRange getRange() const { return SourceRange(LOpen, LClose); }
  354. bool consumeOpen() {
  355. if (!P.Tok.is(Kind))
  356. return true;
  357. if (getDepth() < P.getLangOpts().BracketDepth) {
  358. LOpen = (P.*Consumer)();
  359. return false;
  360. }
  361. return diagnoseOverflow();
  362. }
  363. bool expectAndConsume(unsigned DiagID = diag::err_expected,
  364. const char *Msg = "",
  365. tok::TokenKind SkipToTok = tok::unknown);
  366. bool consumeClose() {
  367. if (P.Tok.is(Close)) {
  368. LClose = (P.*Consumer)();
  369. return false;
  370. } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
  371. SourceLocation SemiLoc = P.ConsumeToken();
  372. P.Diag(SemiLoc, diag::err_unexpected_semi)
  373. << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
  374. LClose = (P.*Consumer)();
  375. return false;
  376. }
  377. return diagnoseMissingClose();
  378. }
  379. void skipToEnd();
  380. };
  381. } // end namespace clang
  382. #endif