Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
Line
Count
Source (jump to first uncovered line)
1
//===- PreprocessorLexer.h - C Language Family Lexer ------------*- 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
/// \file
10
/// Defines the PreprocessorLexer interface.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
15
#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
16
17
#include "clang/Lex/MultipleIncludeOpt.h"
18
#include "clang/Lex/Token.h"
19
#include "clang/Basic/SourceLocation.h"
20
#include "llvm/ADT/ArrayRef.h"
21
#include "llvm/ADT/SmallVector.h"
22
#include <cassert>
23
24
namespace clang {
25
26
class FileEntry;
27
class Preprocessor;
28
29
class PreprocessorLexer {
30
  virtual void anchor();
31
32
protected:
33
  friend class Preprocessor;
34
35
  // Preprocessor object controlling lexing.
36
  Preprocessor *PP = nullptr;
37
38
  /// The SourceManager FileID corresponding to the file being lexed.
39
  const FileID FID;
40
41
  /// Number of SLocEntries before lexing the file.
42
  unsigned InitialNumSLocEntries = 0;
43
44
  //===--------------------------------------------------------------------===//
45
  // Context-specific lexing flags set by the preprocessor.
46
  //===--------------------------------------------------------------------===//
47
48
  /// True when parsing \#XXX; turns '\\n' into a tok::eod token.
49
  bool ParsingPreprocessorDirective = false;
50
51
  /// True after \#include; turns \<xx> or "xxx" into a tok::header_name token.
52
  bool ParsingFilename = false;
53
54
  /// True if in raw mode.
55
  ///
56
  /// Raw mode disables interpretation of tokens and is a far faster mode to
57
  /// lex in than non-raw-mode.  This flag:
58
  ///  1. If EOF of the current lexer is found, the include stack isn't popped.
59
  ///  2. Identifier information is not looked up for identifier tokens.  As an
60
  ///     effect of this, implicit macro expansion is naturally disabled.
61
  ///  3. "#" tokens at the start of a line are treated as normal tokens, not
62
  ///     implicitly transformed by the lexer.
63
  ///  4. All diagnostic messages are disabled.
64
  ///  5. No callbacks are made into the preprocessor.
65
  ///
66
  /// Note that in raw mode that the PP pointer may be null.
67
  bool LexingRawMode = false;
68
69
  /// A state machine that detects the \#ifndef-wrapping a file
70
  /// idiom for the multiple-include optimization.
71
  MultipleIncludeOpt MIOpt;
72
73
  /// Information about the set of \#if/\#ifdef/\#ifndef blocks
74
  /// we are currently in.
75
  SmallVector<PPConditionalInfo, 4> ConditionalStack;
76
77
13.0M
  PreprocessorLexer() : FID() {}
78
  PreprocessorLexer(Preprocessor *pp, FileID fid);
79
13.6M
  virtual ~PreprocessorLexer() = default;
80
81
  virtual void IndirectLex(Token& Result) = 0;
82
83
  /// Return the source location for the next observable location.
84
  virtual SourceLocation getSourceLocation() = 0;
85
86
  //===--------------------------------------------------------------------===//
87
  // #if directive handling.
88
89
  /// pushConditionalLevel - When we enter a \#if directive, this keeps track of
90
  /// what we are currently in for diagnostic emission (e.g. \#if with missing
91
  /// \#endif).
92
  void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
93
10.8M
                            bool FoundNonSkip, bool FoundElse) {
94
10.8M
    PPConditionalInfo CI;
95
10.8M
    CI.IfLoc = DirectiveStart;
96
10.8M
    CI.WasSkipping = WasSkipping;
97
10.8M
    CI.FoundNonSkip = FoundNonSkip;
98
10.8M
    CI.FoundElse = FoundElse;
99
10.8M
    ConditionalStack.push_back(CI);
100
10.8M
  }
101
0
  void pushConditionalLevel(const PPConditionalInfo &CI) {
102
0
    ConditionalStack.push_back(CI);
103
0
  }
104
105
  /// popConditionalLevel - Remove an entry off the top of the conditional
106
  /// stack, returning information about it.  If the conditional stack is empty,
107
  /// this returns true and does not fill in the arguments.
108
10.8M
  bool popConditionalLevel(PPConditionalInfo &CI) {
109
10.8M
    if (ConditionalStack.empty())
110
2
      return true;
111
10.8M
    CI = ConditionalStack.pop_back_val();
112
10.8M
    return false;
113
10.8M
  }
114
115
  /// Return the top of the conditional stack.
116
  /// \pre This requires that there be a conditional active.
117
4.57M
  PPConditionalInfo &peekConditionalLevel() {
118
4.57M
    assert(!ConditionalStack.empty() && "No conditionals active!");
119
4.57M
    return ConditionalStack.back();
120
4.57M
  }
121
122
10.6M
  unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
123
124
public:
125
  PreprocessorLexer(const PreprocessorLexer &) = delete;
126
  PreprocessorLexer &operator=(const PreprocessorLexer &) = delete;
127
128
  //===--------------------------------------------------------------------===//
129
  // Misc. lexing methods.
130
131
  /// Lex a token, producing a header-name token if possible.
132
  void LexIncludeFilename(Token &FilenameTok);
133
134
  /// Inform the lexer whether or not we are currently lexing a
135
  /// preprocessor directive.
136
33.3k
  void setParsingPreprocessorDirective(bool f) {
137
33.3k
    ParsingPreprocessorDirective = f;
138
33.3k
  }
139
140
  /// Return true if this lexer is in raw mode or not.
141
1.44G
  bool isLexingRawMode() const { return LexingRawMode; }
142
143
  /// Return the preprocessor object for this lexer.
144
0
  Preprocessor *getPP() const { return PP; }
145
146
2.99M
  FileID getFileID() const {
147
2.99M
    assert(PP &&
148
2.99M
      "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
149
2.99M
    return FID;
150
2.99M
  }
151
152
  /// Number of SLocEntries before lexing the file.
153
478k
  unsigned getInitialNumSLocEntries() const {
154
478k
    return InitialNumSLocEntries;
155
478k
  }
156
157
  /// getFileEntry - Return the FileEntry corresponding to this FileID.  Like
158
  /// getFileID(), this only works for lexers with attached preprocessors.
159
  const FileEntry *getFileEntry() const;
160
161
  /// Iterator that traverses the current stack of preprocessor
162
  /// conditional directives (\#if/\#ifdef/\#ifndef).
163
  using conditional_iterator =
164
      SmallVectorImpl<PPConditionalInfo>::const_iterator;
165
166
0
  conditional_iterator conditional_begin() const {
167
0
    return ConditionalStack.begin();
168
0
  }
169
170
0
  conditional_iterator conditional_end() const {
171
0
    return ConditionalStack.end();
172
0
  }
173
174
28
  void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) {
175
28
    ConditionalStack.clear();
176
28
    ConditionalStack.append(CL.begin(), CL.end());
177
28
  }
178
};
179
180
} // namespace clang
181
182
#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H