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