Viewing file: PreprocessorLexer.h (6.13 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===- PreprocessorLexer.h - C Language Family Lexer ------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file /// Defines the PreprocessorLexer interface. // //===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H #define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
#include "clang/Basic/FileEntry.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include <cassert>
namespace clang {
class FileEntry; class Preprocessor;
class PreprocessorLexer { virtual void anchor();
protected: friend class Preprocessor;
// Preprocessor object controlling lexing. Preprocessor *PP = nullptr;
/// The SourceManager FileID corresponding to the file being lexed. const FileID FID;
/// Number of SLocEntries before lexing the file. unsigned InitialNumSLocEntries = 0;
//===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. //===--------------------------------------------------------------------===//
/// True when parsing \#XXX; turns '\\n' into a tok::eod token. bool ParsingPreprocessorDirective = false;
/// True after \#include; turns \<xx> or "xxx" into a tok::header_name token. bool ParsingFilename = false;
/// True if in raw mode. /// /// Raw mode disables interpretation of tokens and is a far faster mode to /// lex in than non-raw-mode. This flag: /// 1. If EOF of the current lexer is found, the include stack isn't popped. /// 2. Identifier information is not looked up for identifier tokens. As an /// effect of this, implicit macro expansion is naturally disabled. /// 3. "#" tokens at the start of a line are treated as normal tokens, not /// implicitly transformed by the lexer. /// 4. All diagnostic messages are disabled. /// 5. No callbacks are made into the preprocessor. /// /// Note that in raw mode that the PP pointer may be null. bool LexingRawMode = false;
/// A state machine that detects the \#ifndef-wrapping a file /// idiom for the multiple-include optimization. MultipleIncludeOpt MIOpt;
/// Information about the set of \#if/\#ifdef/\#ifndef blocks /// we are currently in. SmallVector<PPConditionalInfo, 4> ConditionalStack;
PreprocessorLexer() : FID() {} PreprocessorLexer(Preprocessor *pp, FileID fid); virtual ~PreprocessorLexer() = default;
virtual void IndirectLex(Token& Result) = 0;
/// Return the source location for the next observable location. virtual SourceLocation getSourceLocation() = 0;
//===--------------------------------------------------------------------===// // #if directive handling.
/// pushConditionalLevel - When we enter a \#if directive, this keeps track of /// what we are currently in for diagnostic emission (e.g. \#if with missing /// \#endif). void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, bool FoundNonSkip, bool FoundElse) { PPConditionalInfo CI; CI.IfLoc = DirectiveStart; CI.WasSkipping = WasSkipping; CI.FoundNonSkip = FoundNonSkip; CI.FoundElse = FoundElse; ConditionalStack.push_back(CI); } void pushConditionalLevel(const PPConditionalInfo &CI) { ConditionalStack.push_back(CI); }
/// popConditionalLevel - Remove an entry off the top of the conditional /// stack, returning information about it. If the conditional stack is empty, /// this returns true and does not fill in the arguments. bool popConditionalLevel(PPConditionalInfo &CI) { if (ConditionalStack.empty()) return true; CI = ConditionalStack.pop_back_val(); return false; }
/// Return the top of the conditional stack. /// \pre This requires that there be a conditional active. PPConditionalInfo &peekConditionalLevel() { assert(!ConditionalStack.empty() && "No conditionals active!"); return ConditionalStack.back(); }
unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
public: PreprocessorLexer(const PreprocessorLexer &) = delete; PreprocessorLexer &operator=(const PreprocessorLexer &) = delete;
//===--------------------------------------------------------------------===// // Misc. lexing methods.
/// Lex a token, producing a header-name token if possible. void LexIncludeFilename(Token &FilenameTok);
/// Inform the lexer whether or not we are currently lexing a /// preprocessor directive. void setParsingPreprocessorDirective(bool f) { ParsingPreprocessorDirective = f; }
/// Return true if this lexer is in raw mode or not. bool isLexingRawMode() const { return LexingRawMode; }
/// Return the preprocessor object for this lexer. Preprocessor *getPP() const { return PP; }
FileID getFileID() const { assert(PP && "PreprocessorLexer::getFileID() should only be used with a Preprocessor"); return FID; }
/// Number of SLocEntries before lexing the file. unsigned getInitialNumSLocEntries() const { return InitialNumSLocEntries; }
/// getFileEntry - Return the FileEntry corresponding to this FileID. Like /// getFileID(), this only works for lexers with attached preprocessors. OptionalFileEntryRef getFileEntry() const;
/// Iterator that traverses the current stack of preprocessor /// conditional directives (\#if/\#ifdef/\#ifndef). using conditional_iterator = SmallVectorImpl<PPConditionalInfo>::const_iterator;
conditional_iterator conditional_begin() const { return ConditionalStack.begin(); }
conditional_iterator conditional_end() const { return ConditionalStack.end(); }
void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) { ConditionalStack.clear(); ConditionalStack.append(CL.begin(), CL.end()); } };
} // namespace clang
#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H
|