Author: Jan Svoboda Date: 2021-11-18T13:01:07+01:00 New Revision: 197576c40986085cbd5250283e1e80a2679c9cf0
URL: https://github.com/llvm/llvm-project/commit/197576c40986085cbd5250283e1e80a2679c9cf0 DIFF: https://github.com/llvm/llvm-project/commit/197576c40986085cbd5250283e1e80a2679c9cf0.diff LOG: [clang][lex] Refactor check for the first file include This patch refactors the code that checks whether a file has just been included for the first time. The `HeaderSearch::FirstTimeLexingFile` function is removed and the information is threaded to the original call site from `HeaderSearch::ShouldEnterIncludeFile`. This will make it possible to avoid tracking the number of includes in a follow up patch. Depends on D114092. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D114093 Added: Modified: clang/include/clang/Lex/HeaderSearch.h clang/include/clang/Lex/Lexer.h clang/include/clang/Lex/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp clang/lib/Lex/Lexer.cpp clang/lib/Lex/PPDirectives.cpp clang/lib/Lex/PPLexerChange.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index 7f5c4c260f55..b3445703f782 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -443,8 +443,8 @@ class HeaderSearch { /// \return false if \#including the file will have no effect or true /// if we should include it. bool ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File, - bool isImport, bool ModulesEnabled, - Module *M); + bool isImport, bool ModulesEnabled, Module *M, + bool &IsFirstIncludeOfFile); /// Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. @@ -489,11 +489,6 @@ class HeaderSearch { getFileInfo(File).ControllingMacro = ControllingMacro; } - /// Return true if this is the first time encountering this header. - bool FirstTimeLexingFile(const FileEntry *File) { - return getFileInfo(File).NumIncludes == 1; - } - /// Determine whether this file is intended to be safe from /// multiple inclusions, e.g., it has \#pragma once or a controlling /// macro. diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h index 82f494e7c8cf..ba1706b1d13e 100644 --- a/clang/include/clang/Lex/Lexer.h +++ b/clang/include/clang/Lex/Lexer.h @@ -128,6 +128,9 @@ class Lexer : public PreprocessorLexer { bool HasLeadingEmptyMacro; + /// True if this is the first time we're lexing the input file. + bool IsFirstTimeLexingFile; + // NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n', // it also points to '\n.' const char *NewLinePtr; @@ -142,19 +145,22 @@ class Lexer : public PreprocessorLexer { /// with the specified preprocessor managing the lexing process. This lexer /// assumes that the associated file buffer and Preprocessor objects will /// outlive it, so it doesn't take ownership of either of them. - Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, Preprocessor &PP); + Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, Preprocessor &PP, + bool IsFirstIncludeOfFile = true); /// Lexer constructor - Create a new raw lexer object. This object is only /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the /// text range will outlive it, so it doesn't take ownership of it. Lexer(SourceLocation FileLoc, const LangOptions &LangOpts, - const char *BufStart, const char *BufPtr, const char *BufEnd); + const char *BufStart, const char *BufPtr, const char *BufEnd, + bool IsFirstIncludeOfFile = true); /// Lexer constructor - Create a new raw lexer object. This object is only /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the /// text range will outlive it, so it doesn't take ownership of it. Lexer(FileID FID, const llvm::MemoryBufferRef &FromFile, - const SourceManager &SM, const LangOptions &LangOpts); + const SourceManager &SM, const LangOptions &LangOpts, + bool IsFirstIncludeOfFile = true); Lexer(const Lexer &) = delete; Lexer &operator=(const Lexer &) = delete; @@ -563,6 +569,9 @@ class Lexer : public PreprocessorLexer { static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM); + /// Check if this is the first time we're lexing the input file. + bool isFirstTimeLexingFile() const { return IsFirstTimeLexingFile; } + private: //===--------------------------------------------------------------------===// // Internal implementation interfaces. diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index b8b0890e3243..ea96bb12bec6 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1368,7 +1368,7 @@ class Preprocessor { /// /// Emits a diagnostic, doesn't enter the file, and returns true on error. bool EnterSourceFile(FileID FID, const DirectoryLookup *Dir, - SourceLocation Loc); + SourceLocation Loc, bool IsFirstIncludeOfFile = true); /// Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 150e7edb12c1..a0b60118a1a8 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -1310,9 +1310,12 @@ void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE, bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File, bool isImport, - bool ModulesEnabled, Module *M) { + bool ModulesEnabled, Module *M, + bool &IsFirstIncludeOfFile) { ++NumIncluded; // Count # of attempted #includes. + IsFirstIncludeOfFile = false; + // Get information about this file. HeaderFileInfo &FileInfo = getFileInfo(File); @@ -1387,6 +1390,8 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, // Increment the number of times this file has been included. ++FileInfo.NumIncludes; + IsFirstIncludeOfFile = FileInfo.NumIncludes == 1; + return true; } diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 55693c8f8cf4..38467a1835d0 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -133,10 +133,10 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr, /// assumes that the associated file buffer and Preprocessor objects will /// outlive it, so it doesn't take ownership of either of them. Lexer::Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, - Preprocessor &PP) + Preprocessor &PP, bool IsFirstIncludeOfFile) : PreprocessorLexer(&PP, FID), FileLoc(PP.getSourceManager().getLocForStartOfFile(FID)), - LangOpts(PP.getLangOpts()) { + LangOpts(PP.getLangOpts()), IsFirstTimeLexingFile(IsFirstIncludeOfFile) { InitLexer(InputFile.getBufferStart(), InputFile.getBufferStart(), InputFile.getBufferEnd()); @@ -147,8 +147,10 @@ Lexer::Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the text /// range will outlive it, so it doesn't take ownership of it. Lexer::Lexer(SourceLocation fileloc, const LangOptions &langOpts, - const char *BufStart, const char *BufPtr, const char *BufEnd) - : FileLoc(fileloc), LangOpts(langOpts) { + const char *BufStart, const char *BufPtr, const char *BufEnd, + bool IsFirstIncludeOfFile) + : FileLoc(fileloc), LangOpts(langOpts), + IsFirstTimeLexingFile(IsFirstIncludeOfFile) { InitLexer(BufStart, BufPtr, BufEnd); // We *are* in raw mode. @@ -159,9 +161,11 @@ Lexer::Lexer(SourceLocation fileloc, const LangOptions &langOpts, /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the text /// range will outlive it, so it doesn't take ownership of it. Lexer::Lexer(FileID FID, const llvm::MemoryBufferRef &FromFile, - const SourceManager &SM, const LangOptions &langOpts) + const SourceManager &SM, const LangOptions &langOpts, + bool IsFirstIncludeOfFile) : Lexer(SM.getLocForStartOfFile(FID), langOpts, FromFile.getBufferStart(), - FromFile.getBufferStart(), FromFile.getBufferEnd()) {} + FromFile.getBufferStart(), FromFile.getBufferEnd(), + IsFirstIncludeOfFile) {} void Lexer::resetExtendedTokenMode() { assert(PP && "Cannot reset token mode without a preprocessor"); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 79cfc7fcd5fd..ef7a5351953e 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -2143,12 +2143,14 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( IsImportDecl || IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import; + bool IsFirstIncludeOfFile = false; + // Ask HeaderInfo if we should enter this #include file. If not, #including // this file will have no effect. if (Action == Enter && File && - !HeaderInfo.ShouldEnterIncludeFile(*this, &File->getFileEntry(), - EnterOnce, getLangOpts().Modules, - SuggestedModule.getModule())) { + !HeaderInfo.ShouldEnterIncludeFile( + *this, &File->getFileEntry(), EnterOnce, getLangOpts().Modules, + SuggestedModule.getModule(), IsFirstIncludeOfFile)) { // Even if we've already preprocessed this header once and know that we // don't need to see its contents again, we still need to import it if it's // modular because we might not have imported it from this submodule before. @@ -2340,7 +2342,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( } // If all is good, enter the new file! - if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation())) + if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation(), + IsFirstIncludeOfFile)) return {ImportAction::None}; // Determine if we're switching to building a new submodule, and which one. diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 9fbce62e51d6..f8b0a2c5f71b 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -67,7 +67,8 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const { /// EnterSourceFile - Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, - SourceLocation Loc) { + SourceLocation Loc, + bool IsFirstIncludeOfFile) { assert(!CurTokenLexer && "Cannot #include a file inside a macro!"); ++NumEnteredSourceFiles; @@ -91,7 +92,8 @@ bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, CodeCompletionFileLoc.getLocWithOffset(CodeCompletionOffset); } - EnterSourceFileWithLexer(new Lexer(FID, *InputFile, *this), CurDir); + EnterSourceFileWithLexer( + new Lexer(FID, *InputFile, *this, IsFirstIncludeOfFile), CurDir); return false; } @@ -377,7 +379,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc, CurPPLexer->MIOpt.GetDefinedMacro()) { if (!isMacroDefined(ControllingMacro) && DefinedMacro != ControllingMacro && - HeaderInfo.FirstTimeLexingFile(FE)) { + CurLexer->isFirstTimeLexingFile()) { // If the edit distance between the two macros is more than 50%, // DefinedMacro may not be header guard, or can be header guard of _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits