Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines and implements the some simple RAII objects that are used
  10. // by the parser to manage bits in recursion.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
  15. #define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
  16.  
  17. #include "clang/Parse/ParseDiagnostic.h"
  18. #include "clang/Parse/Parser.h"
  19. #include "clang/Sema/DelayedDiagnostic.h"
  20. #include "clang/Sema/ParsedTemplate.h"
  21. #include "clang/Sema/Sema.h"
  22.  
  23. namespace clang {
  24.   // TODO: move ParsingClassDefinition here.
  25.   // TODO: move TentativeParsingAction here.
  26.  
  27.   /// A RAII object used to temporarily suppress access-like
  28.   /// checking.  Access-like checks are those associated with
  29.   /// controlling the use of a declaration, like C++ access control
  30.   /// errors and deprecation warnings.  They are contextually
  31.   /// dependent, in that they can only be resolved with full
  32.   /// information about what's being declared.  They are also
  33.   /// suppressed in certain contexts, like the template arguments of
  34.   /// an explicit instantiation.  However, those suppression contexts
  35.   /// cannot necessarily be fully determined in advance;  for
  36.   /// example, something starting like this:
  37.   ///   template <> class std::vector<A::PrivateType>
  38.   /// might be the entirety of an explicit instantiation:
  39.   ///   template <> class std::vector<A::PrivateType>;
  40.   /// or just an elaborated type specifier:
  41.   ///   template <> class std::vector<A::PrivateType> make_vector<>();
  42.   /// Therefore this class collects all the diagnostics and permits
  43.   /// them to be re-delayed in a new context.
  44.   class SuppressAccessChecks {
  45.     Sema &S;
  46.     sema::DelayedDiagnosticPool DiagnosticPool;
  47.     Sema::ParsingDeclState State;
  48.     bool Active;
  49.  
  50.   public:
  51.     /// Begin suppressing access-like checks
  52.     SuppressAccessChecks(Parser &P, bool activate = true)
  53.         : S(P.getActions()), DiagnosticPool(nullptr) {
  54.       if (activate) {
  55.         State = S.PushParsingDeclaration(DiagnosticPool);
  56.         Active = true;
  57.       } else {
  58.         Active = false;
  59.       }
  60.     }
  61.     SuppressAccessChecks(SuppressAccessChecks &&Other)
  62.       : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
  63.         State(Other.State), Active(Other.Active) {
  64.       Other.Active = false;
  65.     }
  66.     void operator=(SuppressAccessChecks &&Other) = delete;
  67.  
  68.     void done() {
  69.       assert(Active && "trying to end an inactive suppression");
  70.       S.PopParsingDeclaration(State, nullptr);
  71.       Active = false;
  72.     }
  73.  
  74.     void redelay() {
  75.       assert(!Active && "redelaying without having ended first");
  76.       if (!DiagnosticPool.pool_empty())
  77.         S.redelayDiagnostics(DiagnosticPool);
  78.       assert(DiagnosticPool.pool_empty());
  79.     }
  80.  
  81.     ~SuppressAccessChecks() {
  82.       if (Active) done();
  83.     }
  84.   };
  85.  
  86.   /// RAII object used to inform the actions that we're
  87.   /// currently parsing a declaration.  This is active when parsing a
  88.   /// variable's initializer, but not when parsing the body of a
  89.   /// class or function definition.
  90.   class ParsingDeclRAIIObject {
  91.     Sema &Actions;
  92.     sema::DelayedDiagnosticPool DiagnosticPool;
  93.     Sema::ParsingDeclState State;
  94.     bool Popped;
  95.  
  96.     ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
  97.     void operator=(const ParsingDeclRAIIObject &) = delete;
  98.  
  99.   public:
  100.     enum NoParent_t { NoParent };
  101.     ParsingDeclRAIIObject(Parser &P, NoParent_t _)
  102.         : Actions(P.getActions()), DiagnosticPool(nullptr) {
  103.       push();
  104.     }
  105.  
  106.     /// Creates a RAII object whose pool is optionally parented by another.
  107.     ParsingDeclRAIIObject(Parser &P,
  108.                           const sema::DelayedDiagnosticPool *parentPool)
  109.         : Actions(P.getActions()), DiagnosticPool(parentPool) {
  110.       push();
  111.     }
  112.  
  113.     /// Creates a RAII object and, optionally, initialize its
  114.     /// diagnostics pool by stealing the diagnostics from another
  115.     /// RAII object (which is assumed to be the current top pool).
  116.     ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
  117.         : Actions(P.getActions()),
  118.           DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
  119.       if (other) {
  120.         DiagnosticPool.steal(other->DiagnosticPool);
  121.         other->abort();
  122.       }
  123.       push();
  124.     }
  125.  
  126.     ~ParsingDeclRAIIObject() {
  127.       abort();
  128.     }
  129.  
  130.     sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
  131.       return DiagnosticPool;
  132.     }
  133.     const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
  134.       return DiagnosticPool;
  135.     }
  136.  
  137.     /// Resets the RAII object for a new declaration.
  138.     void reset() {
  139.       abort();
  140.       push();
  141.     }
  142.  
  143.     /// Signals that the context was completed without an appropriate
  144.     /// declaration being parsed.
  145.     void abort() {
  146.       pop(nullptr);
  147.     }
  148.  
  149.     void complete(Decl *D) {
  150.       assert(!Popped && "ParsingDeclaration has already been popped!");
  151.       pop(D);
  152.     }
  153.  
  154.     /// Unregister this object from Sema, but remember all the
  155.     /// diagnostics that were emitted into it.
  156.     void abortAndRemember() {
  157.       pop(nullptr);
  158.     }
  159.  
  160.   private:
  161.     void push() {
  162.       State = Actions.PushParsingDeclaration(DiagnosticPool);
  163.       Popped = false;
  164.     }
  165.  
  166.     void pop(Decl *D) {
  167.       if (!Popped) {
  168.         Actions.PopParsingDeclaration(State, D);
  169.         Popped = true;
  170.       }
  171.     }
  172.   };
  173.  
  174.   /// A class for parsing a DeclSpec.
  175.   class ParsingDeclSpec : public DeclSpec {
  176.     ParsingDeclRAIIObject ParsingRAII;
  177.  
  178.   public:
  179.     ParsingDeclSpec(Parser &P)
  180.       : DeclSpec(P.getAttrFactory()),
  181.         ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
  182.     ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
  183.       : DeclSpec(P.getAttrFactory()),
  184.         ParsingRAII(P, RAII) {}
  185.  
  186.     const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
  187.       return ParsingRAII.getDelayedDiagnosticPool();
  188.     }
  189.  
  190.     void complete(Decl *D) {
  191.       ParsingRAII.complete(D);
  192.     }
  193.  
  194.     void abort() {
  195.       ParsingRAII.abort();
  196.     }
  197.   };
  198.  
  199.   /// A class for parsing a declarator.
  200.   class ParsingDeclarator : public Declarator {
  201.     ParsingDeclRAIIObject ParsingRAII;
  202.  
  203.   public:
  204.     ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS,
  205.                       const ParsedAttributes &DeclarationAttrs,
  206.                       DeclaratorContext C)
  207.         : Declarator(DS, DeclarationAttrs, C),
  208.           ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
  209.  
  210.     const ParsingDeclSpec &getDeclSpec() const {
  211.       return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
  212.     }
  213.  
  214.     ParsingDeclSpec &getMutableDeclSpec() const {
  215.       return const_cast<ParsingDeclSpec&>(getDeclSpec());
  216.     }
  217.  
  218.     void clear() {
  219.       Declarator::clear();
  220.       ParsingRAII.reset();
  221.     }
  222.  
  223.     void complete(Decl *D) {
  224.       ParsingRAII.complete(D);
  225.     }
  226.   };
  227.  
  228.   /// A class for parsing a field declarator.
  229.   class ParsingFieldDeclarator : public FieldDeclarator {
  230.     ParsingDeclRAIIObject ParsingRAII;
  231.  
  232.   public:
  233.     ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS,
  234.                            const ParsedAttributes &DeclarationAttrs)
  235.         : FieldDeclarator(DS, DeclarationAttrs),
  236.           ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
  237.  
  238.     const ParsingDeclSpec &getDeclSpec() const {
  239.       return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
  240.     }
  241.  
  242.     ParsingDeclSpec &getMutableDeclSpec() const {
  243.       return const_cast<ParsingDeclSpec&>(getDeclSpec());
  244.     }
  245.  
  246.     void complete(Decl *D) {
  247.       ParsingRAII.complete(D);
  248.     }
  249.   };
  250.  
  251.   /// ExtensionRAIIObject - This saves the state of extension warnings when
  252.   /// constructed and disables them.  When destructed, it restores them back to
  253.   /// the way they used to be.  This is used to handle __extension__ in the
  254.   /// parser.
  255.   class ExtensionRAIIObject {
  256.     ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
  257.     void operator=(const ExtensionRAIIObject &) = delete;
  258.  
  259.     DiagnosticsEngine &Diags;
  260.   public:
  261.     ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
  262.       Diags.IncrementAllExtensionsSilenced();
  263.     }
  264.  
  265.     ~ExtensionRAIIObject() {
  266.       Diags.DecrementAllExtensionsSilenced();
  267.     }
  268.   };
  269.  
  270.   /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
  271.   /// restores it when destroyed.  This says that "foo:" should not be
  272.   /// considered a possible typo for "foo::" for error recovery purposes.
  273.   class ColonProtectionRAIIObject {
  274.     Parser &P;
  275.     bool OldVal;
  276.   public:
  277.     ColonProtectionRAIIObject(Parser &p, bool Value = true)
  278.       : P(p), OldVal(P.ColonIsSacred) {
  279.       P.ColonIsSacred = Value;
  280.     }
  281.  
  282.     /// restore - This can be used to restore the state early, before the dtor
  283.     /// is run.
  284.     void restore() {
  285.       P.ColonIsSacred = OldVal;
  286.     }
  287.  
  288.     ~ColonProtectionRAIIObject() {
  289.       restore();
  290.     }
  291.   };
  292.  
  293.   /// Activates OpenMP parsing mode to preseve OpenMP specific annotation
  294.   /// tokens.
  295.   class ParsingOpenMPDirectiveRAII {
  296.     Parser &P;
  297.     bool OldVal;
  298.  
  299.   public:
  300.     ParsingOpenMPDirectiveRAII(Parser &P, bool Value = true)
  301.         : P(P), OldVal(P.OpenMPDirectiveParsing) {
  302.       P.OpenMPDirectiveParsing = Value;
  303.     }
  304.  
  305.     /// This can be used to restore the state early, before the dtor
  306.     /// is run.
  307.     void restore() { P.OpenMPDirectiveParsing = OldVal; }
  308.  
  309.     ~ParsingOpenMPDirectiveRAII() { restore(); }
  310.   };
  311.  
  312.   /// RAII object that makes '>' behave either as an operator
  313.   /// or as the closing angle bracket for a template argument list.
  314.   class GreaterThanIsOperatorScope {
  315.     bool &GreaterThanIsOperator;
  316.     bool OldGreaterThanIsOperator;
  317.   public:
  318.     GreaterThanIsOperatorScope(bool &GTIO, bool Val)
  319.     : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
  320.       GreaterThanIsOperator = Val;
  321.     }
  322.  
  323.     ~GreaterThanIsOperatorScope() {
  324.       GreaterThanIsOperator = OldGreaterThanIsOperator;
  325.     }
  326.   };
  327.  
  328.   class InMessageExpressionRAIIObject {
  329.     bool &InMessageExpression;
  330.     bool OldValue;
  331.  
  332.   public:
  333.     InMessageExpressionRAIIObject(Parser &P, bool Value)
  334.       : InMessageExpression(P.InMessageExpression),
  335.         OldValue(P.InMessageExpression) {
  336.       InMessageExpression = Value;
  337.     }
  338.  
  339.     ~InMessageExpressionRAIIObject() {
  340.       InMessageExpression = OldValue;
  341.     }
  342.   };
  343.  
  344.   class OffsetOfStateRAIIObject {
  345.     Sema::OffsetOfKind &OffsetOfState;
  346.     Sema::OffsetOfKind OldValue;
  347.  
  348.   public:
  349.     OffsetOfStateRAIIObject(Parser &P, Sema::OffsetOfKind Value)
  350.         : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
  351.       OffsetOfState = Value;
  352.     }
  353.  
  354.     ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
  355.   };
  356.  
  357.   /// RAII object that makes sure paren/bracket/brace count is correct
  358.   /// after declaration/statement parsing, even when there's a parsing error.
  359.   class ParenBraceBracketBalancer {
  360.     Parser &P;
  361.     unsigned short ParenCount, BracketCount, BraceCount;
  362.   public:
  363.     ParenBraceBracketBalancer(Parser &p)
  364.       : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
  365.         BraceCount(p.BraceCount) { }
  366.  
  367.     ~ParenBraceBracketBalancer() {
  368.       P.AngleBrackets.clear(P);
  369.       P.ParenCount = ParenCount;
  370.       P.BracketCount = BracketCount;
  371.       P.BraceCount = BraceCount;
  372.     }
  373.   };
  374.  
  375.   class PoisonSEHIdentifiersRAIIObject {
  376.     PoisonIdentifierRAIIObject Ident_AbnormalTermination;
  377.     PoisonIdentifierRAIIObject Ident_GetExceptionCode;
  378.     PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
  379.     PoisonIdentifierRAIIObject Ident__abnormal_termination;
  380.     PoisonIdentifierRAIIObject Ident__exception_code;
  381.     PoisonIdentifierRAIIObject Ident__exception_info;
  382.     PoisonIdentifierRAIIObject Ident___abnormal_termination;
  383.     PoisonIdentifierRAIIObject Ident___exception_code;
  384.     PoisonIdentifierRAIIObject Ident___exception_info;
  385.   public:
  386.     PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
  387.       : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
  388.         Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
  389.         Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
  390.         Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
  391.         Ident__exception_code(Self.Ident__exception_code, NewValue),
  392.         Ident__exception_info(Self.Ident__exception_info, NewValue),
  393.         Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
  394.         Ident___exception_code(Self.Ident___exception_code, NewValue),
  395.         Ident___exception_info(Self.Ident___exception_info, NewValue) {
  396.     }
  397.   };
  398.  
  399.   /// RAII class that helps handle the parsing of an open/close delimiter
  400.   /// pair, such as braces { ... } or parentheses ( ... ).
  401.   class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
  402.     Parser& P;
  403.     tok::TokenKind Kind, Close, FinalToken;
  404.     SourceLocation (Parser::*Consumer)();
  405.     SourceLocation LOpen, LClose;
  406.  
  407.     unsigned short &getDepth() {
  408.       switch (Kind) {
  409.         case tok::l_brace: return P.BraceCount;
  410.         case tok::l_square: return P.BracketCount;
  411.         case tok::l_paren: return P.ParenCount;
  412.         default: llvm_unreachable("Wrong token kind");
  413.       }
  414.     }
  415.  
  416.     bool diagnoseOverflow();
  417.     bool diagnoseMissingClose();
  418.  
  419.   public:
  420.     BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
  421.                              tok::TokenKind FinalToken = tok::semi)
  422.       : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
  423.         P(p), Kind(k), FinalToken(FinalToken)
  424.     {
  425.       switch (Kind) {
  426.         default: llvm_unreachable("Unexpected balanced token");
  427.         case tok::l_brace:
  428.           Close = tok::r_brace;
  429.           Consumer = &Parser::ConsumeBrace;
  430.           break;
  431.         case tok::l_paren:
  432.           Close = tok::r_paren;
  433.           Consumer = &Parser::ConsumeParen;
  434.           break;
  435.  
  436.         case tok::l_square:
  437.           Close = tok::r_square;
  438.           Consumer = &Parser::ConsumeBracket;
  439.           break;
  440.       }
  441.     }
  442.  
  443.     SourceLocation getOpenLocation() const { return LOpen; }
  444.     SourceLocation getCloseLocation() const { return LClose; }
  445.     SourceRange getRange() const { return SourceRange(LOpen, LClose); }
  446.  
  447.     bool consumeOpen() {
  448.       if (!P.Tok.is(Kind))
  449.         return true;
  450.  
  451.       if (getDepth() < P.getLangOpts().BracketDepth) {
  452.         LOpen = (P.*Consumer)();
  453.         return false;
  454.       }
  455.  
  456.       return diagnoseOverflow();
  457.     }
  458.  
  459.     bool expectAndConsume(unsigned DiagID = diag::err_expected,
  460.                           const char *Msg = "",
  461.                           tok::TokenKind SkipToTok = tok::unknown);
  462.     bool consumeClose() {
  463.       if (P.Tok.is(Close)) {
  464.         LClose = (P.*Consumer)();
  465.         return false;
  466.       } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
  467.         SourceLocation SemiLoc = P.ConsumeToken();
  468.         P.Diag(SemiLoc, diag::err_unexpected_semi)
  469.             << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
  470.         LClose = (P.*Consumer)();
  471.         return false;
  472.       }
  473.  
  474.       return diagnoseMissingClose();
  475.     }
  476.     void skipToEnd();
  477.   };
  478. } // end namespace clang
  479.  
  480. #endif
  481.