clang  6.0.0svn
RAIIObjectsForParser.h
Go to the documentation of this file.
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 
15 #ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
16 #define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
17 
19 #include "clang/Parse/Parser.h"
22 #include "clang/Sema/Sema.h"
23 
24 namespace clang {
25  // TODO: move ParsingClassDefinition here.
26  // TODO: move TentativeParsingAction here.
27 
28  /// \brief 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.
46  Sema &S;
47  sema::DelayedDiagnosticPool DiagnosticPool;
49  bool Active;
50 
51  public:
52  /// Begin suppressing access-like checks
53  SuppressAccessChecks(Parser &P, bool activate = true)
54  : S(P.getActions()), DiagnosticPool(nullptr) {
55  if (activate) {
56  State = S.PushParsingDeclaration(DiagnosticPool);
57  Active = true;
58  } else {
59  Active = false;
60  }
61  }
63  : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
64  State(Other.State), Active(Other.Active) {
65  Other.Active = false;
66  }
67  void operator=(SuppressAccessChecks &&Other) = delete;
68 
69  void done() {
70  assert(Active && "trying to end an inactive suppression");
71  S.PopParsingDeclaration(State, nullptr);
72  Active = false;
73  }
74 
75  void redelay() {
76  assert(!Active && "redelaying without having ended first");
77  if (!DiagnosticPool.pool_empty())
78  S.redelayDiagnostics(DiagnosticPool);
79  assert(DiagnosticPool.pool_empty());
80  }
81 
83  if (Active) done();
84  }
85  };
86 
87  /// \brief RAII object used to inform the actions that we're
88  /// currently parsing a declaration. This is active when parsing a
89  /// variable's initializer, but not when parsing the body of a
90  /// class or function definition.
92  Sema &Actions;
93  sema::DelayedDiagnosticPool DiagnosticPool;
95  bool Popped;
96 
98  void operator=(const ParsingDeclRAIIObject &) = delete;
99 
100  public:
101  enum NoParent_t { NoParent };
103  : Actions(P.getActions()), DiagnosticPool(nullptr) {
104  push();
105  }
106 
107  /// Creates a RAII object whose pool is optionally parented by another.
109  const sema::DelayedDiagnosticPool *parentPool)
110  : Actions(P.getActions()), DiagnosticPool(parentPool) {
111  push();
112  }
113 
114  /// Creates a RAII object and, optionally, initialize its
115  /// diagnostics pool by stealing the diagnostics from another
116  /// RAII object (which is assumed to be the current top pool).
118  : Actions(P.getActions()),
119  DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
120  if (other) {
121  DiagnosticPool.steal(other->DiagnosticPool);
122  other->abort();
123  }
124  push();
125  }
126 
128  abort();
129  }
130 
132  return DiagnosticPool;
133  }
135  return DiagnosticPool;
136  }
137 
138  /// Resets the RAII object for a new declaration.
139  void reset() {
140  abort();
141  push();
142  }
143 
144  /// Signals that the context was completed without an appropriate
145  /// declaration being parsed.
146  void abort() {
147  pop(nullptr);
148  }
149 
150  void complete(Decl *D) {
151  assert(!Popped && "ParsingDeclaration has already been popped!");
152  pop(D);
153  }
154 
155  /// Unregister this object from Sema, but remember all the
156  /// diagnostics that were emitted into it.
158  pop(nullptr);
159  }
160 
161  private:
162  void push() {
163  State = Actions.PushParsingDeclaration(DiagnosticPool);
164  Popped = false;
165  }
166 
167  void pop(Decl *D) {
168  if (!Popped) {
169  Actions.PopParsingDeclaration(State, D);
170  Popped = true;
171  }
172  }
173  };
174 
175  /// A class for parsing a DeclSpec.
176  class ParsingDeclSpec : public DeclSpec {
177  ParsingDeclRAIIObject ParsingRAII;
178 
179  public:
181  : DeclSpec(P.getAttrFactory()),
182  ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
184  : DeclSpec(P.getAttrFactory()),
185  ParsingRAII(P, RAII) {}
186 
188  return ParsingRAII.getDelayedDiagnosticPool();
189  }
190 
191  void complete(Decl *D) {
192  ParsingRAII.complete(D);
193  }
194 
195  void abort() {
196  ParsingRAII.abort();
197  }
198  };
199 
200  /// A class for parsing a declarator.
201  class ParsingDeclarator : public Declarator {
202  ParsingDeclRAIIObject ParsingRAII;
203 
204  public:
206  : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
207  }
208 
209  const ParsingDeclSpec &getDeclSpec() const {
210  return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
211  }
212 
214  return const_cast<ParsingDeclSpec&>(getDeclSpec());
215  }
216 
217  void clear() {
219  ParsingRAII.reset();
220  }
221 
222  void complete(Decl *D) {
223  ParsingRAII.complete(D);
224  }
225  };
226 
227  /// A class for parsing a field declarator.
229  ParsingDeclRAIIObject ParsingRAII;
230 
231  public:
233  : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
234  }
235 
236  const ParsingDeclSpec &getDeclSpec() const {
237  return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
238  }
239 
241  return const_cast<ParsingDeclSpec&>(getDeclSpec());
242  }
243 
244  void complete(Decl *D) {
245  ParsingRAII.complete(D);
246  }
247  };
248 
249  /// ExtensionRAIIObject - This saves the state of extension warnings when
250  /// constructed and disables them. When destructed, it restores them back to
251  /// the way they used to be. This is used to handle __extension__ in the
252  /// parser.
254  ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
255  void operator=(const ExtensionRAIIObject &) = delete;
256 
257  DiagnosticsEngine &Diags;
258  public:
259  ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
261  }
262 
265  }
266  };
267 
268  /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
269  /// restores it when destroyed. This says that "foo:" should not be
270  /// considered a possible typo for "foo::" for error recovery purposes.
272  Parser &P;
273  bool OldVal;
274  public:
276  : P(p), OldVal(P.ColonIsSacred) {
277  P.ColonIsSacred = Value;
278  }
279 
280  /// restore - This can be used to restore the state early, before the dtor
281  /// is run.
282  void restore() {
283  P.ColonIsSacred = OldVal;
284  }
285 
287  restore();
288  }
289  };
290 
291  /// \brief RAII object that makes '>' behave either as an operator
292  /// or as the closing angle bracket for a template argument list.
294  bool &GreaterThanIsOperator;
295  bool OldGreaterThanIsOperator;
296  public:
297  GreaterThanIsOperatorScope(bool &GTIO, bool Val)
298  : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
299  GreaterThanIsOperator = Val;
300  }
301 
303  GreaterThanIsOperator = OldGreaterThanIsOperator;
304  }
305  };
306 
308  bool &InMessageExpression;
309  bool OldValue;
310 
311  public:
313  : InMessageExpression(P.InMessageExpression),
314  OldValue(P.InMessageExpression) {
315  InMessageExpression = Value;
316  }
317 
319  InMessageExpression = OldValue;
320  }
321  };
322 
323  /// \brief RAII object that makes sure paren/bracket/brace count is correct
324  /// after declaration/statement parsing, even when there's a parsing error.
326  Parser &P;
327  unsigned short ParenCount, BracketCount, BraceCount;
328  public:
330  : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
331  BraceCount(p.BraceCount) { }
332 
334  P.ParenCount = ParenCount;
335  P.BracketCount = BracketCount;
336  P.BraceCount = BraceCount;
337  }
338  };
339 
341  PoisonIdentifierRAIIObject Ident_AbnormalTermination;
342  PoisonIdentifierRAIIObject Ident_GetExceptionCode;
343  PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
344  PoisonIdentifierRAIIObject Ident__abnormal_termination;
345  PoisonIdentifierRAIIObject Ident__exception_code;
346  PoisonIdentifierRAIIObject Ident__exception_info;
347  PoisonIdentifierRAIIObject Ident___abnormal_termination;
348  PoisonIdentifierRAIIObject Ident___exception_code;
349  PoisonIdentifierRAIIObject Ident___exception_info;
350  public:
352  : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
353  Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
354  Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
355  Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
356  Ident__exception_code(Self.Ident__exception_code, NewValue),
357  Ident__exception_info(Self.Ident__exception_info, NewValue),
358  Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
359  Ident___exception_code(Self.Ident___exception_code, NewValue),
360  Ident___exception_info(Self.Ident___exception_info, NewValue) {
361  }
362  };
363 
364  /// \brief RAII class that helps handle the parsing of an open/close delimiter
365  /// pair, such as braces { ... } or parentheses ( ... ).
367  Parser& P;
368  tok::TokenKind Kind, Close, FinalToken;
369  SourceLocation (Parser::*Consumer)();
370  SourceLocation LOpen, LClose;
371 
372  unsigned short &getDepth() {
373  switch (Kind) {
374  case tok::l_brace: return P.BraceCount;
375  case tok::l_square: return P.BracketCount;
376  case tok::l_paren: return P.ParenCount;
377  default: llvm_unreachable("Wrong token kind");
378  }
379  }
380 
381  enum { MaxDepth = 256 };
382 
383  bool diagnoseOverflow();
384  bool diagnoseMissingClose();
385 
386  public:
388  tok::TokenKind FinalToken = tok::semi)
389  : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
390  P(p), Kind(k), FinalToken(FinalToken)
391  {
392  switch (Kind) {
393  default: llvm_unreachable("Unexpected balanced token");
394  case tok::l_brace:
395  Close = tok::r_brace;
396  Consumer = &Parser::ConsumeBrace;
397  break;
398  case tok::l_paren:
399  Close = tok::r_paren;
400  Consumer = &Parser::ConsumeParen;
401  break;
402 
403  case tok::l_square:
404  Close = tok::r_square;
405  Consumer = &Parser::ConsumeBracket;
406  break;
407  }
408  }
409 
410  SourceLocation getOpenLocation() const { return LOpen; }
411  SourceLocation getCloseLocation() const { return LClose; }
412  SourceRange getRange() const { return SourceRange(LOpen, LClose); }
413 
414  bool consumeOpen() {
415  if (!P.Tok.is(Kind))
416  return true;
417 
418  if (getDepth() < P.getLangOpts().BracketDepth) {
419  LOpen = (P.*Consumer)();
420  return false;
421  }
422 
423  return diagnoseOverflow();
424  }
425 
426  bool expectAndConsume(unsigned DiagID = diag::err_expected,
427  const char *Msg = "",
428  tok::TokenKind SkipToTok = tok::unknown);
429  bool consumeClose() {
430  if (P.Tok.is(Close)) {
431  LClose = (P.*Consumer)();
432  return false;
433  } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
434  SourceLocation SemiLoc = P.ConsumeToken();
435  P.Diag(SemiLoc, diag::err_unexpected_semi)
436  << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
437  LClose = (P.*Consumer)();
438  return false;
439  }
440 
441  return diagnoseMissingClose();
442  }
443  void skipToEnd();
444  };
445 
446  /// \brief RAIIObject to destroy the contents of a SmallVector of
447  /// TemplateIdAnnotation pointers and clear the vector.
450 
451  public:
454  : Container(Container) {}
455 
458  Container.begin(),
459  E = Container.end();
460  I != E; ++I)
461  (*I)->Destroy();
462  Container.clear();
463  }
464  };
465 } // end namespace clang
466 
467 #endif
DestroyTemplateIdAnnotationsRAIIObj(SmallVectorImpl< TemplateIdAnnotation *> &Container)
void restore()
restore - This can be used to restore the state early, before the dtor is run.
void clear()
Reset the contents of this Declarator.
Definition: DeclSpec.h:1899
SuppressAccessChecks(SuppressAccessChecks &&Other)
ColonProtectionRAIIObject(Parser &p, bool Value=true)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
Definition: Token.h:95
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
RAII object used to inform the actions that we&#39;re currently parsing a declaration.
A RAII object used to temporarily suppress access-like checking.
StringRef P
SourceLocation getCloseLocation() const
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:57
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1720
RAIIObject to destroy the contents of a SmallVector of TemplateIdAnnotation pointers and clear the ve...
ExtensionRAIIObject(DiagnosticsEngine &diags)
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Definition: Parser.h:613
void operator=(SuppressAccessChecks &&Other)=delete
LineState State
void IncrementAllExtensionsSilenced()
Counter bumped when an extension block is/ encountered.
Definition: Diagnostic.h:611
Definition: Format.h:1900
const sema::DelayedDiagnosticPool & getDelayedDiagnosticPool() const
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool)
Definition: Sema.h:3929
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool)
Given a set of delayed diagnostics, re-emit them as if they had been delayed in the current context i...
This little struct is used to capture information about structure field declarators, which is basically just a bitfield size.
Definition: DeclSpec.h:2450
void reset()
Resets the RAII object for a new declaration.
void abortAndRemember()
Unregister this object from Sema, but remember all the diagnostics that were emitted into it...
void PopParsingDeclaration(ParsingDeclState state, Decl *decl)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
ParsingDeclSpec & getMutableDeclSpec() const
void steal(DelayedDiagnosticPool &pool)
Steal the diagnostics from the given pool.
const ParsingDeclSpec & getDeclSpec() const
GreaterThanIsOperatorScope(bool &GTIO, bool Val)
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:274
A class for parsing a declarator.
ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
ParsingDeclRAIIObject(Parser &P, const sema::DelayedDiagnosticPool *parentPool)
Creates a RAII object whose pool is optionally parented by another.
ParsingDeclRAIIObject(Parser &P, NoParent_t _)
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
Creates a RAII object and, optionally, initialize its diagnostics pool by stealing the diagnostics fr...
SuppressAccessChecks(Parser &P, bool activate=true)
Begin suppressing access-like checks.
A class for parsing a field declarator.
SourceLocation getOpenLocation() const
RAII object that makes &#39;>&#39; behave either as an operator or as the closing angle bracket for a templat...
const LangOptions & getLangOpts() const
Definition: Parser.h:271
A class for parsing a DeclSpec.
Kind
Encodes a location in the source.
const ParsingDeclSpec & getDeclSpec() const
ExtensionRAIIObject - This saves the state of extension warnings when constructed and disables them...
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
InMessageExpressionRAIIObject(Parser &P, bool Value)
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
Dataflow Directional Tag Classes.
BalancedDelimiterTracker(Parser &p, tok::TokenKind k, tok::TokenKind FinalToken=tok::semi)
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:116
const sema::DelayedDiagnosticPool & getDelayedDiagnosticPool() const
sema::DelayedDiagnosticPool & getDelayedDiagnosticPool()
void abort()
Signals that the context was completed without an appropriate declaration being parsed.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition: Parser.cpp:72
ParsingDeclSpec & getMutableDeclSpec() const
void DecrementAllExtensionsSilenced()
Definition: Diagnostic.h:612
Captures information about "declaration specifiers".
Definition: DeclSpec.h:228
SourceLocation ConsumeToken()
ConsumeToken - Consume the current &#39;peek token&#39; and lex the next one.
Definition: Parser.h:316
PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:1836
A collection of diagnostics which were delayed.
#define true
Definition: stdbool.h:32
A trivial tuple used to represent a source range.
An RAII object for [un]poisoning an identifier within a scope.