Clang Project

clang_source_code/include/clang/Parse/RAIIObjectsForParser.h
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_LIB_PARSE_RAIIOBJECTSFORPARSER_H
15#define LLVM_CLANG_LIB_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
23namespace 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 &Pbool 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       (0) . __assert_fail ("Active && \"trying to end an inactive suppression\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Parse/RAIIObjectsForParser.h", 69, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Active && "trying to end an inactive suppression");
70      S.PopParsingDeclaration(Statenullptr);
71      Active = false;
72    }
73
74    void redelay() {
75       (0) . __assert_fail ("!Active && \"redelaying without having ended first\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Parse/RAIIObjectsForParser.h", 75, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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 (Activedone();
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 &PNoParent_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 &PParsingDeclRAIIObject *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       (0) . __assert_fail ("!Popped && \"ParsingDeclaration has already been popped!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Parse/RAIIObjectsForParser.h", 150, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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(StateD);
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 &PParsingDeclRAIIObject *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 &Pconst ParsingDeclSpec &DSDeclaratorContext C)
205      : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
206    }
207
208    const ParsingDeclSpec &getDeclSpec() const {
209      return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
210    }
211
212    ParsingDeclSpec &getMutableDeclSpec() const {
213      return const_cast<ParsingDeclSpec&>(getDeclSpec());
214    }
215
216    void clear() {
217      Declarator::clear();
218      ParsingRAII.reset();
219    }
220
221    void complete(Decl *D) {
222      ParsingRAII.complete(D);
223    }
224  };
225
226  /// A class for parsing a field declarator.
227  class ParsingFieldDeclarator : public FieldDeclarator {
228    ParsingDeclRAIIObject ParsingRAII;
229
230  public:
231    ParsingFieldDeclarator(Parser &Pconst ParsingDeclSpec &DS)
232      : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
233    }
234
235    const ParsingDeclSpec &getDeclSpec() const {
236      return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
237    }
238
239    ParsingDeclSpec &getMutableDeclSpec() const {
240      return const_cast<ParsingDeclSpec&>(getDeclSpec());
241    }
242
243    void complete(Decl *D) {
244      ParsingRAII.complete(D);
245    }
246  };
247
248  /// ExtensionRAIIObject - This saves the state of extension warnings when
249  /// constructed and disables them.  When destructed, it restores them back to
250  /// the way they used to be.  This is used to handle __extension__ in the
251  /// parser.
252  class ExtensionRAIIObject {
253    ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
254    void operator=(const ExtensionRAIIObject &) = delete;
255
256    DiagnosticsEngine &Diags;
257  public:
258    ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
259      Diags.IncrementAllExtensionsSilenced();
260    }
261
262    ~ExtensionRAIIObject() {
263      Diags.DecrementAllExtensionsSilenced();
264    }
265  };
266
267  /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
268  /// restores it when destroyed.  This says that "foo:" should not be
269  /// considered a possible typo for "foo::" for error recovery purposes.
270  class ColonProtectionRAIIObject {
271    Parser &P;
272    bool OldVal;
273  public:
274    ColonProtectionRAIIObject(Parser &pbool Value = true)
275      : P(p), OldVal(P.ColonIsSacred) {
276      P.ColonIsSacred = Value;
277    }
278
279    /// restore - This can be used to restore the state early, before the dtor
280    /// is run.
281    void restore() {
282      P.ColonIsSacred = OldVal;
283    }
284
285    ~ColonProtectionRAIIObject() {
286      restore();
287    }
288  };
289
290  /// RAII object that makes '>' behave either as an operator
291  /// or as the closing angle bracket for a template argument list.
292  class GreaterThanIsOperatorScope {
293    bool &GreaterThanIsOperator;
294    bool OldGreaterThanIsOperator;
295  public:
296    GreaterThanIsOperatorScope(bool &GTIObool Val)
297    : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
298      GreaterThanIsOperator = Val;
299    }
300
301    ~GreaterThanIsOperatorScope() {
302      GreaterThanIsOperator = OldGreaterThanIsOperator;
303    }
304  };
305
306  class InMessageExpressionRAIIObject {
307    bool &InMessageExpression;
308    bool OldValue;
309
310  public:
311    InMessageExpressionRAIIObject(Parser &Pbool Value)
312      : InMessageExpression(P.InMessageExpression),
313        OldValue(P.InMessageExpression) {
314      InMessageExpression = Value;
315    }
316
317    ~InMessageExpressionRAIIObject() {
318      InMessageExpression = OldValue;
319    }
320  };
321
322  /// RAII object that makes sure paren/bracket/brace count is correct
323  /// after declaration/statement parsing, even when there's a parsing error.
324  class ParenBraceBracketBalancer {
325    Parser &P;
326    unsigned short ParenCountBracketCountBraceCount;
327  public:
328    ParenBraceBracketBalancer(Parser &p)
329      : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
330        BraceCount(p.BraceCount) { }
331
332    ~ParenBraceBracketBalancer() {
333      P.AngleBrackets.clear(P);
334      P.ParenCount = ParenCount;
335      P.BracketCount = BracketCount;
336      P.BraceCount = BraceCount;
337    }
338  };
339
340  class PoisonSEHIdentifiersRAIIObject {
341    PoisonIdentifierRAIIObject Ident_AbnormalTermination;
342    PoisonIdentifierRAIIObject Ident_GetExceptionCode;
343    PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
344    PoisonIdentifierRAIIObject Ident__abnormal_termination;
345    PoisonIdentifierRAIIObject Ident__exception_code;
346    PoisonIdentifierRAIIObject Ident__exception_info;
347    PoisonIdentifierRAIIObject Ident___abnormal_termination;
348    PoisonIdentifierRAIIObject Ident___exception_code;
349    PoisonIdentifierRAIIObject Ident___exception_info;
350  public:
351    PoisonSEHIdentifiersRAIIObject(Parser &Selfbool NewValue)
352      : Ident_AbnormalTermination(Self.Ident_AbnormalTerminationNewValue),
353        Ident_GetExceptionCode(Self.Ident_GetExceptionCodeNewValue),
354        Ident_GetExceptionInfo(Self.Ident_GetExceptionInfoNewValue),
355        Ident__abnormal_termination(Self.Ident__abnormal_terminationNewValue),
356        Ident__exception_code(Self.Ident__exception_codeNewValue),
357        Ident__exception_info(Self.Ident__exception_infoNewValue),
358        Ident___abnormal_termination(Self.Ident___abnormal_terminationNewValue),
359        Ident___exception_code(Self.Ident___exception_codeNewValue),
360        Ident___exception_info(Self.Ident___exception_infoNewValue) {
361    }
362  };
363
364  /// RAII class that helps handle the parsing of an open/close delimiter
365  /// pair, such as braces { ... } or parentheses ( ... ).
366  class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
367    ParserP;
368    tok::TokenKind KindCloseFinalToken;
369    SourceLocation (Parser::*Consumer)();
370    SourceLocation LOpenLClose;
371
372    unsigned short &getDepth() {
373      switch (Kind) {
374        case tok::l_bracereturn P.BraceCount;
375        case tok::l_squarereturn P.BracketCount;
376        case tok::l_parenreturn P.ParenCount;
377        default: llvm_unreachable("Wrong token kind");
378      }
379    }
380
381    bool diagnoseOverflow();
382    bool diagnoseMissingClose();
383
384  public:
385    BalancedDelimiterTracker(Parserptok::TokenKind k,
386                             tok::TokenKind FinalToken = tok::semi)
387      : GreaterThanIsOperatorScope(p.GreaterThanIsOperatortrue),
388        P(p), Kind(k), FinalToken(FinalToken)
389    {
390      switch (Kind) {
391        default: llvm_unreachable("Unexpected balanced token");
392        case tok::l_brace:
393          Close = tok::r_brace;
394          Consumer = &Parser::ConsumeBrace;
395          break;
396        case tok::l_paren:
397          Close = tok::r_paren;
398          Consumer = &Parser::ConsumeParen;
399          break;
400
401        case tok::l_square:
402          Close = tok::r_square;
403          Consumer = &Parser::ConsumeBracket;
404          break;
405      }
406    }
407
408    SourceLocation getOpenLocation() const { return LOpen; }
409    SourceLocation getCloseLocation() const { return LClose; }
410    SourceRange getRange() const { return SourceRange(LOpenLClose); }
411
412    bool consumeOpen() {
413      if (!P.Tok.is(Kind))
414        return true;
415
416      if (getDepth() < P.getLangOpts().BracketDepth) {
417        LOpen = (P.*Consumer)();
418        return false;
419      }
420
421      return diagnoseOverflow();
422    }
423
424    bool expectAndConsume(unsigned DiagID = diag::err_expected,
425                          const char *Msg = "",
426                          tok::TokenKind SkipToTok = tok::unknown);
427    bool consumeClose() {
428      if (P.Tok.is(Close)) {
429        LClose = (P.*Consumer)();
430        return false;
431      } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
432        SourceLocation SemiLoc = P.ConsumeToken();
433        P.Diag(SemiLoc, diag::err_unexpected_semi)
434            << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
435        LClose = (P.*Consumer)();
436        return false;
437      }
438
439      return diagnoseMissingClose();
440    }
441    void skipToEnd();
442  };
443
444  /// RAIIObject to destroy the contents of a SmallVector of
445  /// TemplateIdAnnotation pointers and clear the vector.
446  class DestroyTemplateIdAnnotationsRAIIObj {
447    SmallVectorImpl<TemplateIdAnnotation *> &Container;
448
449  public:
450    DestroyTemplateIdAnnotationsRAIIObj(
451        SmallVectorImpl<TemplateIdAnnotation *> &Container)
452        : Container(Container) {}
453
454    ~DestroyTemplateIdAnnotationsRAIIObj() {
455      for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
456               Container.begin(),
457             E = Container.end();
458           I != E; ++I)
459        (*I)->Destroy();
460      Container.clear();
461    }
462  };
463// end namespace clang
464
465#endif
466
clang::SuppressAccessChecks::S
clang::SuppressAccessChecks::DiagnosticPool
clang::SuppressAccessChecks::State
clang::SuppressAccessChecks::Active
clang::SuppressAccessChecks::done
clang::SuppressAccessChecks::redelay
clang::ParsingDeclRAIIObject::Actions
clang::ParsingDeclRAIIObject::DiagnosticPool
clang::ParsingDeclRAIIObject::State
clang::ParsingDeclRAIIObject::Popped
clang::ParsingDeclRAIIObject::NoParent_t
clang::ParsingDeclRAIIObject::getDelayedDiagnosticPool
clang::ParsingDeclRAIIObject::getDelayedDiagnosticPool
clang::ParsingDeclRAIIObject::reset
clang::ParsingDeclRAIIObject::abort
clang::ParsingDeclRAIIObject::complete
clang::ParsingDeclRAIIObject::abortAndRemember
clang::ParsingDeclRAIIObject::push
clang::ParsingDeclRAIIObject::pop
clang::ParsingDeclSpec::ParsingRAII
clang::ParsingDeclSpec::getDelayedDiagnosticPool
clang::ParsingDeclSpec::complete
clang::ParsingDeclSpec::abort
clang::ParsingDeclarator::ParsingRAII
clang::ParsingDeclarator::getDeclSpec
clang::ParsingDeclarator::getMutableDeclSpec
clang::ParsingDeclarator::clear
clang::ParsingDeclarator::complete
clang::ParsingFieldDeclarator::ParsingRAII
clang::ParsingFieldDeclarator::getDeclSpec
clang::ParsingFieldDeclarator::getMutableDeclSpec
clang::ParsingFieldDeclarator::complete
clang::ExtensionRAIIObject::Diags
clang::ColonProtectionRAIIObject::P
clang::ColonProtectionRAIIObject::OldVal
clang::ColonProtectionRAIIObject::restore
clang::GreaterThanIsOperatorScope::GreaterThanIsOperator
clang::GreaterThanIsOperatorScope::OldGreaterThanIsOperator
clang::InMessageExpressionRAIIObject::InMessageExpression
clang::InMessageExpressionRAIIObject::OldValue
clang::ParenBraceBracketBalancer::P
clang::ParenBraceBracketBalancer::ParenCount
clang::ParenBraceBracketBalancer::BracketCount
clang::ParenBraceBracketBalancer::BraceCount
clang::PoisonSEHIdentifiersRAIIObject::Ident_AbnormalTermination
clang::PoisonSEHIdentifiersRAIIObject::Ident_GetExceptionCode
clang::PoisonSEHIdentifiersRAIIObject::Ident_GetExceptionInfo
clang::PoisonSEHIdentifiersRAIIObject::Ident__abnormal_termination
clang::PoisonSEHIdentifiersRAIIObject::Ident__exception_code
clang::PoisonSEHIdentifiersRAIIObject::Ident__exception_info
clang::PoisonSEHIdentifiersRAIIObject::Ident___abnormal_termination
clang::PoisonSEHIdentifiersRAIIObject::Ident___exception_code
clang::PoisonSEHIdentifiersRAIIObject::Ident___exception_info
clang::BalancedDelimiterTracker::P
clang::BalancedDelimiterTracker::Kind
clang::BalancedDelimiterTracker::Close
clang::BalancedDelimiterTracker::FinalToken
clang::BalancedDelimiterTracker::Consumer
clang::BalancedDelimiterTracker::LOpen
clang::BalancedDelimiterTracker::LClose
clang::BalancedDelimiterTracker::getDepth
clang::BalancedDelimiterTracker::diagnoseOverflow
clang::BalancedDelimiterTracker::diagnoseMissingClose
clang::BalancedDelimiterTracker::getOpenLocation
clang::BalancedDelimiterTracker::getCloseLocation
clang::BalancedDelimiterTracker::getRange
clang::BalancedDelimiterTracker::consumeOpen
clang::BalancedDelimiterTracker::expectAndConsume
clang::BalancedDelimiterTracker::consumeClose
clang::BalancedDelimiterTracker::skipToEnd
clang::DestroyTemplateIdAnnotationsRAIIObj::Container