diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 5613d372d20c..ca910befcd22 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -135,19 +135,31 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return NewModule? NewlyLoaded : AlreadyLoaded; } +static void getModuleFileAncestors( + ModuleFile *F, + llvm::SmallPtrSetImpl &Ancestors) { + Ancestors.insert(F); + for (ModuleFile *Importer : F->ImportedBy) + getModuleFileAncestors(Importer, Ancestors); +} + 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. Collect the files to remove from + // the cache below, since rebuilding them will create new files at the old + // locations. + llvm::SmallPtrSet Ancestors; + getModuleFileAncestors(*(last-1), Ancestors); + assert(Ancestors.count(*first) && "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) { @@ -165,6 +177,10 @@ void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last, mod->setASTFile(nullptr); } } + + if (Ancestors.count(*victim)) + FileMgr.invalidateCache((*victim)->File); + delete *victim; }