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