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