Coverage Report

Created: 2017-03-23 08:39

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
Line
Count
Source (jump to first uncovered line)
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/Sema.h"
22
23
namespace clang {
24
  // TODO: move ParsingClassDefinition here.
25
  // TODO: move TentativeParsingAction here.
26
27
  /// \brief 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
1.03M
        : S(P.getActions()), DiagnosticPool(nullptr) {
54
1.03M
      if (
activate1.03M
)
{336k
55
336k
        State = S.PushParsingDeclaration(DiagnosticPool);
56
336k
        Active = true;
57
693k
      } else {
58
693k
        Active = false;
59
693k
      }
60
1.03M
    }
61
    SuppressAccessChecks(SuppressAccessChecks &&Other)
62
      : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
63
133k
        State(Other.State), Active(Other.Active) {
64
133k
      Other.Active = false;
65
133k
    }
66
    void operator=(SuppressAccessChecks &&Other) = delete;
67
68
336k
    void done() {
69
336k
      assert(Active && "trying to end an inactive suppression");
70
336k
      S.PopParsingDeclaration(State, nullptr);
71
336k
      Active = false;
72
336k
    }
73
74
333k
    void redelay() {
75
333k
      assert(!Active && "redelaying without having ended first");
76
333k
      if (!DiagnosticPool.pool_empty())
77
295
        S.redelayDiagnostics(DiagnosticPool);
78
333k
      assert(DiagnosticPool.pool_empty());
79
333k
    }
80
81
1.16M
    ~SuppressAccessChecks() {
82
1.16M
      if (
Active1.16M
)
done()0
;
83
1.16M
    }
84
  };
85
86
  /// \brief 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
6.29M
        : Actions(P.getActions()), DiagnosticPool(nullptr) {
103
6.29M
      push();
104
6.29M
    }
105
106
    /// Creates a RAII object whose pool is optionally parented by another.
107
    ParsingDeclRAIIObject(Parser &P,
108
                          const sema::DelayedDiagnosticPool *parentPool)
109
6.20M
        : Actions(P.getActions()), DiagnosticPool(parentPool) {
110
6.20M
      push();
111
6.20M
    }
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
726k
          DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
119
726k
      if (
other726k
)
{57.5k
120
57.5k
        DiagnosticPool.steal(other->DiagnosticPool);
121
57.5k
        other->abort();
122
57.5k
      }
123
726k
      push();
124
726k
    }
125
126
13.2M
    ~ParsingDeclRAIIObject() {
127
13.2M
      abort();
128
13.2M
    }
129
130
0
    sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
131
0
      return DiagnosticPool;
132
0
    }
133
6.20M
    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
134
6.20M
      return DiagnosticPool;
135
6.20M
    }
136
137
    /// Resets the RAII object for a new declaration.
138
73.4k
    void reset() {
139
73.4k
      abort();
140
73.4k
      push();
141
73.4k
    }
142
143
    /// Signals that the context was completed without an appropriate
144
    /// declaration being parsed.
145
14.2M
    void abort() {
146
14.2M
      pop(nullptr);
147
14.2M
    }
148
149
7.02M
    void complete(Decl *D) {
150
7.02M
      assert(!Popped && "ParsingDeclaration has already been popped!");
151
7.02M
      pop(D);
152
7.02M
    }
153
154
    /// Unregister this object from Sema, but remember all the
155
    /// diagnostics that were emitted into it.
156
0
    void abortAndRemember() {
157
0
      pop(nullptr);
158
0
    }
159
160
  private:
161
13.2M
    void push() {
162
13.2M
      State = Actions.PushParsingDeclaration(DiagnosticPool);
163
13.2M
      Popped = false;
164
13.2M
    }
165
166
21.2M
    void pop(Decl *D) {
167
21.2M
      if (
!Popped21.2M
)
{13.2M
168
13.2M
        Actions.PopParsingDeclaration(State, D);
169
13.2M
        Popped = true;
170
13.2M
      }
171
21.2M
    }
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
5.79M
        ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
182
    ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
183
      : DeclSpec(P.getAttrFactory()),
184
726k
        ParsingRAII(P, RAII) {}
185
186
6.20M
    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
187
6.20M
      return ParsingRAII.getDelayedDiagnosticPool();
188
6.20M
    }
