Coverage Report

Created: 2018-07-19 20:53

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/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/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
1.75M
        : S(P.getActions()), DiagnosticPool(nullptr) {
55
1.75M
      if (activate) {
56
414k
        State = S.PushParsingDeclaration(DiagnosticPool);
57
414k
        Active = true;
58
1.34M
      } else {
59
1.34M
        Active = false;
60
1.34M
      }
61
1.75M
    }
62
    SuppressAccessChecks(SuppressAccessChecks &&Other)
63
      : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
64
164k
        State(Other.State), Active(Other.Active) {
65
164k
      Other.Active = false;
66
164k
    }
67
    void operator=(SuppressAccessChecks &&Other) = delete;
68
69
414k
    void done() {
70
414k
      assert(Active && "trying to end an inactive suppression");
71
414k
      S.PopParsingDeclaration(State, nullptr);
72
414k
      Active = false;
73
414k
    }
74
75
347k
    void redelay() {
76
347k
      assert(!Active && "redelaying without having ended first");
77
347k
      if (!DiagnosticPool.pool_empty())
78
719
        S.redelayDiagnostics(DiagnosticPool);
79
347k
      assert(DiagnosticPool.pool_empty());
80
347k
    }
81
82
1.92M
    ~SuppressAccessChecks() {
83
1.92M
      if (Active) 
done()0
;
84
1.92M
    }
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
8.99M
        : Actions(P.getActions()), DiagnosticPool(nullptr) {
104
8.99M
      push();
105
8.99M
    }
106
107
    /// Creates a RAII object whose pool is optionally parented by another.
108
    ParsingDeclRAIIObject(Parser &P,
109
                          const sema::DelayedDiagnosticPool *parentPool)
110
11.0M
        : Actions(P.getActions()), DiagnosticPool(parentPool) {
111
11.0M
      push();
112
11.0M
    }
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
4.59M
          DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
120
4.59M
      if (other) {
121
1.16M
        DiagnosticPool.steal(other->DiagnosticPool);
122
1.16M
        other->abort();
123
1.16M
      }
124
4.59M
      push();
125
4.59M
    }
126
127
24.6M
    ~ParsingDeclRAIIObject() {
128
24.6M
      abort();
129
24.6M
    }
130
131
0
    sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
132
0
      return DiagnosticPool;
133
0
    }
134
11.0M
    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
135
11.0M
      return DiagnosticPool;
136
11.0M
    }
137
138
    /// Resets the RAII object for a new declaration.
139
64.4k
    void reset() {
140
64.4k
      abort();
141
64.4k
      push();
142
64.4k
    }
143
144
    /// Signals that the context was completed without an appropriate
145
    /// declaration being parsed.
146
27.6M
    void abort() {
147
27.6M
      pop(nullptr);
148
27.6M
    }
149
150
12.4M
    void complete(Decl *D) {
151
12.4M
      assert(!Popped && "ParsingDeclaration has already been popped!");
152
12.4M
      pop(D);
153
12.4M
    }
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
24.7M
    void push() {
163
24.7M
      State = Actions.PushParsingDeclaration(DiagnosticPool);
164
24.7M
      Popped = false;
165
24.7M
    }
166
167
40.0M
    void pop(Decl *D) {
168
40.0M
      if (!Popped) {
169
24.7M
        Actions.PopParsingDeclaration(State, D);
170
24.7M
        Popped = true;
171
24.7M
      }
172
40.0M
    }
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
7.40M
        ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
183
    ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
184
      : DeclSpec(P.getAttrFactory()),
185
4.59M
        ParsingRAII(P, RAII) {}
186
187
11.0M
    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
188
11.0M
      return ParsingRAII.getDelayedDiagnosticPool();
189
11.0M
    }
190
191
911k
    void complete(Decl *D) {
192
911k
      ParsingRAII.complete(D);
193
911k
    }
194
195
1.73M
    void abort() {
196
1.73M
      ParsingRAII.abort();
197
1.73M
    }
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
10.2M
      : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
207
10.2M
    }
208
209
3.48M
    const ParsingDeclSpec &getDeclSpec() const {
210
3.48M
      return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
211
3.48M
    }
212
213
1.68M
    ParsingDeclSpec &getMutableDeclSpec() const {
214
1.68M
      return const_cast<ParsingDeclSpec&>(getDeclSpec());
215
1.68M
    }
216
217
64.4k
    void clear() {
218
64.4k
      Declarator::clear();
219
64.4k
      ParsingRAII.reset();
220
64.4k
    }
221
222
10.3M
    void complete(Decl *D) {
223
10.3M
      ParsingRAII.complete(D);
224
10.3M
    }
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
768k
      : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
234
768k
    }
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
768k
    void complete(Decl *D) {
245
768k
      ParsingRAII.complete(D);
246
768k
    }
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
20.2k
    ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
260
20.2k
      Diags.IncrementAllExtensionsSilenced();
