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 /// 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 "clang/Basic/SourceLocation.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> into a tok::angle_string_literal 53 /// token. 54 bool ParsingFilename = false; 55 56 /// True if in raw mode. 57 /// 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. 67 /// 68 /// Note that in raw mode that the PP pointer may be null. 69 bool LexingRawMode = false; 70 71 /// A state machine that detects the \#ifndef-wrapping a file 72 /// idiom for the multiple-include optimization. 73 MultipleIncludeOpt MIOpt; 74 75 /// Information about the set of \#if/\#ifdef/\#ifndef blocks 76 /// we are currently in. 77 SmallVector<PPConditionalInfo, 4> ConditionalStack; 78 PreprocessorLexer()79 PreprocessorLexer() : FID() {} 80 PreprocessorLexer(Preprocessor *pp, FileID fid); 81 virtual ~PreprocessorLexer() = default; 82 83 virtual void IndirectLex(Token& Result) = 0; 84 85 /// Return the source location for the next observable location. 86 virtual SourceLocation getSourceLocation() = 0; 87 88 //===--------------------------------------------------------------------===// 89 // #if directive handling. 90 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 93 /// \#endif). pushConditionalLevel(SourceLocation DirectiveStart,bool WasSkipping,bool FoundNonSkip,bool FoundElse)94 void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, 95 bool FoundNonSkip, bool FoundElse) { 96 PPConditionalInfo CI; 97 CI.IfLoc = DirectiveStart; 98 CI.WasSkipping = WasSkipping; 99 CI.FoundNonSkip = FoundNonSkip; 100 CI.FoundElse = FoundElse; 101 ConditionalStack.push_back(CI); 102 } pushConditionalLevel(const PPConditionalInfo & CI)103 void pushConditionalLevel(const PPConditionalInfo &CI) { 104 ConditionalStack.push_back(CI); 105 } 106 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. popConditionalLevel(PPConditionalInfo & CI)110 bool popConditionalLevel(PPConditionalInfo &CI) { 111 if (ConditionalStack.empty()) 112 return true; 113 CI = ConditionalStack.pop_back_val(); 114 return false; 115 } 116 117 /// Return the top of the conditional stack. 118 /// \pre This requires that there be a conditional active. peekConditionalLevel()119 PPConditionalInfo &peekConditionalLevel() { 120 assert(!ConditionalStack.empty() && "No conditionals active!"); 121 return ConditionalStack.back(); 122 } 123 getConditionalStackDepth()124 unsigned getConditionalStackDepth() const { return ConditionalStack.size(); } 125 126 public: 127 PreprocessorLexer(const PreprocessorLexer &) = delete; 128 PreprocessorLexer &operator=(const PreprocessorLexer &) = delete; 129 130 //===--------------------------------------------------------------------===// 131 // Misc. lexing methods. 132 133 /// After the preprocessor has parsed a \#include, lex and 134 /// (potentially) macro expand the filename. 135 /// 136 /// If the sequence parsed is not lexically legal, emit a diagnostic and 137 /// return a result EOD token. 138 void LexIncludeFilename(Token &FilenameTok); 139 140 /// Inform the lexer whether or not we are currently lexing a 141 /// preprocessor directive. setParsingPreprocessorDirective(bool f)142 void setParsingPreprocessorDirective(bool f) { 143 ParsingPreprocessorDirective = f; 144 } 145 146 /// Return true if this lexer is in raw mode or not. isLexingRawMode()147 bool isLexingRawMode() const { return LexingRawMode; } 148 149 /// Return the preprocessor object for this lexer. getPP()150 Preprocessor *getPP() const { return PP; } 151 getFileID()152 FileID getFileID() const { 153 assert(PP && 154 "PreprocessorLexer::getFileID() should only be used with a Preprocessor"); 155 return FID; 156 } 157 158 /// Number of SLocEntries before lexing the file. getInitialNumSLocEntries()159 unsigned getInitialNumSLocEntries() const { 160 return InitialNumSLocEntries; 161 } 162 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; 166 167 /// Iterator that traverses the current stack of preprocessor 168 /// conditional directives (\#if/\#ifdef/\#ifndef). 169 using conditional_iterator = 170 SmallVectorImpl<PPConditionalInfo>::const_iterator; 171 conditional_begin()172 conditional_iterator conditional_begin() const { 173 return ConditionalStack.begin(); 174 } 175 conditional_end()176 conditional_iterator conditional_end() const { 177 return ConditionalStack.end(); 178 } 179 setConditionalLevels(ArrayRef<PPConditionalInfo> CL)180 void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) { 181 ConditionalStack.clear(); 182 ConditionalStack.append(CL.begin(), CL.end()); 183 } 184 }; 185 186 } // namespace clang 187 188 #endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H 189