189
190
305k
    void complete(Decl *D) {
191
305k
      ParsingRAII.complete(D);
192
305k
    }
193
194
897k
    void abort() {
195
897k
      ParsingRAII.abort();
196
897k
    }
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, TheContext C)
205
5.06M
      : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
206
5.06M
    }
207
208
1.36M
    const ParsingDeclSpec &getDeclSpec() const {
209
1.36M
      return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
210
1.36M
    }
211
212
867k
    ParsingDeclSpec &getMutableDeclSpec() const {
213
867k
      return const_cast<ParsingDeclSpec&>(getDeclSpec());
214
867k
    }
215
216
73.4k
    void clear() {
217
73.4k
      Declarator::clear();
218
73.4k
      ParsingRAII.reset();
219
73.4k
    }
220
221
5.13M
    void complete(Decl *D) {
222
5.13M
      ParsingRAII.complete(D);
223
5.13M
    }
224
  };
225
226
  /// A class for parsing a field declarator.
227
  class ParsingFieldDeclarator : public FieldDeclarator {
228
    ParsingDeclRAIIObject ParsingRAII;
229
230
  public:
231
    ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
232
1.13M
      : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
233
1.13M
    }
234
235
0
    const ParsingDeclSpec &getDeclSpec() const {
236
0
      return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
237
0
    }
238
239
0
    ParsingDeclSpec &getMutableDeclSpec() const {
240
0
      return const_cast<ParsingDeclSpec&>(getDeclSpec());
241
0
    }
242
243
1.13M
    void complete(Decl *D) {
244
1.13M
      ParsingRAII.complete(D);
245
1.13M
    }
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
28.9k
    ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
259
28.9k
      Diags.IncrementAllExtensionsSilenced();
260
28.9k
    }
261
262
28.9k
    ~ExtensionRAIIObject() {
263
28.9k
      Diags.DecrementAllExtensionsSilenced();
264
28.9k
    }
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 &p, bool Value = true)
275
8.74M
      : P(p), OldVal(P.ColonIsSacred) {
276
8.74M
      P.ColonIsSacred = Value;
277
8.74M
    }
278
    
279
    /// restore - This can be used to restore the state early, before the dtor
280
    /// is run.
281
11.2M
    void restore() {
282
11.2M
      P.ColonIsSacred = OldVal;
283
11.2M
    }
284
    
285
8.74M
    ~ColonProtectionRAIIObject() {
286
8.74M
      restore();
287
8.74M
    }
288
  };
289
  
290
  /// \brief 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 &GTIO, bool Val)
297
12.4M
    : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
298
12.4M
      GreaterThanIsOperator = Val;
299
12.4M
    }
300
    
301
12.4M
    ~GreaterThanIsOperatorScope() {
302
12.4M
      GreaterThanIsOperator = OldGreaterThanIsOperator;
303
12.4M
    }
304
  };
305
  
306
  class InMessageExpressionRAIIObject {
307
    bool &InMessageExpression;
308
    bool OldValue;
309
    
310
  public:
311
    InMessageExpressionRAIIObject(Parser &P, bool Value)
312
      : InMessageExpression(P.InMessageExpression), 
313
4.18M
        OldValue(P.InMessageExpression) {
314
4.18M
      InMessageExpression = Value;
315
4.18M
    }
316
    
317
4.18M
    ~InMessageExpressionRAIIObject() {
318
4.18M
      InMessageExpression = OldValue;
319
4.18M
    }
320
  };
321
  
322
  /// \brief 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 ParenCount, BracketCount, BraceCount;
327
  public:
328
    ParenBraceBracketBalancer(Parser &p)
329
      : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
330
9.11M
        BraceCount(p.BraceCount) { }
331
    
332
9.11M
    ~ParenBraceBracketBalancer() {
333
9.11M
      P.ParenCount = ParenCount;
334
9.11M
      P.BracketCount = BracketCount;
335
9.11M
      P.BraceCount = BraceCount;
336
9.11M
    }
337
  };
