From 04b9c70da6be729bd828f0d3e41b91b945591814 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Fri, 30 May 2014 17:42:15 +0000 Subject: [PATCH] Invalidate the file system cache entries for files that may rebuild I thought we could get away without this, but it means that the FileEntry objects actually refer to the wrong files, since pcms are not updated inplace, they are atomically renamed into place after compiling a module. So we are close to the original behaviour of invalidating the cache for all modules being removed, but now we should only invalidate the ones that depend on whichever module failed to load. Unfortunately I haven't come up with a new test that didn't require a race between parallel invocations of clang. llvm-svn: 209910 --- clang/lib/Serialization/ModuleManager.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 5613d37..7b68726 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -135,19 +135,32 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return NewModule? NewlyLoaded : AlreadyLoaded; } +static void invalidateFileCacheForFileAndImporters( + ModuleFile *F, FileManager &FileMgr, + llvm::SmallPtrSetImpl &VictimSet) { + assert(VictimSet.count(F) && "removeModules() missing ancestor of module " + "that failed to load"); + FileMgr.invalidateCache(F->File); + F->File = nullptr; + for (ModuleFile *Importer : F->ImportedBy) + invalidateFileCacheForFileAndImporters(Importer, FileMgr, VictimSet); +} + void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last, ModuleMap *modMap) { if (first == last) return; - // The first file entry is about to be rebuilt (or there was an error), so - // there should be no references to it. Remove it from the cache to close it, - // as Windows doesn't seem to allow renaming over an open file. - FileMgr.invalidateCache((*first)->File); - // Collect the set of module file pointers that we'll be removing. llvm::SmallPtrSet victimSet(first, last); + // The last module file caused the load failure, so it and its ancestors in + // the module dependency tree will be rebuilt (or there was an error), so + // there should be no references to them. Remove them from the cache, + // since rebuilding them will create new files at the old locations. + invalidateFileCacheForFileAndImporters(*(last-1), FileMgr, victimSet); + assert((*first)->File == nullptr && "non-dependent module loaded"); + // Remove any references to the now-destroyed modules. for (unsigned i = 0, n = Chain.size(); i != n; ++i) { Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) { -- 2.7.4