clang API Documentation

RAIIObjectsForParser.h
Go to the documentation of this file.
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_LIB_PARSE_RAIIOBJECTSFORPARSER_H
00016 #define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_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(nullptr) {
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, nullptr);
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     ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION;
00091     void operator=(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION;
00092 
00093   public:
00094     enum NoParent_t { NoParent };
00095     ParsingDeclRAIIObject(Parser &P, NoParent_t _)
00096         : Actions(P.getActions()), DiagnosticPool(nullptr) {
00097       push();
00098     }
00099 
00100     /// Creates a RAII object whose pool is optionally parented by another.
00101     ParsingDeclRAIIObject(Parser &P,
00102                           const sema::DelayedDiagnosticPool *parentPool)
00103         : Actions(P.getActions()), DiagnosticPool(parentPool) {
00104       push();
00105     }
00106 
00107     /// Creates a RAII object and, optionally, initialize its
00108     /// diagnostics pool by stealing the diagnostics from another
00109     /// RAII object (which is assumed to be the current top pool).
00110     ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
00111         : Actions(P.getActions()),
00112           DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
00113       if (other) {
00114         DiagnosticPool.steal(other->DiagnosticPool);
00115         other->abort();
00116       }
00117       push();
00118     }
00119 
00120     ~ParsingDeclRAIIObject() {
00121       abort();
00122     }
00123 
00124     sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
00125       return DiagnosticPool;
00126     }
00127     const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
00128       return DiagnosticPool;
00129     }
00130 
00131     /// Resets the RAII object for a new declaration.
00132     void reset() {
00133       abort();
00134       push();
00135     }
00136 
00137     /// Signals that the context was completed without an appropriate
00138     /// declaration being parsed.
00139     void abort() {
00140       pop(nullptr);
00141     }
00142 
00143     void complete(Decl *D) {
00144       assert(!Popped && "ParsingDeclaration has already been popped!");
00145       pop(D);
00146     }
00147 
00148     /// Unregister this object from Sema, but remember all the
00149     /// diagnostics that were emitted into it.
00150     void abortAndRemember() {
00151       pop(nullptr);
00152     }
00153 
00154   private:
00155     void push() {
00156       State = Actions.PushParsingDeclaration(DiagnosticPool);
00157       Popped = false;
00158     }
00159 
00160     void pop(Decl *D) {
00161       if (!Popped) {
00162         Actions.PopParsingDeclaration(State, D);
00163         Popped = true;
00164       }
00165     }
00166   };
00167 
00168   /// A class for parsing a DeclSpec.
00169   class ParsingDeclSpec : public DeclSpec {
00170     ParsingDeclRAIIObject ParsingRAII;
00171 
00172   public:
00173     ParsingDeclSpec(Parser &P)
00174       : DeclSpec(P.getAttrFactory()),
00175         ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
00176     ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
00177       : DeclSpec(P.getAttrFactory()),
00178         ParsingRAII(P, RAII) {}
00179 
00180     const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
00181       return ParsingRAII.getDelayedDiagnosticPool();
00182     }
00183 
00184     void complete(Decl *D) {
00185       ParsingRAII.complete(D);
00186     }
00187 
00188     void abort() {
00189       ParsingRAII.abort();
00190     }
00191   };
00192 
00193   /// A class for parsing a declarator.
00194   class ParsingDeclarator : public Declarator {
00195     ParsingDeclRAIIObject ParsingRAII;
00196 
00197   public:
00198     ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
00199       : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
00200     }
00201 
00202     const ParsingDeclSpec &getDeclSpec() const {
00203       return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
00204     }
00205 
00206     ParsingDeclSpec &getMutableDeclSpec() const {
00207       return const_cast<ParsingDeclSpec&>(getDeclSpec());
00208     }
00209 
00210     void clear() {
00211       Declarator::clear();
00212       ParsingRAII.reset();
00213     }
00214 
00215     void complete(Decl *D) {
00216       ParsingRAII.complete(D);
00217     }
00218   };
00219 
00220   /// A class for parsing a field declarator.
00221   class ParsingFieldDeclarator : public FieldDeclarator {
00222     ParsingDeclRAIIObject ParsingRAII;
00223 
00224   public:
00225     ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
00226       : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
00227     }
00228 
00229     const ParsingDeclSpec &getDeclSpec() const {
00230       return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
00231     }
00232 
00233     ParsingDeclSpec &getMutableDeclSpec() const {
00234       return const_cast<ParsingDeclSpec&>(getDeclSpec());
00235     }
00236 
00237     void complete(Decl *D) {
00238       ParsingRAII.complete(D);
00239     }
00240   };
00241 
00242   /// ExtensionRAIIObject - This saves the state of extension warnings when
00243   /// constructed and disables them.  When destructed, it restores them back to
00244   /// the way they used to be.  This is used to handle __extension__ in the
00245   /// parser.
00246   class ExtensionRAIIObject {
00247     ExtensionRAIIObject(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION;
00248     void operator=(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION;
00249 
00250     DiagnosticsEngine &Diags;
00251   public:
00252     ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
00253       Diags.IncrementAllExtensionsSilenced();
00254     }
00255 
00256     ~ExtensionRAIIObject() {
00257       Diags.DecrementAllExtensionsSilenced();
00258     }
00259   };
00260   
00261   /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
00262   /// restores it when destroyed.  This says that "foo:" should not be
00263   /// considered a possible typo for "foo::" for error recovery purposes.
00264   class ColonProtectionRAIIObject {
00265     Parser &P;
00266     bool OldVal;
00267   public:
00268     ColonProtectionRAIIObject(Parser &p, bool Value = true)
00269       : P(p), OldVal(P.ColonIsSacred) {
00270       P.ColonIsSacred = Value;
00271     }
00272     
00273     /// restore - This can be used to restore the state early, before the dtor
00274     /// is run.
00275     void restore() {
00276       P.ColonIsSacred = OldVal;
00277     }
00278     
00279     ~ColonProtectionRAIIObject() {
00280       restore();
00281     }
00282   };
00283   
00284   /// \brief RAII object that makes '>' behave either as an operator
00285   /// or as the closing angle bracket for a template argument list.
00286   class GreaterThanIsOperatorScope {
00287     bool &GreaterThanIsOperator;
00288     bool OldGreaterThanIsOperator;
00289   public:
00290     GreaterThanIsOperatorScope(bool &GTIO, bool Val)
00291     : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
00292       GreaterThanIsOperator = Val;
00293     }
00294     
00295     ~GreaterThanIsOperatorScope() {
00296       GreaterThanIsOperator = OldGreaterThanIsOperator;
00297     }
00298   };
00299   
00300   class InMessageExpressionRAIIObject {
00301     bool &InMessageExpression;
00302     bool OldValue;
00303     
00304   public:
00305     InMessageExpressionRAIIObject(Parser &P, bool Value)
00306       : InMessageExpression(P.InMessageExpression), 
00307         OldValue(P.InMessageExpression) {
00308       InMessageExpression = Value;
00309     }
00310     
00311     ~InMessageExpressionRAIIObject() {
00312       InMessageExpression = OldValue;
00313     }
00314   };
00315   
00316   /// \brief RAII object that makes sure paren/bracket/brace count is correct
00317   /// after declaration/statement parsing, even when there's a parsing error.
00318   class ParenBraceBracketBalancer {
00319     Parser &P;
00320     unsigned short ParenCount, BracketCount, BraceCount;
00321   public:
00322     ParenBraceBracketBalancer(Parser &p)
00323       : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
00324         BraceCount(p.BraceCount) { }
00325     
00326     ~ParenBraceBracketBalancer() {
00327       P.ParenCount = ParenCount;
00328       P.BracketCount = BracketCount;
00329       P.BraceCount = BraceCount;
00330     }
00331   };
00332 
00333   class PoisonSEHIdentifiersRAIIObject {
00334     PoisonIdentifierRAIIObject Ident_AbnormalTermination;
00335     PoisonIdentifierRAIIObject Ident_GetExceptionCode;
00336     PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
00337     PoisonIdentifierRAIIObject Ident__abnormal_termination;
00338     PoisonIdentifierRAIIObject Ident__exception_code;
00339     PoisonIdentifierRAIIObject Ident__exception_info;
00340     PoisonIdentifierRAIIObject Ident___abnormal_termination;
00341     PoisonIdentifierRAIIObject Ident___exception_code;
00342     PoisonIdentifierRAIIObject Ident___exception_info;
00343   public:
00344     PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
00345       : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
00346         Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
00347         Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
00348         Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
00349         Ident__exception_code(Self.Ident__exception_code, NewValue),
00350         Ident__exception_info(Self.Ident__exception_info, NewValue),
00351         Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
00352         Ident___exception_code(Self.Ident___exception_code, NewValue),
00353         Ident___exception_info(Self.Ident___exception_info, NewValue) {
00354     }
00355   };
00356 
00357   /// \brief RAII class that helps handle the parsing of an open/close delimiter
00358   /// pair, such as braces { ... } or parentheses ( ... ).
00359   class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
00360     Parser& P;
00361     tok::TokenKind Kind, Close, FinalToken;
00362     SourceLocation (Parser::*Consumer)();
00363     SourceLocation LOpen, LClose;
00364     
00365     unsigned short &getDepth() {
00366       switch (Kind) {
00367         case tok::l_brace: return P.BraceCount;
00368         case tok::l_square: return P.BracketCount;
00369         case tok::l_paren: return P.ParenCount;
00370         default: llvm_unreachable("Wrong token kind");
00371       }
00372     }
00373     
00374     enum { MaxDepth = 256 };
00375     
00376     bool diagnoseOverflow();
00377     bool diagnoseMissingClose();
00378     
00379   public:
00380     BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
00381                              tok::TokenKind FinalToken = tok::semi)
00382       : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
00383         P(p), Kind(k), FinalToken(FinalToken)
00384     {
00385       switch (Kind) {
00386         default: llvm_unreachable("Unexpected balanced token");
00387         case tok::l_brace:
00388           Close = tok::r_brace; 
00389           Consumer = &Parser::ConsumeBrace;
00390           break;
00391         case tok::l_paren:
00392           Close = tok::r_paren; 
00393           Consumer = &Parser::ConsumeParen;
00394           break;
00395           
00396         case tok::l_square:
00397           Close = tok::r_square; 
00398           Consumer = &Parser::ConsumeBracket;
00399           break;
00400       }      
00401     }
00402     
00403     SourceLocation getOpenLocation() const { return LOpen; }
00404     SourceLocation getCloseLocation() const { return LClose; }
00405     SourceRange getRange() const { return SourceRange(LOpen, LClose); }
00406     
00407     bool consumeOpen() {
00408       if (!P.Tok.is(Kind))
00409         return true;
00410       
00411       if (getDepth() < P.getLangOpts().BracketDepth) {
00412         LOpen = (P.*Consumer)();
00413         return false;
00414       }
00415       
00416       return diagnoseOverflow();
00417     }
00418 
00419     bool expectAndConsume(unsigned DiagID = diag::err_expected,
00420                           const char *Msg = "",
00421                           tok::TokenKind SkipToTok = tok::unknown);
00422     bool consumeClose() {
00423       if (P.Tok.is(Close)) {
00424         LClose = (P.*Consumer)();
00425         return false;
00426       } 
00427       
00428       return diagnoseMissingClose();
00429     }
00430     void skipToEnd();
00431   };
00432 
00433 } // end namespace clang
00434 
00435 #endif