]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Parse/RAIIObjectsForParser.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / 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   /// 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   /// 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, DeclaratorContext 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   /// 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   /// 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.AngleBrackets.clear(P);
335       P.ParenCount = ParenCount;
336       P.BracketCount = BracketCount;
337       P.BraceCount = BraceCount;
338     }
339   };
340
341   class PoisonSEHIdentifiersRAIIObject {
342     PoisonIdentifierRAIIObject Ident_AbnormalTermination;
343     PoisonIdentifierRAIIObject Ident_GetExceptionCode;
344     PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
345     PoisonIdentifierRAIIObject Ident__abnormal_termination;
346     PoisonIdentifierRAIIObject Ident__exception_code;
347     PoisonIdentifierRAIIObject Ident__exception_info;
348     PoisonIdentifierRAIIObject Ident___abnormal_termination;
349     PoisonIdentifierRAIIObject Ident___exception_code;
350     PoisonIdentifierRAIIObject Ident___exception_info;
351   public:
352     PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
353       : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
354         Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
355         Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
356         Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
357         Ident__exception_code(Self.Ident__exception_code, NewValue),
358         Ident__exception_info(Self.Ident__exception_info, NewValue),
359         Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
360         Ident___exception_code(Self.Ident___exception_code, NewValue),
361         Ident___exception_info(Self.Ident___exception_info, NewValue) {
362     }
363   };
364
365   /// RAII class that helps handle the parsing of an open/close delimiter
366   /// pair, such as braces { ... } or parentheses ( ... ).
367   class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
368     Parser& P;
369     tok::TokenKind Kind, Close, FinalToken;
370     SourceLocation (Parser::*Consumer)();
371     SourceLocation LOpen, LClose;
372
373     unsigned short &getDepth() {
374       switch (Kind) {
375         case tok::l_brace: return P.BraceCount;
376         case tok::l_square: return P.BracketCount;
377         case tok::l_paren: return P.ParenCount;
378         default: llvm_unreachable("Wrong token kind");
379       }
380     }
381
382     bool diagnoseOverflow();
383     bool diagnoseMissingClose();
384
385   public:
386     BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
387                              tok::TokenKind FinalToken = tok::semi)
388       : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
389         P(p), Kind(k), FinalToken(FinalToken)
390     {
391       switch (Kind) {
392         default: llvm_unreachable("Unexpected balanced token");
393         case tok::l_brace:
394           Close = tok::r_brace;
395           Consumer = &Parser::ConsumeBrace;
396           break;
397         case tok::l_paren:
398           Close = tok::r_paren;
399           Consumer = &Parser::ConsumeParen;
400           break;
401
402         case tok::l_square:
403           Close = tok::r_square;
404           Consumer = &Parser::ConsumeBracket;
405           break;
406       }
407     }
408
409     SourceLocation getOpenLocation() const { return LOpen; }
410     SourceLocation getCloseLocation() const { return LClose; }
411     SourceRange getRange() const { return SourceRange(LOpen, LClose); }
412
413     bool consumeOpen() {
414       if (!P.Tok.is(Kind))
415         return true;
416
417       if (getDepth() < P.getLangOpts().BracketDepth) {
418         LOpen = (P.*Consumer)();
419         return false;
420       }
421
422       return diagnoseOverflow();
423     }
424
425     bool expectAndConsume(unsigned DiagID = diag::err_expected,
426                           const char *Msg = "",
427                           tok::TokenKind SkipToTok = tok::unknown);
428     bool consumeClose() {
429       if (P.Tok.is(Close)) {
430         LClose = (P.*Consumer)();
431         return false;
432       } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
433         SourceLocation SemiLoc = P.ConsumeToken();
434         P.Diag(SemiLoc, diag::err_unexpected_semi)
435             << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
436         LClose = (P.*Consumer)();
437         return false;
438       }
439
440       return diagnoseMissingClose();
441     }
442     void skipToEnd();
443   };
444
445   /// RAIIObject to destroy the contents of a SmallVector of
446   /// TemplateIdAnnotation pointers and clear the vector.
447   class DestroyTemplateIdAnnotationsRAIIObj {
448     SmallVectorImpl<TemplateIdAnnotation *> &Container;
449
450   public:
451     DestroyTemplateIdAnnotationsRAIIObj(
452         SmallVectorImpl<TemplateIdAnnotation *> &Container)
453         : Container(Container) {}
454
455     ~DestroyTemplateIdAnnotationsRAIIObj() {
456       for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
457                Container.begin(),
458              E = Container.end();
459            I != E; ++I)
460         (*I)->Destroy();
461       Container.clear();
462     }
463   };
464 } // end namespace clang
465
466 #endif