clang API Documentation
00001 //===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines and implements the some simple RAII objects that are used 00011 // by the parser to manage bits in recursion. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H 00016 #define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H 00017 00018 #include "clang/Parse/ParseDiagnostic.h" 00019 #include "clang/Parse/Parser.h" 00020 #include "clang/Sema/DelayedDiagnostic.h" 00021 #include "clang/Sema/Sema.h" 00022 00023 namespace clang { 00024 // TODO: move ParsingClassDefinition here. 00025 // TODO: move TentativeParsingAction here. 00026 00027 /// \brief A RAII object used to temporarily suppress access-like 00028 /// checking. Access-like checks are those associated with 00029 /// controlling the use of a declaration, like C++ access control 00030 /// errors and deprecation warnings. They are contextually 00031 /// dependent, in that they can only be resolved with full 00032 /// information about what's being declared. They are also 00033 /// suppressed in certain contexts, like the template arguments of 00034 /// an explicit instantiation. However, those suppression contexts 00035 /// cannot necessarily be fully determined in advance; for 00036 /// example, something starting like this: 00037 /// template <> class std::vector<A::PrivateType> 00038 /// might be the entirety of an explicit instantiation: 00039 /// template <> class std::vector<A::PrivateType>; 00040 /// or just an elaborated type specifier: 00041 /// template <> class std::vector<A::PrivateType> make_vector<>(); 00042 /// Therefore this class collects all the diagnostics and permits 00043 /// them to be re-delayed in a new context. 00044 class SuppressAccessChecks { 00045 Sema &S; 00046 sema::DelayedDiagnosticPool DiagnosticPool; 00047 Sema::ParsingDeclState State; 00048 bool Active; 00049 00050 public: 00051 /// Begin suppressing access-like checks 00052 SuppressAccessChecks(Parser &P, bool activate = true) 00053 : S(P.getActions()), DiagnosticPool(NULL) { 00054 if (activate) { 00055 State = S.PushParsingDeclaration(DiagnosticPool); 00056 Active = true; 00057 } else { 00058 Active = false; 00059 } 00060 } 00061 00062 void done() { 00063 assert(Active && "trying to end an inactive suppression"); 00064 S.PopParsingDeclaration(State, NULL); 00065 Active = false; 00066 } 00067 00068 void redelay() { 00069 assert(!Active && "redelaying without having ended first"); 00070 if (!DiagnosticPool.pool_empty()) 00071 S.redelayDiagnostics(DiagnosticPool); 00072 assert(DiagnosticPool.pool_empty()); 00073 } 00074 00075 ~SuppressAccessChecks() { 00076 if (Active) done(); 00077 } 00078 }; 00079 00080 /// \brief RAII object used to inform the actions that we're 00081 /// currently parsing a declaration. This is active when parsing a 00082 /// variable's initializer, but not when parsing the body of a 00083 /// class or function definition. 00084 class ParsingDeclRAIIObject { 00085 Sema &Actions; 00086 sema::DelayedDiagnosticPool DiagnosticPool; 00087 Sema::ParsingDeclState State; 00088 bool Popped; 00089 00090 // Do not implement. 00091 ParsingDeclRAIIObject(const ParsingDeclRAIIObject &other); 00092 ParsingDeclRAIIObject &operator=(const ParsingDeclRAIIObject &other); 00093 00094 public: 00095 enum NoParent_t { NoParent }; 00096 ParsingDeclRAIIObject(Parser &P, NoParent_t _) 00097 : Actions(P.getActions()), DiagnosticPool(NULL) { 00098 push(); 00099 } 00100 00101 /// Creates a RAII object whose pool is optionally parented by another. 00102 ParsingDeclRAIIObject(Parser &P, 00103 const sema::DelayedDiagnosticPool *parentPool) 00104 : Actions(P.getActions()), DiagnosticPool(parentPool) { 00105 push(); 00106 } 00107 00108 /// Creates a RAII object and, optionally, initialize its 00109 /// diagnostics pool by stealing the diagnostics from another 00110 /// RAII object (which is assumed to be the current top pool). 00111 ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other) 00112 : Actions(P.getActions()), 00113 DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) { 00114 if (other) { 00115 DiagnosticPool.steal(other->DiagnosticPool); 00116 other->abort(); 00117 } 00118 push(); 00119 } 00120 00121 ~ParsingDeclRAIIObject() { 00122 abort(); 00123 } 00124 00125 sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() { 00126 return DiagnosticPool; 00127 } 00128 const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { 00129 return DiagnosticPool; 00130 } 00131 00132 /// Resets the RAII object for a new declaration. 00133 void reset() { 00134 abort(); 00135 push(); 00136 } 00137 00138 /// Signals that the context was completed without an appropriate 00139 /// declaration being parsed. 00140 void abort() { 00141 pop(0); 00142 } 00143 00144 void complete(Decl *D) { 00145 assert(!Popped && "ParsingDeclaration has already been popped!"); 00146 pop(D); 00147 } 00148 00149 /// Unregister this object from Sema, but remember all the 00150 /// diagnostics that were emitted into it. 00151 void abortAndRemember() { 00152 pop(0); 00153 } 00154 00155 private: 00156 void push() { 00157 State = Actions.PushParsingDeclaration(DiagnosticPool); 00158 Popped = false; 00159 } 00160 00161 void pop(Decl *D) { 00162 if (!Popped) { 00163 Actions.PopParsingDeclaration(State, D); 00164 Popped = true; 00165 } 00166 } 00167 }; 00168 00169 /// A class for parsing a DeclSpec. 00170 class ParsingDeclSpec : public DeclSpec { 00171 ParsingDeclRAIIObject ParsingRAII; 00172 00173 public: 00174 ParsingDeclSpec(Parser &P) 00175 : DeclSpec(P.getAttrFactory()), 00176 ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} 00177 ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) 00178 : DeclSpec(P.getAttrFactory()), 00179 ParsingRAII(P, RAII) {} 00180 00181 const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { 00182 return ParsingRAII.getDelayedDiagnosticPool(); 00183 } 00184 00185 void complete(Decl *D) { 00186 ParsingRAII.complete(D); 00187 } 00188 00189 void abort() { 00190 ParsingRAII.abort(); 00191 } 00192 }; 00193 00194 /// A class for parsing a declarator. 00195 class ParsingDeclarator : public Declarator { 00196 ParsingDeclRAIIObject ParsingRAII; 00197 00198 public: 00199 ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) 00200 : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { 00201 } 00202 00203 const ParsingDeclSpec &getDeclSpec() const { 00204 return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); 00205 } 00206 00207 ParsingDeclSpec &getMutableDeclSpec() const { 00208 return const_cast<ParsingDeclSpec&>(getDeclSpec()); 00209 } 00210 00211 void clear() { 00212 Declarator::clear(); 00213 ParsingRAII.reset(); 00214 } 00215 00216 void complete(Decl *D) { 00217 ParsingRAII.complete(D); 00218 } 00219 }; 00220 00221 /// ExtensionRAIIObject - This saves the state of extension warnings when 00222 /// constructed and disables them. When destructed, it restores them back to 00223 /// the way they used to be. This is used to handle __extension__ in the 00224 /// parser. 00225 class ExtensionRAIIObject { 00226 void operator=(const ExtensionRAIIObject &); // DO NOT IMPLEMENT 00227 ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT 00228 DiagnosticsEngine &Diags; 00229 public: 00230 ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) { 00231 Diags.IncrementAllExtensionsSilenced(); 00232 } 00233 00234 ~ExtensionRAIIObject() { 00235 Diags.DecrementAllExtensionsSilenced(); 00236 } 00237 }; 00238 00239 /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and 00240 /// restores it when destroyed. This says that "foo:" should not be 00241 /// considered a possible typo for "foo::" for error recovery purposes. 00242 class ColonProtectionRAIIObject { 00243 Parser &P; 00244 bool OldVal; 00245 public: 00246 ColonProtectionRAIIObject(Parser &p, bool Value = true) 00247 : P(p), OldVal(P.ColonIsSacred) { 00248 P.ColonIsSacred = Value; 00249 } 00250 00251 /// restore - This can be used to restore the state early, before the dtor 00252 /// is run. 00253 void restore() { 00254 P.ColonIsSacred = OldVal; 00255 } 00256 00257 ~ColonProtectionRAIIObject() { 00258 restore(); 00259 } 00260 }; 00261 00262 /// \brief RAII object that makes '>' behave either as an operator 00263 /// or as the closing angle bracket for a template argument list. 00264 class GreaterThanIsOperatorScope { 00265 bool &GreaterThanIsOperator; 00266 bool OldGreaterThanIsOperator; 00267 public: 00268 GreaterThanIsOperatorScope(bool >IO, bool Val) 00269 : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) { 00270 GreaterThanIsOperator = Val; 00271 } 00272 00273 ~GreaterThanIsOperatorScope() { 00274 GreaterThanIsOperator = OldGreaterThanIsOperator; 00275 } 00276 }; 00277 00278 class InMessageExpressionRAIIObject { 00279 bool &InMessageExpression; 00280 bool OldValue; 00281 00282 public: 00283 InMessageExpressionRAIIObject(Parser &P, bool Value) 00284 : InMessageExpression(P.InMessageExpression), 00285 OldValue(P.InMessageExpression) { 00286 InMessageExpression = Value; 00287 } 00288 00289 ~InMessageExpressionRAIIObject() { 00290 InMessageExpression = OldValue; 00291 } 00292 }; 00293 00294 /// \brief RAII object that makes sure paren/bracket/brace count is correct 00295 /// after declaration/statement parsing, even when there's a parsing error. 00296 class ParenBraceBracketBalancer { 00297 Parser &P; 00298 unsigned short ParenCount, BracketCount, BraceCount; 00299 public: 00300 ParenBraceBracketBalancer(Parser &p) 00301 : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount), 00302 BraceCount(p.BraceCount) { } 00303 00304 ~ParenBraceBracketBalancer() { 00305 P.ParenCount = ParenCount; 00306 P.BracketCount = BracketCount; 00307 P.BraceCount = BraceCount; 00308 } 00309 }; 00310 00311 class PoisonSEHIdentifiersRAIIObject { 00312 PoisonIdentifierRAIIObject Ident_AbnormalTermination; 00313 PoisonIdentifierRAIIObject Ident_GetExceptionCode; 00314 PoisonIdentifierRAIIObject Ident_GetExceptionInfo; 00315 PoisonIdentifierRAIIObject Ident__abnormal_termination; 00316 PoisonIdentifierRAIIObject Ident__exception_code; 00317 PoisonIdentifierRAIIObject Ident__exception_info; 00318 PoisonIdentifierRAIIObject Ident___abnormal_termination; 00319 PoisonIdentifierRAIIObject Ident___exception_code; 00320 PoisonIdentifierRAIIObject Ident___exception_info; 00321 public: 00322 PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue) 00323 : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue), 00324 Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue), 00325 Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue), 00326 Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue), 00327 Ident__exception_code(Self.Ident__exception_code, NewValue), 00328 Ident__exception_info(Self.Ident__exception_info, NewValue), 00329 Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue), 00330 Ident___exception_code(Self.Ident___exception_code, NewValue), 00331 Ident___exception_info(Self.Ident___exception_info, NewValue) { 00332 } 00333 }; 00334 00335 } // end namespace clang 00336 00337 #endif