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