diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -1118,6 +1118,9 @@ /// Return the filename of the file containing a SourceLocation. StringRef getFilename(SourceLocation SpellingLoc) const; + /// Return the filename of the file associated with a \p FileID. + Optional getFilename(FileID FID) const; + /// Return the source location corresponding to the first byte of /// the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { diff --git a/clang/include/clang/Lex/PPCallbacks.h b/clang/include/clang/Lex/PPCallbacks.h --- a/clang/include/clang/Lex/PPCallbacks.h +++ b/clang/include/clang/Lex/PPCallbacks.h @@ -49,6 +49,27 @@ FileID PrevFID = FileID()) { } + enum class LexedFileChangeReason { EnterFile, ExitFile }; + + /// Callback invoked whenever the \p Lexer moves to a different file for + /// lexing. Unlike \p FileChanged line number directives and other related + /// pragmas do not trigger callbacks to \p LexedFileChanged. + /// + /// \param FID The \p FileID that the \p Lexer moved to. + /// + /// \param Reason Whether the \p Lexer entered a new file or exited one. + /// + /// \param FileType The \p CharacteristicKind of the file the \p Lexer moved + /// to. + /// + /// \param PrevFID The \p FileID the \p Lexer was using before the change. + /// + /// \param Loc The location where the \p Lexer entered a new file from or the + /// location that the \p Lexer moved into after exiting a file. + virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID, SourceLocation Loc) {} + /// Callback invoked whenever a source file is skipped as the result /// of header guard optimization. /// @@ -420,6 +441,13 @@ Second->FileChanged(Loc, Reason, FileType, PrevFID); } + void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, FileID PrevFID, + SourceLocation Loc) override { + First->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc); + Second->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc); + } + void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, SrcMgr::CharacteristicKind FileType) override { First->FileSkipped(SkippedFile, FilenameTok, FileType); diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -1011,11 +1011,17 @@ /// Return the filename of the file containing a SourceLocation. StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const { - if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc))) - return F->getName(); + if (Optional Name = getFilename(getFileID(SpellingLoc))) + return *Name; return StringRef(); } +Optional SourceManager::getFilename(FileID FID) const { + if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID)) + return Entry->getFile().getName(); + return None; +} + /// getImmediateExpansionRange - Loc is required to be an expansion location. /// Return the start/end of the expansion information. CharSourceRange diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -31,23 +31,22 @@ namespace { struct DepCollectorPPCallbacks : public PPCallbacks { DependencyCollector &DepCollector; - SourceManager &SM; - DiagnosticsEngine &Diags; - DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM, - DiagnosticsEngine &Diags) - : DepCollector(L), SM(SM), Diags(Diags) {} - - void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override { - if (Reason != PPCallbacks::EnterFile) + Preprocessor &PP; + DepCollectorPPCallbacks(DependencyCollector &L, Preprocessor &PP) + : DepCollector(L), PP(PP) {} + + void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, FileID PrevFID, + SourceLocation Loc) override { + if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile) + return; + if (PP.getPredefinesFileID() == FID) return; // Dependency generation really does want to go all the way to the // file entry for a source location to find out what is depended on. // We do not want #line markers to affect dependency generation! - if (Optional Filename = SM.getNonBuiltinFilenameForID( - SM.getFileID(SM.getExpansionLoc(Loc)))) + if (Optional Filename = PP.getSourceManager().getFilename(FID)) DepCollector.maybeAddDependency( llvm::sys::path::remove_leading_dotslash(*Filename), /*FromModule*/ false, isSystem(FileType), /*IsModuleFile*/ false, @@ -90,7 +89,9 @@ /*IsMissing=*/false); } - void EndOfMainFile() override { DepCollector.finishedMainFile(Diags); } + void EndOfMainFile() override { + DepCollector.finishedMainFile(PP.getDiagnostics()); + } }; struct DepCollectorMMCallbacks : public ModuleMapCallbacks { @@ -175,8 +176,7 @@ DependencyCollector::~DependencyCollector() { } void DependencyCollector::attachToPreprocessor(Preprocessor &PP) { - PP.addPPCallbacks(std::make_unique( - *this, PP.getSourceManager(), PP.getDiagnostics())); + PP.addPPCallbacks(std::make_unique(*this, PP)); PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( std::make_unique(*this)); } diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -111,6 +111,7 @@ /// and start lexing tokens from it instead of the current buffer. void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, ConstSearchDirIterator CurDir) { + PreprocessorLexer *PrevPPLexer = CurPPLexer; // Add the current lexer to the include stack. if (CurPPLexer || CurTokenLexer) @@ -132,6 +133,15 @@ Callbacks->FileChanged(CurLexer->getFileLoc(), PPCallbacks::EnterFile, FileType); + FileID PrevFID; + SourceLocation EnterLoc; + if (PrevPPLexer) { + PrevFID = PrevPPLexer->getFileID(); + EnterLoc = PrevPPLexer->getSourceLocation(); + } + Callbacks->LexedFileChanged(CurLexer->getFileID(), + PPCallbacks::LexedFileChangeReason::EnterFile, + FileType, PrevFID, EnterLoc); } } @@ -486,10 +496,13 @@ // Notify the client, if desired, that we are in a new source file. if (Callbacks && !isEndOfMacro && CurPPLexer) { + SourceLocation Loc = CurPPLexer->getSourceLocation(); SrcMgr::CharacteristicKind FileType = - SourceMgr.getFileCharacteristic(CurPPLexer->getSourceLocation()); - Callbacks->FileChanged(CurPPLexer->getSourceLocation(), - PPCallbacks::ExitFile, FileType, ExitedFID); + SourceMgr.getFileCharacteristic(Loc); + Callbacks->FileChanged(Loc, PPCallbacks::ExitFile, FileType, ExitedFID); + Callbacks->LexedFileChanged(CurPPLexer->getFileID(), + PPCallbacks::LexedFileChangeReason::ExitFile, + FileType, ExitedFID, Loc); } // Restore conditional stack as well as the recorded