From 33c8090a2f7f2e6d554f84a15a573a7ff7d3f59d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Mon, 30 Jun 2014 20:04:14 +0000 Subject: Consider module depedencies when checking a preamble in libclang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add module dependencies (header files, module map files) to the list of files to check when deciding whether to rebuild a preamble. That fixes using preambles with module imports so long as they are in non-overridden files. My intent is to use to unify the existing dependency collectors to the new “DependencyCollectory” interface from this commit, starting with the DependencyFileGenerator. llvm-svn: 212060 --- clang/lib/Frontend/DependencyFile.cpp | 99 +++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) (limited to 'clang/lib/Frontend/DependencyFile.cpp') diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp index e72be89b4e9..0b9c0d47dc3 100644 --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -28,6 +28,105 @@ using namespace clang; +namespace { +struct DepCollectorPPCallbacks : public PPCallbacks { + DependencyCollector &DepCollector; + SourceManager &SM; + DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM) + : DepCollector(L), SM(SM) { } + + void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) override { + if (Reason != PPCallbacks::EnterFile) + 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! + const FileEntry *FE = + SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc))); + if (!FE) + return; + + StringRef Filename = FE->getName(); + + // Remove leading "./" (or ".//" or "././" etc.) + while (Filename.size() > 2 && Filename[0] == '.' && + llvm::sys::path::is_separator(Filename[1])) { + Filename = Filename.substr(1); + while (llvm::sys::path::is_separator(Filename[0])) + Filename = Filename.substr(1); + } + + DepCollector.maybeAddDependency(Filename, /*FromModule*/false, + FileType != SrcMgr::C_User, + /*IsModuleFile*/false, /*IsMissing*/false); + } + + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, + StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, + StringRef SearchPath, StringRef RelativePath, + const Module *Imported) override { + if (!File) + DepCollector.maybeAddDependency(FileName, /*FromModule*/false, + /*IsSystem*/false, /*IsModuleFile*/false, + /*IsMissing*/true); + // Files that actually exist are handled by FileChanged. + } + + void EndOfMainFile() override { + DepCollector.finishedMainFile(); + } +}; + +struct DepCollectorASTListener : public ASTReaderListener { + DependencyCollector &DepCollector; + DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { } + bool needsInputFileVisitation() override { return true; } + bool needsSystemInputFileVisitation() override { + return DepCollector.needSystemDependencies(); + } + void visitModuleFile(StringRef Filename) override { + DepCollector.maybeAddDependency(Filename, /*FromModule*/true, + /*IsSystem*/false, /*IsModuleFile*/true, + /*IsMissing*/false); + } + bool visitInputFile(StringRef Filename, bool IsSystem, + bool IsOverridden) override { + if (IsOverridden) + return true; + + DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem, + /*IsModuleFile*/false, /*IsMissing*/false); + return true; + } +}; +} // end anonymous namespace + +void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule, + bool IsSystem, bool IsModuleFile, + bool IsMissing) { + if (Seen.insert(Filename) && + sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) + Dependencies.push_back(Filename); +} + +bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule, + bool IsSystem, bool IsModuleFile, + bool IsMissing) { + return Filename != "" && (needSystemDependencies() || !IsSystem); +} + +DependencyCollector::~DependencyCollector() { } +void DependencyCollector::attachToPreprocessor(Preprocessor &PP) { + PP.addPPCallbacks(new DepCollectorPPCallbacks(*this, PP.getSourceManager())); +} +void DependencyCollector::attachToASTReader(ASTReader &R) { + R.addListener(new DepCollectorASTListener(*this)); +} + namespace { /// Private implementation for DependencyFileGenerator class DFGImpl : public PPCallbacks { -- cgit v1.2.3