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