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