]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Lex / PreprocessorLexer.h
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   PreprocessorLexer() : FID() {}
78   PreprocessorLexer(Preprocessor *pp, FileID fid);
79   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                             bool FoundNonSkip, bool FoundElse) {
94     PPConditionalInfo CI;
95     CI.IfLoc = DirectiveStart;
96     CI.WasSkipping = WasSkipping;
97     CI.FoundNonSkip = FoundNonSkip;
98     CI.FoundElse = FoundElse;
99     ConditionalStack.push_back(CI);
100   }
101   void pushConditionalLevel(const PPConditionalInfo &CI) {
102     ConditionalStack.push_back(CI);
103   }
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   bool popConditionalLevel(PPConditionalInfo &CI) {
109     if (ConditionalStack.empty())
110       return true;
111     CI = ConditionalStack.pop_back_val();
112     return false;
113   }
114
115   /// Return the top of the conditional stack.
116   /// \pre This requires that there be a conditional active.
117   PPConditionalInfo &peekConditionalLevel() {
118     assert(!ConditionalStack.empty() && "No conditionals active!");
119     return ConditionalStack.back();
120   }
121
122   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   void setParsingPreprocessorDirective(bool f) {
137     ParsingPreprocessorDirective = f;
138   }
139
140   /// Return true if this lexer is in raw mode or not.
141   bool isLexingRawMode() const { return LexingRawMode; }
142
143   /// Return the preprocessor object for this lexer.
144   Preprocessor *getPP() const { return PP; }
145
146   FileID getFileID() const {
147     assert(PP &&
148       "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
149     return FID;
150   }
151
152   /// Number of SLocEntries before lexing the file.
153   unsigned getInitialNumSLocEntries() const {
154     return InitialNumSLocEntries;
155   }
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   conditional_iterator conditional_begin() const {
167     return ConditionalStack.begin();
168   }
169
170   conditional_iterator conditional_end() const {
171     return ConditionalStack.end();
172   }
173
174   void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) {
175     ConditionalStack.clear();
176     ConditionalStack.append(CL.begin(), CL.end());
177   }
178 };
179
180 } // namespace clang
181
182 #endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H