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_PreprocessorLexer_H 16 #define LLVM_CLANG_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 &) LLVM_DELETED_FUNCTION; 73 void operator=(const PreprocessorLexer &) LLVM_DELETED_FUNCTION; 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