338
339
  class PoisonSEHIdentifiersRAIIObject {
340
    PoisonIdentifierRAIIObject Ident_AbnormalTermination;
341
    PoisonIdentifierRAIIObject Ident_GetExceptionCode;
342
    PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
343
    PoisonIdentifierRAIIObject Ident__abnormal_termination;
344
    PoisonIdentifierRAIIObject Ident__exception_code;
345
    PoisonIdentifierRAIIObject Ident__exception_info;
346
    PoisonIdentifierRAIIObject Ident___abnormal_termination;
347
    PoisonIdentifierRAIIObject Ident___exception_code;
348
    PoisonIdentifierRAIIObject Ident___exception_info;
349
  public:
350
    PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
351
      : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
352
        Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
353
        Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
354
        Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
355
        Ident__exception_code(Self.Ident__exception_code, NewValue),
356
        Ident__exception_info(Self.Ident__exception_info, NewValue),
357
        Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
358
        Ident___exception_code(Self.Ident___exception_code, NewValue),
359
889k
        Ident___exception_info(Self.Ident___exception_info, NewValue) {
360
889k
    }
361
  };
362
363
  /// \brief RAII class that helps handle the parsing of an open/close delimiter
364
  /// pair, such as braces { ... } or parentheses ( ... ).
365
  class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
366
    Parser& P;
367
    tok::TokenKind Kind, Close, FinalToken;
368
    SourceLocation (Parser::*Consumer)();
369
    SourceLocation LOpen, LClose;
370
    
371
12.3M
    unsigned short &getDepth() {
372
12.3M
      switch (Kind) {
373
1.89M
        case tok::l_brace: return P.BraceCount;
374
984k
        case tok::l_square: return P.BracketCount;
375
9.43M
        case tok::l_paren: return P.ParenCount;
376
0
        
default: 0
llvm_unreachable0
("Wrong token kind");
377
12.3M
      }
378
12.3M
    }
379
    
380
    enum { MaxDepth = 256 };
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
12.3M
    {
391
12.3M
      switch (Kind) {
392
0
        
default: 0
llvm_unreachable0
("Unexpected balanced token");
393
1.89M
        case tok::l_brace:
394
1.89M
          Close = tok::r_brace; 
395
1.89M
          Consumer = &Parser::ConsumeBrace;
396
1.89M
          break;
397
9.45M
        case tok::l_paren:
398
9.45M
          Close = tok::r_paren; 
399
9.45M
          Consumer = &Parser::ConsumeParen;
400
9.45M
          break;
401
0
          
402
984k
        case tok::l_square:
403
984k
          Close = tok::r_square; 
404
984k
          Consumer = &Parser::ConsumeBracket;
405
984k
          break;
406
12.3M
      }      
407
12.3M
    }
408
    
409
11.3M
    SourceLocation getOpenLocation() const { return LOpen; }
410
10.1M
    SourceLocation getCloseLocation() const { return LClose; }
411
432k
    SourceRange getRange() const { return SourceRange(LOpen, LClose); }
412
    
413
12.2M
    bool consumeOpen() {
414
12.2M
      if (!P.Tok.is(Kind))
415
190
        return true;
416
12.2M
      
417
12.2M
      
if (12.2M
getDepth() < P.getLangOpts().BracketDepth12.2M
)
{12.2M
418
12.2M
        LOpen = (P.*Consumer)();
419
12.2M
        return false;
420
12.2M
      }
421
12.2M
      
422
5
      return diagnoseOverflow();
423
12.2M
    }
424
425
    bool expectAndConsume(unsigned DiagID = diag::err_expected,
426
                          const char *Msg = "",
427
                          tok::TokenKind SkipToTok = tok::unknown);
428
12.2M
    bool consumeClose() {
429
12.2M
      if (
P.Tok.is(Close)12.2M
)
{12.2M
430
12.2M
        LClose = (P.*Consumer)();
431
12.2M
        return false;
432
6.59k
      } else 
if (6.59k
P.Tok.is(tok::semi) && 6.59k
P.NextToken().is(Close)28
)
{17
433
17
        SourceLocation SemiLoc = P.ConsumeToken();
434
17
        P.Diag(SemiLoc, diag::err_unexpected_semi)
435
17
            << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
436
17
        LClose = (P.*Consumer)();
437
17
        return false;
438
17
      }
439
12.2M
      
440
6.57k
      return diagnoseMissingClose();
441
12.2M
    }
442
    void skipToEnd();
443
  };
444
445
} // end namespace clang
446
447
#endif