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 >IO, 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