RAIIObjectsForParser.h 15 KB

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