RAIIObjectsForParser.h revision 9257664568bf375b7790131a84d9a4fa30a5b7e3
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_PARSE_RAII_OBJECTS_FOR_PARSER_H
16#define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
17
18#include "clang/Parse/ParseDiagnostic.h"
19#include "clang/Parse/Parser.h"
20#include "clang/Sema/DelayedDiagnostic.h"
21#include "clang/Sema/Sema.h"
22
23namespace clang {
24  // TODO: move ParsingClassDefinition here.
25  // TODO: move TentativeParsingAction here.
26
27  /// \brief RAII object used to inform the actions that we're
28  /// currently parsing a declaration.  This is active when parsing a
29  /// variable's initializer, but not when parsing the body of a
30  /// class or function definition.
31  class ParsingDeclRAIIObject {
32    Sema &Actions;
33    sema::DelayedDiagnosticPool DiagnosticPool;
34    Sema::ParsingDeclState State;
35    bool Popped;
36
37    // Do not implement.
38    ParsingDeclRAIIObject(const ParsingDeclRAIIObject &other);
39    ParsingDeclRAIIObject &operator=(const ParsingDeclRAIIObject &other);
40
41  public:
42    enum NoParent_t { NoParent };
43    ParsingDeclRAIIObject(Parser &P, NoParent_t _)
44        : Actions(P.getActions()), DiagnosticPool(NULL) {
45      push();
46    }
47
48    /// Creates a RAII object whose pool is optionally parented by another.
49    ParsingDeclRAIIObject(Parser &P,
50                          const sema::DelayedDiagnosticPool *parentPool)
51        : Actions(P.getActions()), DiagnosticPool(parentPool) {
52      push();
53    }
54
55    /// Creates a RAII object and, optionally, initialize its
56    /// diagnostics pool by stealing the diagnostics from another
57    /// RAII object (which is assumed to be the current top pool).
58    ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
59        : Actions(P.getActions()),
60          DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) {
61      if (other) {
62        DiagnosticPool.steal(other->DiagnosticPool);
63        other->abort();
64      }
65      push();
66    }
67
68    ~ParsingDeclRAIIObject() {
69      abort();
70    }
71
72    sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
73      return DiagnosticPool;
74    }
75    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
76      return DiagnosticPool;
77    }
78
79    /// Resets the RAII object for a new declaration.
80    void reset() {
81      abort();
82      push();
83    }
84
85    /// Signals that the context was completed without an appropriate
86    /// declaration being parsed.
87    void abort() {
88      pop(0);
89    }
90
91    void complete(Decl *D) {
92      assert(!Popped && "ParsingDeclaration has already been popped!");
93      pop(D);
94    }
95
96  private:
97    void steal(ParsingDeclRAIIObject &Other) {
98      DiagnosticPool.steal(Other.DiagnosticPool);
99      State = Other.State;
100      Popped = Other.Popped;
101      Other.Popped = true;
102    }
103
104    void push() {
105      State = Actions.PushParsingDeclaration(DiagnosticPool);
106      Popped = false;
107    }
108
109    void pop(Decl *D) {
110      if (!Popped) {
111        Actions.PopParsingDeclaration(State, D);
112        Popped = true;
113      }
114    }
115  };
116
117  /// A class for parsing a DeclSpec.
118  class ParsingDeclSpec : public DeclSpec {
119    ParsingDeclRAIIObject ParsingRAII;
120
121  public:
122    ParsingDeclSpec(Parser &P)
123      : DeclSpec(P.getAttrFactory()),
124        ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
125    ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
126      : DeclSpec(P.getAttrFactory()),
127        ParsingRAII(P, RAII) {}
128
129    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
130      return ParsingRAII.getDelayedDiagnosticPool();
131    }
132
133    void complete(Decl *D) {
134      ParsingRAII.complete(D);
135    }
136
137    void abort() {
138      ParsingRAII.abort();
139    }
140  };
141
142  /// A class for parsing a declarator.
143  class ParsingDeclarator : public Declarator {
144    ParsingDeclRAIIObject ParsingRAII;
145
146  public:
147    ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
148      : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
149    }
150
151    const ParsingDeclSpec &getDeclSpec() const {
152      return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
153    }
154
155    ParsingDeclSpec &getMutableDeclSpec() const {
156      return const_cast<ParsingDeclSpec&>(getDeclSpec());
157    }
158
159    void clear() {
160      Declarator::clear();
161      ParsingRAII.reset();
162    }
163
164    void complete(Decl *D) {
165      ParsingRAII.complete(D);
166    }
167  };
168
169  /// ExtensionRAIIObject - This saves the state of extension warnings when
170  /// constructed and disables them.  When destructed, it restores them back to
171  /// the way they used to be.  This is used to handle __extension__ in the
172  /// parser.
173  class ExtensionRAIIObject {
174    void operator=(const ExtensionRAIIObject &);     // DO NOT IMPLEMENT
175    ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT
176    DiagnosticsEngine &Diags;
177  public:
178    ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
179      Diags.IncrementAllExtensionsSilenced();
180    }
181
182    ~ExtensionRAIIObject() {
183      Diags.DecrementAllExtensionsSilenced();
184    }
185  };
186
187  /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
188  /// restores it when destroyed.  This says that "foo:" should not be
189  /// considered a possible typo for "foo::" for error recovery purposes.
190  class ColonProtectionRAIIObject {
191    Parser &P;
192    bool OldVal;
193  public:
194    ColonProtectionRAIIObject(Parser &p, bool Value = true)
195      : P(p), OldVal(P.ColonIsSacred) {
196      P.ColonIsSacred = Value;
197    }
198
199    /// restore - This can be used to restore the state early, before the dtor
200    /// is run.
201    void restore() {
202      P.ColonIsSacred = OldVal;
203    }
204
205    ~ColonProtectionRAIIObject() {
206      restore();
207    }
208  };
209
210  /// \brief RAII object that makes '>' behave either as an operator
211  /// or as the closing angle bracket for a template argument list.
212  class GreaterThanIsOperatorScope {
213    bool &GreaterThanIsOperator;
214    bool OldGreaterThanIsOperator;
215  public:
216    GreaterThanIsOperatorScope(bool &GTIO, bool Val)
217    : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
218      GreaterThanIsOperator = Val;
219    }
220
221    ~GreaterThanIsOperatorScope() {
222      GreaterThanIsOperator = OldGreaterThanIsOperator;
223    }
224  };
225
226  class InMessageExpressionRAIIObject {
227    bool &InMessageExpression;
228    bool OldValue;
229
230  public:
231    InMessageExpressionRAIIObject(Parser &P, bool Value)
232      : InMessageExpression(P.InMessageExpression),
233        OldValue(P.InMessageExpression) {
234      InMessageExpression = Value;
235    }
236
237    ~InMessageExpressionRAIIObject() {
238      InMessageExpression = OldValue;
239    }
240  };
241
242  /// \brief RAII object that makes sure paren/bracket/brace count is correct
243  /// after declaration/statement parsing, even when there's a parsing error.
244  class ParenBraceBracketBalancer {
245    Parser &P;
246    unsigned short ParenCount, BracketCount, BraceCount;
247  public:
248    ParenBraceBracketBalancer(Parser &p)
249      : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
250        BraceCount(p.BraceCount) { }
251
252    ~ParenBraceBracketBalancer() {
253      P.ParenCount = ParenCount;
254      P.BracketCount = BracketCount;
255      P.BraceCount = BraceCount;
256    }
257  };
258
259  class PoisonSEHIdentifiersRAIIObject {
260    PoisonIdentifierRAIIObject Ident_AbnormalTermination;
261    PoisonIdentifierRAIIObject Ident_GetExceptionCode;
262    PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
263    PoisonIdentifierRAIIObject Ident__abnormal_termination;
264    PoisonIdentifierRAIIObject Ident__exception_code;
265    PoisonIdentifierRAIIObject Ident__exception_info;
266    PoisonIdentifierRAIIObject Ident___abnormal_termination;
267    PoisonIdentifierRAIIObject Ident___exception_code;
268    PoisonIdentifierRAIIObject Ident___exception_info;
269  public:
270    PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
271      : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
272        Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
273        Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
274        Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
275        Ident__exception_code(Self.Ident__exception_code, NewValue),
276        Ident__exception_info(Self.Ident__exception_info, NewValue),
277        Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
278        Ident___exception_code(Self.Ident___exception_code, NewValue),
279        Ident___exception_info(Self.Ident___exception_info, NewValue) {
280    }
281  };
282
283} // end namespace clang
284
285#endif
286