When loading a module fails because it is out of date, rebuild that
module in place. <rdar://problem/10138913>


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167539 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index c46e9f0..efe4421 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -88,6 +88,45 @@
   return std::make_pair(ModuleEntry, NewModule);
 }
 
+namespace {
+  /// \brief Predicate that checks whether a module file occurs within
+  /// the given set.
+  class IsInModuleFileSet : public std::unary_function<ModuleFile *, bool> {
+    llvm::SmallPtrSet<ModuleFile *, 4> &Removed;
+
+  public:
+    IsInModuleFileSet(llvm::SmallPtrSet<ModuleFile *, 4> &Removed)
+    : Removed(Removed) { }
+
+    bool operator()(ModuleFile *MF) const {
+      return Removed.count(MF);
+    }
+  };
+}
+
+void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last) {
+  if (first == last)
+    return;
+
+  // Collect the set of module file pointers that we'll be removing.
+  llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
+
+  // Remove any references to the now-destroyed modules.
+  IsInModuleFileSet checkInSet(victimSet);
+  for (unsigned i = 0, n = Chain.size(); i != n; ++i) {
+    Chain[i]->ImportedBy.remove_if(checkInSet);
+  }
+
+  // Delete the modules and erase them from the various structures.
+  for (ModuleIterator victim = first; victim != last; ++victim) {
+    Modules.erase((*victim)->File);
+    delete *victim;
+  }
+
+  // Remove the modules from the chain.
+  Chain.erase(first, last);
+}
+
 void ModuleManager::addInMemoryBuffer(StringRef FileName, 
                                       llvm::MemoryBuffer *Buffer) {