diff options
author | Ben Langmuir <blangmuir@apple.com> | 2014-06-30 20:04:14 +0000 |
---|---|---|
committer | Ben Langmuir <blangmuir@apple.com> | 2014-06-30 20:04:14 +0000 |
commit | 33c8090a2f7f2e6d554f84a15a573a7ff7d3f59d (patch) | |
tree | b113aa17c51cca823bd7f4199507d87b48e80264 /clang/lib/Frontend | |
parent | 557c54d6ca95d0bf6569364b40e6ba6e0defa47f (diff) | |
download | bcm5719-llvm-33c8090a2f7f2e6d554f84a15a573a7ff7d3f59d.tar.gz bcm5719-llvm-33c8090a2f7f2e6d554f84a15a573a7ff7d3f59d.zip |
Consider module depedencies when checking a preamble in libclang
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
Diffstat (limited to 'clang/lib/Frontend')
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/DependencyFile.cpp | 99 |
3 files changed, 114 insertions, 15 deletions
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index df50c407735..3c2b4235018 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1609,6 +1609,9 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( Clang->setSourceManager(new SourceManager(getDiagnostics(), Clang->getFileManager())); + auto PreambleDepCollector = std::make_shared<DependencyCollector>(); + Clang->addDependencyCollector(PreambleDepCollector); + std::unique_ptr<PrecompilePreambleAction> Act; Act.reset(new PrecompilePreambleAction(*this)); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { @@ -1657,29 +1660,20 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // so we can verify whether they have changed or not. FilesInPreamble.clear(); SourceManager &SourceMgr = Clang->getSourceManager(); - const llvm::MemoryBuffer *MainFileBuffer - = SourceMgr.getBuffer(SourceMgr.getMainFileID()); - for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(), - FEnd = SourceMgr.fileinfo_end(); - F != FEnd; - ++F) { - const FileEntry *File = F->second->OrigEntry; - if (!File) - continue; - const llvm::MemoryBuffer *Buffer = F->second->getRawBuffer(); - if (Buffer == MainFileBuffer) + for (auto &Filename : PreambleDepCollector->getDependencies()) { + const FileEntry *File = Clang->getFileManager().getFile(Filename); + if (!File || File == SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())) continue; - if (time_t ModTime = File->getModificationTime()) { FilesInPreamble[File->getName()] = PreambleFileHash::createForFile( - F->second->getSize(), ModTime); + File->getSize(), ModTime); } else { - assert(F->second->getSize() == Buffer->getBufferSize()); + llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File); FilesInPreamble[File->getName()] = PreambleFileHash::createForMemoryBuffer(Buffer); } } - + PreambleRebuildCounter = 1; PreprocessorOpts.eraseRemappedFile( PreprocessorOpts.remapped_file_buffer_end() - 1); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index b5efb14dc2e..60f8ae8fdf0 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -288,6 +288,9 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, getHeaderSearchOpts().Sysroot); + for (auto &Listener : DependencyCollectors) + Listener->attachToPreprocessor(*PP); + // If we don't have a collector, but we are collecting module dependencies, // then we're the top level compiler instance and need to create one. if (!ModuleDepCollector && !DepOpts.ModuleDependencyOutputDir.empty()) @@ -1233,6 +1236,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, if (ModuleDepCollector) ModuleDepCollector->attachToASTReader(*ModuleManager); + for (auto &Listener : DependencyCollectors) + Listener->attachToASTReader(*ModuleManager); + // Try to load the module file. unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; switch (ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module, 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 @@ -29,6 +29,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 != "<built-in>" && (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 { std::vector<std::string> Files; |