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