1 //===- PreprocessorLexer.h - C Language Family Lexer ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Defines the PreprocessorLexer interface.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
16 #define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
18 #include "clang/Lex/MultipleIncludeOpt.h"
19 #include "clang/Lex/Token.h"
20 #include "clang/Basic/SourceLocation.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/SmallVector.h"
30 class PreprocessorLexer {
31 virtual void anchor();
34 friend class Preprocessor;
36 // Preprocessor object controlling lexing.
37 Preprocessor *PP = nullptr;
39 /// The SourceManager FileID corresponding to the file being lexed.
42 /// \brief Number of SLocEntries before lexing the file.
43 unsigned InitialNumSLocEntries = 0;
45 //===--------------------------------------------------------------------===//
46 // Context-specific lexing flags set by the preprocessor.
47 //===--------------------------------------------------------------------===//
49 /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token.
50 bool ParsingPreprocessorDirective = false;
52 /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal
54 bool ParsingFilename = false;
56 /// \brief True if in raw mode.
58 /// Raw mode disables interpretation of tokens and is a far faster mode to
59 /// lex in than non-raw-mode. This flag:
60 /// 1. If EOF of the current lexer is found, the include stack isn't popped.
61 /// 2. Identifier information is not looked up for identifier tokens. As an
62 /// effect of this, implicit macro expansion is naturally disabled.
63 /// 3. "#" tokens at the start of a line are treated as normal tokens, not
64 /// implicitly transformed by the lexer.
65 /// 4. All diagnostic messages are disabled.
66 /// 5. No callbacks are made into the preprocessor.
68 /// Note that in raw mode that the PP pointer may be null.
69 bool LexingRawMode = false;
71 /// \brief A state machine that detects the \#ifndef-wrapping a file
72 /// idiom for the multiple-include optimization.
73 MultipleIncludeOpt MIOpt;
75 /// \brief Information about the set of \#if/\#ifdef/\#ifndef blocks
76 /// we are currently in.
77 SmallVector<PPConditionalInfo, 4> ConditionalStack;
79 PreprocessorLexer() : FID() {}
80 PreprocessorLexer(Preprocessor *pp, FileID fid);
81 virtual ~PreprocessorLexer() = default;
83 virtual void IndirectLex(Token& Result) = 0;
85 /// \brief Return the source location for the next observable location.
86 virtual SourceLocation getSourceLocation() = 0;
88 //===--------------------------------------------------------------------===//
89 // #if directive handling.
91 /// pushConditionalLevel - When we enter a \#if directive, this keeps track of
92 /// what we are currently in for diagnostic emission (e.g. \#if with missing
94 void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
95 bool FoundNonSkip, bool FoundElse) {
97 CI.IfLoc = DirectiveStart;
98 CI.WasSkipping = WasSkipping;
99 CI.FoundNonSkip = FoundNonSkip;
100 CI.FoundElse = FoundElse;
101 ConditionalStack.push_back(CI);
103 void pushConditionalLevel(const PPConditionalInfo &CI) {
104 ConditionalStack.push_back(CI);
107 /// popConditionalLevel - Remove an entry off the top of the conditional
108 /// stack, returning information about it. If the conditional stack is empty,
109 /// this returns true and does not fill in the arguments.
110 bool popConditionalLevel(PPConditionalInfo &CI) {
111 if (ConditionalStack.empty())
113 CI = ConditionalStack.pop_back_val();
117 /// \brief Return the top of the conditional stack.
118 /// \pre This requires that there be a conditional active.
119 PPConditionalInfo &peekConditionalLevel() {
120 assert(!ConditionalStack.empty() && "No conditionals active!");
121 return ConditionalStack.back();
124 unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
127 PreprocessorLexer(const PreprocessorLexer &) = delete;
128 PreprocessorLexer &operator=(const PreprocessorLexer &) = delete;
130 //===--------------------------------------------------------------------===//
131 // Misc. lexing methods.
133 /// \brief After the preprocessor has parsed a \#include, lex and
134 /// (potentially) macro expand the filename.
136 /// If the sequence parsed is not lexically legal, emit a diagnostic and
137 /// return a result EOD token.
138 void LexIncludeFilename(Token &Result);
140 /// \brief Inform the lexer whether or not we are currently lexing a
141 /// preprocessor directive.
142 void setParsingPreprocessorDirective(bool f) {
143 ParsingPreprocessorDirective = f;
146 /// \brief Return true if this lexer is in raw mode or not.
147 bool isLexingRawMode() const { return LexingRawMode; }
149 /// \brief Return the preprocessor object for this lexer.
150 Preprocessor *getPP() const { return PP; }
152 FileID getFileID() const {
154 "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
158 /// \brief Number of SLocEntries before lexing the file.
159 unsigned getInitialNumSLocEntries() const {
160 return InitialNumSLocEntries;
163 /// getFileEntry - Return the FileEntry corresponding to this FileID. Like
164 /// getFileID(), this only works for lexers with attached preprocessors.
165 const FileEntry *getFileEntry() const;
167 /// \brief Iterator that traverses the current stack of preprocessor
168 /// conditional directives (\#if/\#ifdef/\#ifndef).
169 using conditional_iterator =
170 SmallVectorImpl<PPConditionalInfo>::const_iterator;
172 conditional_iterator conditional_begin() const {
173 return ConditionalStack.begin();
176 conditional_iterator conditional_end() const {
177 return ConditionalStack.end();
180 void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) {
181 ConditionalStack.clear();
182 ConditionalStack.append(CL.begin(), CL.end());
188 #endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H