261
20.2k
    }
262
263
20.2k
    ~ExtensionRAIIObject() {
264
20.2k
      Diags.DecrementAllExtensionsSilenced();
265
20.2k
    }
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
26.5M
      : P(p), OldVal(P.ColonIsSacred) {
277
26.5M
      P.ColonIsSacred = Value;
278
26.5M
    }
279
    
280
    /// restore - This can be used to restore the state early, before the dtor
281
    /// is run.
282
33.0M
    void restore() {
283
33.0M
      P.ColonIsSacred = OldVal;
284
33.0M
    }
285
    
286
26.5M
    ~ColonProtectionRAIIObject() {
287
26.5M
      restore();
288
26.5M
    }
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
26.9M
    : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
299
26.9M
      GreaterThanIsOperator = Val;
300
26.9M
    }
301
    
302
26.9M
    ~GreaterThanIsOperatorScope() {
303
26.9M
      GreaterThanIsOperator = OldGreaterThanIsOperator;
304
26.9M
    }
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
10.3M
        OldValue(P.InMessageExpression) {
315
10.3M
      InMessageExpression = Value;
316
10.3M
    }
317
    
318
10.3M
    ~InMessageExpressionRAIIObject() {
319
10.3M
      InMessageExpression = OldValue;
320
10.3M
    }
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
25.1M
        BraceCount(p.BraceCount) { }
332
    
333
25.1M
    ~ParenBraceBracketBalancer() {
334
25.1M
      P.AngleBrackets.clear(P);
335
25.1M
      P.ParenCount = ParenCount;
336
25.1M
      P.BracketCount = BracketCount;
337
25.1M
      P.BraceCount = BraceCount;
338
25.1M
    }
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
1.83M
        Ident___exception_info(Self.Ident___exception_info, NewValue) {
362
1.83M
    }
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
24.4M
    unsigned short &getDepth() {
374
24.4M
      switch (Kind) {
375
24.4M
        
case tok::l_brace: return P.BraceCount4.67M
;
376
24.4M
        
case tok::l_square: return P.BracketCount994k
;
377
24.4M
        
case tok::l_paren: return P.ParenCount18.7M
;
378
24.4M
        
default: 0
llvm_unreachable0
("Wrong token kind");
379
24.4M
      }
380
24.4M
    }
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
24.4M
    {
391
24.4M
      switch (Kind) {
392
24.4M
        
default: 0
llvm_unreachable0
("Unexpected balanced token");
393
24.4M
        case tok::l_brace:
394
4.67M
          Close = tok::r_brace; 
395
4.67M
          Consumer = &Parser::ConsumeBrace;
396
4.67M
          break;
397
24.4M
        case tok::l_paren:
398
18.7M
          Close = tok::r_paren; 
399
18.7M
          Consumer = &Parser::ConsumeParen;
400
18.7M
          break;
401
24.4M
          
402
24.4M
        case tok::l_square:
403
994k
          Close = tok::r_square; 
404
994k
          Consumer = &Parser::ConsumeBracket;
405
994k
          break;
406
24.4M
      }      
407
24.4M
    }
408
    
409
22.9M
    SourceLocation getOpenLocation() const { return LOpen; }
410
18.9M
    SourceLocation getCloseLocation() const { return LClose; }
411
1.02M
    SourceRange getRange() const { return SourceRange(LOpen, LClose); }
412
    
413
24.0M
    bool consumeOpen() {
414
24.0M
      if (!P.Tok.is(Kind))
415
588
        return true;
416
24.0M
      
417
24.0M
      if (getDepth() < P.getLangOpts().BracketDepth) {
418
24.0M
        LOpen = (P.*Consumer)();
419
24.0M
        return false;
420
24.0M
      }
421
4
      
422
4
      return diagnoseOverflow();
423
4
    }
424
425
    bool expectAndConsume(unsigned DiagID = diag::err_expected,
426
                          const char *Msg = "",
427
                          tok::TokenKind SkipToTok = tok::unknown);
428
24.3M
    bool consumeClose() {
429
24.3M
      if (P.Tok.is(Close)) {
430
24.3M
        LClose = (P.*Consumer)();
431
24.3M
        return false;
432
24.3M
      } else 
if (11.4k
P.Tok.is(tok::semi)11.4k
&&
P.NextToken().is(Close)32
) {
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
11.4k
      
440
11.4k
      return diagnoseMissingClose();
441
11.4k
    }
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
9.91M
        : Container(Container) {}
454
455
9.91M
    ~DestroyTemplateIdAnnotationsRAIIObj() {
456
9.91M
      for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
457
9.91M
               Container.begin(),
458
9.91M
             E = Container.end();
459
12.3M
           I != E; 
++I2.44M
)
460
2.44M
        (*I)->Destroy();
461
9.91M
      Container.clear();
462
9.91M
    }
463
  };
464
} // end namespace clang
465
466
#endif