Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:59

0001 //===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines and implements the some simple RAII objects that are used
0010 // by the parser to manage bits in recursion.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
0015 #define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
0016 
0017 #include "clang/Basic/DiagnosticParse.h"
0018 #include "clang/Parse/Parser.h"
0019 #include "clang/Sema/DelayedDiagnostic.h"
0020 #include "clang/Sema/ParsedTemplate.h"
0021 #include "clang/Sema/Sema.h"
0022 
0023 namespace clang {
0024   // TODO: move ParsingClassDefinition here.
0025   // TODO: move TentativeParsingAction here.
0026 
0027   /// A RAII object used to temporarily suppress access-like
0028   /// checking.  Access-like checks are those associated with
0029   /// controlling the use of a declaration, like C++ access control
0030   /// errors and deprecation warnings.  They are contextually
0031   /// dependent, in that they can only be resolved with full
0032   /// information about what's being declared.  They are also
0033   /// suppressed in certain contexts, like the template arguments of
0034   /// an explicit instantiation.  However, those suppression contexts
0035   /// cannot necessarily be fully determined in advance;  for
0036   /// example, something starting like this:
0037   ///   template <> class std::vector<A::PrivateType>
0038   /// might be the entirety of an explicit instantiation:
0039   ///   template <> class std::vector<A::PrivateType>;
0040   /// or just an elaborated type specifier:
0041   ///   template <> class std::vector<A::PrivateType> make_vector<>();
0042   /// Therefore this class collects all the diagnostics and permits
0043   /// them to be re-delayed in a new context.
0044   class SuppressAccessChecks {
0045     Sema &S;
0046     sema::DelayedDiagnosticPool DiagnosticPool;
0047     Sema::ParsingDeclState State;
0048     bool Active;
0049 
0050   public:
0051     /// Begin suppressing access-like checks
0052     SuppressAccessChecks(Parser &P, bool activate = true)
0053         : S(P.getActions()), DiagnosticPool(nullptr) {
0054       if (activate) {
0055         State = S.PushParsingDeclaration(DiagnosticPool);
0056         Active = true;
0057       } else {
0058         Active = false;
0059       }
0060     }
0061     SuppressAccessChecks(SuppressAccessChecks &&Other)
0062       : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
0063         State(Other.State), Active(Other.Active) {
0064       Other.Active = false;
0065     }
0066     void operator=(SuppressAccessChecks &&Other) = delete;
0067 
0068     void done() {
0069       assert(Active && "trying to end an inactive suppression");
0070       S.PopParsingDeclaration(State, nullptr);
0071       Active = false;
0072     }
0073 
0074     void redelay() {
0075       assert(!Active && "redelaying without having ended first");
0076       if (!DiagnosticPool.pool_empty())
0077         S.redelayDiagnostics(DiagnosticPool);
0078       assert(DiagnosticPool.pool_empty());
0079     }
0080 
0081     ~SuppressAccessChecks() {
0082       if (Active) done();
0083     }
0084   };
0085 
0086   /// RAII object used to inform the actions that we're
0087   /// currently parsing a declaration.  This is active when parsing a
0088   /// variable's initializer, but not when parsing the body of a
0089   /// class or function definition.
0090   class ParsingDeclRAIIObject {
0091     Sema &Actions;
0092     sema::DelayedDiagnosticPool DiagnosticPool;
0093     Sema::ParsingDeclState State;
0094     bool Popped;
0095 
0096     ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
0097     void operator=(const ParsingDeclRAIIObject &) = delete;
0098 
0099   public:
0100     enum NoParent_t { NoParent };
0101     ParsingDeclRAIIObject(Parser &P, NoParent_t _)
0102         : Actions(P.getActions()), DiagnosticPool(nullptr) {
0103       push();
0104     }
0105 
0106     /// Creates a RAII object whose pool is optionally parented by another.
0107     ParsingDeclRAIIObject(Parser &P,
0108                           const sema::DelayedDiagnosticPool *parentPool)
0109         : Actions(P.getActions()), DiagnosticPool(parentPool) {
0110       push();
0111     }
0112 
0113     /// Creates a RAII object and, optionally, initialize its
0114     /// diagnostics pool by stealing the diagnostics from another
0115     /// RAII object (which is assumed to be the current top pool).
0116     ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
0117         : Actions(P.getActions()),
0118           DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
0119       if (other) {
0120         DiagnosticPool.steal(other->DiagnosticPool);
0121         other->abort();
0122       }
0123       push();
0124     }
0125 
0126     ~ParsingDeclRAIIObject() {
0127       abort();
0128     }
0129 
0130     sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
0131       return DiagnosticPool;
0132     }
0133     const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
0134       return DiagnosticPool;
0135     }
0136 
0137     /// Resets the RAII object for a new declaration.
0138     void reset() {
0139       abort();
0140       push();
0141     }
0142 
0143     /// Signals that the context was completed without an appropriate
0144     /// declaration being parsed.
0145     void abort() {
0146       pop(nullptr);
0147     }
0148 
0149     void complete(Decl *D) {
0150       assert(!Popped && "ParsingDeclaration has already been popped!");
0151       pop(D);
0152     }
0153 
0154     /// Unregister this object from Sema, but remember all the
0155     /// diagnostics that were emitted into it.
0156     void abortAndRemember() {
0157       pop(nullptr);
0158     }
0159 
0160   private:
0161     void push() {
0162       State = Actions.PushParsingDeclaration(DiagnosticPool);
0163       Popped = false;
0164     }
0165 
0166     void pop(Decl *D) {
0167       if (!Popped) {
0168         Actions.PopParsingDeclaration(State, D);
0169         Popped = true;
0170       }
0171     }
0172   };
0173 
0174   /// A class for parsing a DeclSpec.
0175   class ParsingDeclSpec : public DeclSpec {
0176     ParsingDeclRAIIObject ParsingRAII;
0177 
0178   public:
0179     ParsingDeclSpec(Parser &P)
0180       : DeclSpec(P.getAttrFactory()),
0181         ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
0182     ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
0183       : DeclSpec(P.getAttrFactory()),
0184         ParsingRAII(P, RAII) {}
0185 
0186     const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
0187       return ParsingRAII.getDelayedDiagnosticPool();
0188     }
0189 
0190     void complete(Decl *D) {
0191       ParsingRAII.complete(D);
0192     }
0193 
0194     void abort() {
0195       ParsingRAII.abort();
0196     }
0197   };
0198 
0199   /// A class for parsing a declarator.
0200   class ParsingDeclarator : public Declarator {
0201     ParsingDeclRAIIObject ParsingRAII;
0202 
0203   public:
0204     ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS,
0205                       const ParsedAttributes &DeclarationAttrs,
0206                       DeclaratorContext C)
0207         : Declarator(DS, DeclarationAttrs, C),
0208           ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
0209 
0210     const ParsingDeclSpec &getDeclSpec() const {
0211       return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
0212     }
0213 
0214     ParsingDeclSpec &getMutableDeclSpec() const {
0215       return const_cast<ParsingDeclSpec&>(getDeclSpec());
0216     }
0217 
0218     void clear() {
0219       Declarator::clear();
0220       ParsingRAII.reset();
0221     }
0222 
0223     void complete(Decl *D) {
0224       ParsingRAII.complete(D);
0225     }
0226   };
0227 
0228   /// A class for parsing a field declarator.
0229   class ParsingFieldDeclarator : public FieldDeclarator {
0230     ParsingDeclRAIIObject ParsingRAII;
0231 
0232   public:
0233     ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS,
0234                            const ParsedAttributes &DeclarationAttrs)
0235         : FieldDeclarator(DS, DeclarationAttrs),
0236           ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
0237 
0238     const ParsingDeclSpec &getDeclSpec() const {
0239       return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
0240     }
0241 
0242     ParsingDeclSpec &getMutableDeclSpec() const {
0243       return const_cast<ParsingDeclSpec&>(getDeclSpec());
0244     }
0245 
0246     void complete(Decl *D) {
0247       ParsingRAII.complete(D);
0248     }
0249   };
0250 
0251   /// ExtensionRAIIObject - This saves the state of extension warnings when
0252   /// constructed and disables them.  When destructed, it restores them back to
0253   /// the way they used to be.  This is used to handle __extension__ in the
0254   /// parser.
0255   class ExtensionRAIIObject {
0256     ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
0257     void operator=(const ExtensionRAIIObject &) = delete;
0258 
0259     DiagnosticsEngine &Diags;
0260   public:
0261     ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
0262       Diags.IncrementAllExtensionsSilenced();
0263     }
0264 
0265     ~ExtensionRAIIObject() {
0266       Diags.DecrementAllExtensionsSilenced();
0267     }
0268   };
0269 
0270   /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
0271   /// restores it when destroyed.  This says that "foo:" should not be
0272   /// considered a possible typo for "foo::" for error recovery purposes.
0273   class ColonProtectionRAIIObject {
0274     Parser &P;
0275     bool OldVal;
0276   public:
0277     ColonProtectionRAIIObject(Parser &p, bool Value = true)
0278       : P(p), OldVal(P.ColonIsSacred) {
0279       P.ColonIsSacred = Value;
0280     }
0281 
0282     /// restore - This can be used to restore the state early, before the dtor
0283     /// is run.
0284     void restore() {
0285       P.ColonIsSacred = OldVal;
0286     }
0287 
0288     ~ColonProtectionRAIIObject() {
0289       restore();
0290     }
0291   };
0292 
0293   /// Activates OpenMP parsing mode to preseve OpenMP specific annotation
0294   /// tokens.
0295   class ParsingOpenMPDirectiveRAII {
0296     Parser &P;
0297     bool OldVal;
0298 
0299   public:
0300     ParsingOpenMPDirectiveRAII(Parser &P, bool Value = true)
0301         : P(P), OldVal(P.OpenMPDirectiveParsing) {
0302       P.OpenMPDirectiveParsing = Value;
0303     }
0304 
0305     /// This can be used to restore the state early, before the dtor
0306     /// is run.
0307     void restore() { P.OpenMPDirectiveParsing = OldVal; }
0308 
0309     ~ParsingOpenMPDirectiveRAII() { restore(); }
0310   };
0311 
0312   /// Activates OpenACC parsing mode to preseve OpenACC specific annotation
0313   /// tokens.
0314   class ParsingOpenACCDirectiveRAII {
0315     Parser &P;
0316     bool OldVal;
0317 
0318   public:
0319     ParsingOpenACCDirectiveRAII(Parser &P, bool Value = true)
0320         : P(P), OldVal(P.OpenACCDirectiveParsing) {
0321       P.OpenACCDirectiveParsing = Value;
0322     }
0323 
0324     /// This can be used to restore the state early, before the dtor
0325     /// is run.
0326     void restore() { P.OpenACCDirectiveParsing = OldVal; }
0327 
0328     ~ParsingOpenACCDirectiveRAII() { restore(); }
0329   };
0330 
0331   /// RAII object that makes '>' behave either as an operator
0332   /// or as the closing angle bracket for a template argument list.
0333   class GreaterThanIsOperatorScope {
0334     bool &GreaterThanIsOperator;
0335     bool OldGreaterThanIsOperator;
0336   public:
0337     GreaterThanIsOperatorScope(bool &GTIO, bool Val)
0338     : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
0339       GreaterThanIsOperator = Val;
0340     }
0341 
0342     ~GreaterThanIsOperatorScope() {
0343       GreaterThanIsOperator = OldGreaterThanIsOperator;
0344     }
0345   };
0346 
0347   class InMessageExpressionRAIIObject {
0348     bool &InMessageExpression;
0349     bool OldValue;
0350 
0351   public:
0352     InMessageExpressionRAIIObject(Parser &P, bool Value)
0353       : InMessageExpression(P.InMessageExpression),
0354         OldValue(P.InMessageExpression) {
0355       InMessageExpression = Value;
0356     }
0357 
0358     ~InMessageExpressionRAIIObject() {
0359       InMessageExpression = OldValue;
0360     }
0361   };
0362 
0363   class OffsetOfStateRAIIObject {
0364     Sema::OffsetOfKind &OffsetOfState;
0365     Sema::OffsetOfKind OldValue;
0366 
0367   public:
0368     OffsetOfStateRAIIObject(Parser &P, Sema::OffsetOfKind Value)
0369         : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
0370       OffsetOfState = Value;
0371     }
0372 
0373     ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
0374   };
0375 
0376   /// RAII object that makes sure paren/bracket/brace count is correct
0377   /// after declaration/statement parsing, even when there's a parsing error.
0378   class ParenBraceBracketBalancer {
0379     Parser &P;
0380     unsigned short ParenCount, BracketCount, BraceCount;
0381   public:
0382     ParenBraceBracketBalancer(Parser &p)
0383       : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
0384         BraceCount(p.BraceCount) { }
0385 
0386     ~ParenBraceBracketBalancer() {
0387       P.AngleBrackets.clear(P);
0388       P.ParenCount = ParenCount;
0389       P.BracketCount = BracketCount;
0390       P.BraceCount = BraceCount;
0391     }
0392   };
0393 
0394   class PoisonSEHIdentifiersRAIIObject {
0395     PoisonIdentifierRAIIObject Ident_AbnormalTermination;
0396     PoisonIdentifierRAIIObject Ident_GetExceptionCode;
0397     PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
0398     PoisonIdentifierRAIIObject Ident__abnormal_termination;
0399     PoisonIdentifierRAIIObject Ident__exception_code;
0400     PoisonIdentifierRAIIObject Ident__exception_info;
0401     PoisonIdentifierRAIIObject Ident___abnormal_termination;
0402     PoisonIdentifierRAIIObject Ident___exception_code;
0403     PoisonIdentifierRAIIObject Ident___exception_info;
0404   public:
0405     PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
0406       : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
0407         Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
0408         Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
0409         Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
0410         Ident__exception_code(Self.Ident__exception_code, NewValue),
0411         Ident__exception_info(Self.Ident__exception_info, NewValue),
0412         Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
0413         Ident___exception_code(Self.Ident___exception_code, NewValue),
0414         Ident___exception_info(Self.Ident___exception_info, NewValue) {
0415     }
0416   };
0417 
0418   /// RAII class that helps handle the parsing of an open/close delimiter
0419   /// pair, such as braces { ... } or parentheses ( ... ).
0420   class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
0421     Parser& P;
0422     tok::TokenKind Kind, Close, FinalToken;
0423     SourceLocation (Parser::*Consumer)();
0424     SourceLocation LOpen, LClose;
0425 
0426     unsigned short &getDepth() {
0427       switch (Kind) {
0428         case tok::l_brace: return P.BraceCount;
0429         case tok::l_square: return P.BracketCount;
0430         case tok::l_paren: return P.ParenCount;
0431         default: llvm_unreachable("Wrong token kind");
0432       }
0433     }
0434 
0435     bool diagnoseOverflow();
0436     bool diagnoseMissingClose();
0437 
0438   public:
0439     BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
0440                              tok::TokenKind FinalToken = tok::semi)
0441       : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
0442         P(p), Kind(k), FinalToken(FinalToken)
0443     {
0444       switch (Kind) {
0445         default: llvm_unreachable("Unexpected balanced token");
0446         case tok::l_brace:
0447           Close = tok::r_brace;
0448           Consumer = &Parser::ConsumeBrace;
0449           break;
0450         case tok::l_paren:
0451           Close = tok::r_paren;
0452           Consumer = &Parser::ConsumeParen;
0453           break;
0454 
0455         case tok::l_square:
0456           Close = tok::r_square;
0457           Consumer = &Parser::ConsumeBracket;
0458           break;
0459       }
0460     }
0461 
0462     SourceLocation getOpenLocation() const { return LOpen; }
0463     SourceLocation getCloseLocation() const { return LClose; }
0464     SourceRange getRange() const { return SourceRange(LOpen, LClose); }
0465 
0466     bool consumeOpen() {
0467       if (!P.Tok.is(Kind))
0468         return true;
0469 
0470       if (getDepth() < P.getLangOpts().BracketDepth) {
0471         LOpen = (P.*Consumer)();
0472         return false;
0473       }
0474 
0475       return diagnoseOverflow();
0476     }
0477 
0478     bool expectAndConsume(unsigned DiagID = diag::err_expected,
0479                           const char *Msg = "",
0480                           tok::TokenKind SkipToTok = tok::unknown);
0481     bool consumeClose() {
0482       if (P.Tok.is(Close)) {
0483         LClose = (P.*Consumer)();
0484         return false;
0485       } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
0486         SourceLocation SemiLoc = P.ConsumeToken();
0487         P.Diag(SemiLoc, diag::err_unexpected_semi)
0488             << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
0489         LClose = (P.*Consumer)();
0490         return false;
0491       }
0492 
0493       return diagnoseMissingClose();
0494     }
0495     void skipToEnd();
0496   };
0497 } // end namespace clang
0498 
0499 #endif