clang  19.0.0git
RAIIObjectsForParser.h
Go to the documentation of this file.
1 //===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- 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 // This file defines and implements the some simple RAII objects that are used
10 // by the parser to manage bits in recursion.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
15 #define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
16 
18 #include "clang/Parse/Parser.h"
21 #include "clang/Sema/Sema.h"
22 
23 namespace clang {
24  // TODO: move ParsingClassDefinition here.
25  // TODO: move TentativeParsingAction here.
26 
27  /// A RAII object used to temporarily suppress access-like
28  /// checking. Access-like checks are those associated with
29  /// controlling the use of a declaration, like C++ access control
30  /// errors and deprecation warnings. They are contextually
31  /// dependent, in that they can only be resolved with full
32  /// information about what's being declared. They are also
33  /// suppressed in certain contexts, like the template arguments of
34  /// an explicit instantiation. However, those suppression contexts
35  /// cannot necessarily be fully determined in advance; for
36  /// example, something starting like this:
37  /// template <> class std::vector<A::PrivateType>
38  /// might be the entirety of an explicit instantiation:
39  /// template <> class std::vector<A::PrivateType>;
40  /// or just an elaborated type specifier:
41  /// template <> class std::vector<A::PrivateType> make_vector<>();
42  /// Therefore this class collects all the diagnostics and permits
43  /// them to be re-delayed in a new context.
45  Sema &S;
46  sema::DelayedDiagnosticPool DiagnosticPool;
48  bool Active;
49 
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  }
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 
68  void done() {
69  assert(Active && "trying to end an inactive suppression");
70  S.PopParsingDeclaration(State, nullptr);
71  Active = false;
72  }
73 
74  void redelay() {
75  assert(!Active && "redelaying without having ended first");
76  if (!DiagnosticPool.pool_empty())
77  S.redelayDiagnostics(DiagnosticPool);
78  assert(DiagnosticPool.pool_empty());
79  }
80 
82  if (Active) done();
83  }
84  };
85 
86  /// RAII object used to inform the actions that we're
87  /// currently parsing a declaration. This is active when parsing a
88  /// variable's initializer, but not when parsing the body of a
89  /// class or function definition.
91  Sema &Actions;
92  sema::DelayedDiagnosticPool DiagnosticPool;
94  bool Popped;
95 
97  void operator=(const ParsingDeclRAIIObject &) = delete;
98 
99  public:
102  : Actions(P.getActions()), DiagnosticPool(nullptr) {
103  push();
104  }
105 
106  /// Creates a RAII object whose pool is optionally parented by another.
108  const sema::DelayedDiagnosticPool *parentPool)
109  : Actions(P.getActions()), DiagnosticPool(parentPool) {
110  push();
111  }
112 
113  /// Creates a RAII object and, optionally, initialize its
114  /// diagnostics pool by stealing the diagnostics from another
115  /// RAII object (which is assumed to be the current top pool).
117  : Actions(P.getActions()),
118  DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
119  if (other) {
120  DiagnosticPool.steal(other->DiagnosticPool);
121  other->abort();
122  }
123  push();
124  }
125 
127  abort();
128  }
129 
131  return DiagnosticPool;
132  }
134  return DiagnosticPool;
135  }
136 
137  /// Resets the RAII object for a new declaration.
138  void reset() {
139  abort();
140  push();
141  }
142 
143  /// Signals that the context was completed without an appropriate
144  /// declaration being parsed.
145  void abort() {
146  pop(nullptr);
147  }
148 
149  void complete(Decl *D) {
150  assert(!Popped && "ParsingDeclaration has already been popped!");
151  pop(D);
152  }
153 
154  /// Unregister this object from Sema, but remember all the
155  /// diagnostics that were emitted into it.
157  pop(nullptr);
158  }
159 
160  private:
161  void push() {
162  State = Actions.PushParsingDeclaration(DiagnosticPool);
163  Popped = false;
164  }
165 
166  void pop(Decl *D) {
167  if (!Popped) {
168  Actions.PopParsingDeclaration(State, D);
169  Popped = true;
170  }
171  }
172  };
173 
174  /// A class for parsing a DeclSpec.
175  class ParsingDeclSpec : public DeclSpec {
176  ParsingDeclRAIIObject ParsingRAII;
177 
178  public:
180  : DeclSpec(P.getAttrFactory()),
181  ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
183  : DeclSpec(P.getAttrFactory()),
184  ParsingRAII(P, RAII) {}
185 
187  return ParsingRAII.getDelayedDiagnosticPool();
188  }
189 
190  void complete(Decl *D) {
191  ParsingRAII.complete(D);
192  }
193 
194  void abort() {
195  ParsingRAII.abort();
196  }
197  };
198 
199  /// A class for parsing a declarator.
200  class ParsingDeclarator : public Declarator {
201  ParsingDeclRAIIObject ParsingRAII;
202 
203  public:
205  const ParsedAttributes &DeclarationAttrs,
207  : Declarator(DS, DeclarationAttrs, C),
208  ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
209 
210  const ParsingDeclSpec &getDeclSpec() const {
211  return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
212  }
213 
215  return const_cast<ParsingDeclSpec&>(getDeclSpec());
216  }
217 
218  void clear() {
220  ParsingRAII.reset();
221  }
222 
223  void complete(Decl *D) {
224  ParsingRAII.complete(D);
225  }
226  };
227 
228  /// A class for parsing a field declarator.
230  ParsingDeclRAIIObject ParsingRAII;
231 
232  public:
234  const ParsedAttributes &DeclarationAttrs)
235  : FieldDeclarator(DS, DeclarationAttrs),
236  ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
237 
238  const ParsingDeclSpec &getDeclSpec() const {
239  return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
240  }
241 
243  return const_cast<ParsingDeclSpec&>(getDeclSpec());
244  }
245 
246  void complete(Decl *D) {
247  ParsingRAII.complete(D);
248  }
249  };
250 
251  /// ExtensionRAIIObject - This saves the state of extension warnings when
252  /// constructed and disables them. When destructed, it restores them back to
253  /// the way they used to be. This is used to handle __extension__ in the
254  /// parser.
256  ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
257  void operator=(const ExtensionRAIIObject &) = delete;
258 
259  DiagnosticsEngine &Diags;
260  public:
261  ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
263  }
264 
267  }
268  };
269 
270  /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
271  /// restores it when destroyed. This says that "foo:" should not be
272  /// considered a possible typo for "foo::" for error recovery purposes.
274  Parser &P;
275  bool OldVal;
276  public:
278  : P(p), OldVal(P.ColonIsSacred) {
279  P.ColonIsSacred = Value;
280  }
281 
282  /// restore - This can be used to restore the state early, before the dtor
283  /// is run.
284  void restore() {
285  P.ColonIsSacred = OldVal;
286  }
287 
289  restore();
290  }
291  };
292 
293  /// Activates OpenMP parsing mode to preseve OpenMP specific annotation
294  /// tokens.
296  Parser &P;
297  bool OldVal;
298 
299  public:
301  : P(P), OldVal(P.OpenMPDirectiveParsing) {
302  P.OpenMPDirectiveParsing = Value;
303  }
304 
305  /// This can be used to restore the state early, before the dtor
306  /// is run.
307  void restore() { P.OpenMPDirectiveParsing = OldVal; }
308 
310  };
311 
312  /// Activates OpenACC parsing mode to preseve OpenACC specific annotation
313  /// tokens.
315  Parser &P;
316  bool OldVal;
317 
318  public:
320  : P(P), OldVal(P.OpenACCDirectiveParsing) {
321  P.OpenACCDirectiveParsing = Value;
322  }
323 
324  /// This can be used to restore the state early, before the dtor
325  /// is run.
326  void restore() { P.OpenACCDirectiveParsing = OldVal; }
327 
329  };
330 
331  /// RAII object that makes '>' behave either as an operator
332  /// or as the closing angle bracket for a template argument list.
334  bool &GreaterThanIsOperator;
335  bool OldGreaterThanIsOperator;
336  public:
337  GreaterThanIsOperatorScope(bool &GTIO, bool Val)
338  : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
339  GreaterThanIsOperator = Val;
340  }
341 
343  GreaterThanIsOperator = OldGreaterThanIsOperator;
344  }
345  };
346 
348  bool &InMessageExpression;
349  bool OldValue;
350 
351  public:
353  : InMessageExpression(P.InMessageExpression),
354  OldValue(P.InMessageExpression) {
355  InMessageExpression = Value;
356  }
357 
359  InMessageExpression = OldValue;
360  }
361  };
362 
364  Sema::OffsetOfKind &OffsetOfState;
365  Sema::OffsetOfKind OldValue;
366 
367  public:
369  : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
370  OffsetOfState = Value;
371  }
372 
373  ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
374  };
375 
376  /// RAII object that makes sure paren/bracket/brace count is correct
377  /// after declaration/statement parsing, even when there's a parsing error.
379  Parser &P;
380  unsigned short ParenCount, BracketCount, BraceCount;
381  public:
383  : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
384  BraceCount(p.BraceCount) { }
385 
387  P.AngleBrackets.clear(P);
388  P.ParenCount = ParenCount;
389  P.BracketCount = BracketCount;
390  P.BraceCount = BraceCount;
391  }
392  };
393 
395  PoisonIdentifierRAIIObject Ident_AbnormalTermination;
396  PoisonIdentifierRAIIObject Ident_GetExceptionCode;
397  PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
398  PoisonIdentifierRAIIObject Ident__abnormal_termination;
399  PoisonIdentifierRAIIObject Ident__exception_code;
400  PoisonIdentifierRAIIObject Ident__exception_info;
401  PoisonIdentifierRAIIObject Ident___abnormal_termination;
402  PoisonIdentifierRAIIObject Ident___exception_code;
403  PoisonIdentifierRAIIObject Ident___exception_info;
404  public:
406  : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
407  Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
408  Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
409  Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
410  Ident__exception_code(Self.Ident__exception_code, NewValue),
411  Ident__exception_info(Self.Ident__exception_info, NewValue),
412  Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
413  Ident___exception_code(Self.Ident___exception_code, NewValue),
414  Ident___exception_info(Self.Ident___exception_info, NewValue) {
415  }
416  };
417 
418  /// RAII class that helps handle the parsing of an open/close delimiter
419  /// pair, such as braces { ... } or parentheses ( ... ).
421  Parser& P;
422  tok::TokenKind Kind, Close, FinalToken;
423  SourceLocation (Parser::*Consumer)();
424  SourceLocation LOpen, LClose;
425 
426  unsigned short &getDepth() {
427  switch (Kind) {
428  case tok::l_brace: return P.BraceCount;
429  case tok::l_square: return P.BracketCount;
430  case tok::l_paren: return P.ParenCount;
431  default: llvm_unreachable("Wrong token kind");
432  }
433  }
434 
435  bool diagnoseOverflow();
436  bool diagnoseMissingClose();
437 
438  public:
440  tok::TokenKind FinalToken = tok::semi)
441  : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
442  P(p), Kind(k), FinalToken(FinalToken)
443  {
444  switch (Kind) {
445  default: llvm_unreachable("Unexpected balanced token");
446  case tok::l_brace:
447  Close = tok::r_brace;
448  Consumer = &Parser::ConsumeBrace;
449  break;
450  case tok::l_paren:
451  Close = tok::r_paren;
452  Consumer = &Parser::ConsumeParen;
453  break;
454 
455  case tok::l_square:
456  Close = tok::r_square;
457  Consumer = &Parser::ConsumeBracket;
458  break;
459  }
460  }
461 
462  SourceLocation getOpenLocation() const { return LOpen; }
463  SourceLocation getCloseLocation() const { return LClose; }
464  SourceRange getRange() const { return SourceRange(LOpen, LClose); }
465 
466  bool consumeOpen() {
467  if (!P.Tok.is(Kind))
468  return true;
469 
470  if (getDepth() < P.getLangOpts().BracketDepth) {
471  LOpen = (P.*Consumer)();
472  return false;
473  }
474 
475  return diagnoseOverflow();
476  }
477 
478  bool expectAndConsume(unsigned DiagID = diag::err_expected,
479  const char *Msg = "",
480  tok::TokenKind SkipToTok = tok::unknown);
481  bool consumeClose() {
482  if (P.Tok.is(Close)) {
483  LClose = (P.*Consumer)();
484  return false;
485  } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
486  SourceLocation SemiLoc = P.ConsumeToken();
487  P.Diag(SemiLoc, diag::err_unexpected_semi)
488  << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
489  LClose = (P.*Consumer)();
490  return false;
491  }
492 
493  return diagnoseMissingClose();
494  }
495  void skipToEnd();
496  };
497 } // end namespace clang
498 
499 #endif
StringRef P
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
Definition: Parser.cpp:2774
SourceLocation getOpenLocation() const
BalancedDelimiterTracker(Parser &p, tok::TokenKind k, tok::TokenKind FinalToken=tok::semi)
SourceLocation getCloseLocation() const
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.
void restore()
restore - This can be used to restore the state early, before the dtor is run.
ColonProtectionRAIIObject(Parser &p, bool Value=true)
Captures information about "declaration specifiers".
Definition: DeclSpec.h:247
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1900
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:2047
void clear()
Reset the contents of this Declarator.
Definition: DeclSpec.h:2110
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:193
void DecrementAllExtensionsSilenced()
Definition: Diagnostic.h:796
void IncrementAllExtensionsSilenced()
Counter bumped when an extension block is/ encountered.
Definition: Diagnostic.h:795
ExtensionRAIIObject - This saves the state of extension warnings when constructed and disables them.
ExtensionRAIIObject(DiagnosticsEngine &diags)
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:124
RAII object that makes '>' behave either as an operator or as the closing angle bracket for a templat...
GreaterThanIsOperatorScope(bool &GTIO, bool Val)
InMessageExpressionRAIIObject(Parser &P, bool Value)
OffsetOfStateRAIIObject(Parser &P, Sema::OffsetOfKind Value)
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:963
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:58
RAII object used to inform the actions that we're currently parsing a declaration.
ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
Creates a RAII object and, optionally, initialize its diagnostics pool by stealing the diagnostics fr...
ParsingDeclRAIIObject(Parser &P, const sema::DelayedDiagnosticPool *parentPool)
Creates a RAII object whose pool is optionally parented by another.
const sema::DelayedDiagnosticPool & getDelayedDiagnosticPool() const
void abort()
Signals that the context was completed without an appropriate declaration being parsed.
void abortAndRemember()
Unregister this object from Sema, but remember all the diagnostics that were emitted into it.
sema::DelayedDiagnosticPool & getDelayedDiagnosticPool()
ParsingDeclRAIIObject(Parser &P, NoParent_t _)
void reset()
Resets the RAII object for a new declaration.
A class for parsing a DeclSpec.
ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
const sema::DelayedDiagnosticPool & getDelayedDiagnosticPool() const
A class for parsing a declarator.
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, const ParsedAttributes &DeclarationAttrs, DeclaratorContext C)
ParsingDeclSpec & getMutableDeclSpec() const
const ParsingDeclSpec & getDeclSpec() const
A class for parsing a field declarator.
const ParsingDeclSpec & getDeclSpec() const
ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS, const ParsedAttributes &DeclarationAttrs)
ParsingDeclSpec & getMutableDeclSpec() const
Activates OpenACC parsing mode to preseve OpenACC specific annotation tokens.
void restore()
This can be used to restore the state early, before the dtor is run.
ParsingOpenACCDirectiveRAII(Parser &P, bool Value=true)
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
void restore()
This can be used to restore the state early, before the dtor is run.
ParsingOpenMPDirectiveRAII(Parser &P, bool Value=true)
An RAII object for [un]poisoning an identifier within a scope.
PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:462
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool)
Definition: Sema.h:985
void PopParsingDeclaration(ParsingDeclState state, Decl *decl)
OffsetOfKind
Definition: Sema.h:3192
Encodes a location in the source.
A trivial tuple used to represent a source range.
A RAII object used to temporarily suppress access-like checking.
void operator=(SuppressAccessChecks &&Other)=delete
SuppressAccessChecks(Parser &P, bool activate=true)
Begin suppressing access-like checks.
SuppressAccessChecks(SuppressAccessChecks &&Other)
A collection of diagnostics which were delayed.
void steal(DelayedDiagnosticPool &pool)
Steal the diagnostics from the given pool.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
The JSON file list parser is used to communicate input to InstallAPI.
DeclaratorContext
Definition: DeclSpec.h:1850
@ Other
Other implicit parameter.
Definition: Format.h:5433
#define true
Definition: stdbool.h:25
This little struct is used to capture information about structure field declarators,...
Definition: DeclSpec.h:2770