summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/FileManager.h3
-rw-r--r--clang/include/clang/Serialization/ModuleManager.h2
-rw-r--r--clang/lib/Basic/FileManager.cpp7
-rw-r--r--clang/lib/Serialization/ASTReader.cpp9
-rw-r--r--clang/lib/Serialization/ModuleManager.cpp39
5 files changed, 33 insertions, 27 deletions
diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h
index 023433b25be..f0f0d2f2e19 100644
--- a/clang/include/clang/Basic/FileManager.h
+++ b/clang/include/clang/Basic/FileManager.h
@@ -242,7 +242,8 @@ public:
/// MemoryBuffer if successful, otherwise returning null.
llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
std::string *ErrorStr = nullptr,
- bool isVolatile = false);
+ bool isVolatile = false,
+ bool ShouldCloseOpenFile = true);
llvm::MemoryBuffer *getBufferForFile(StringRef Filename,
std::string *ErrorStr = nullptr);
diff --git a/clang/include/clang/Serialization/ModuleManager.h b/clang/include/clang/Serialization/ModuleManager.h
index 08c1735ab01..3259902222d 100644
--- a/clang/include/clang/Serialization/ModuleManager.h
+++ b/clang/include/clang/Serialization/ModuleManager.h
@@ -18,6 +18,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Serialization/Module.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
@@ -194,6 +195,7 @@ public:
/// \brief Remove the given set of modules.
void removeModules(ModuleIterator first, ModuleIterator last,
+ llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
ModuleMap *modMap);
/// \brief Add an in-memory buffer the list of known buffers
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index aa06020be61..17622c7e13f 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -388,7 +388,7 @@ void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
llvm::MemoryBuffer *FileManager::
getBufferForFile(const FileEntry *Entry, std::string *ErrorStr,
- bool isVolatile) {
+ bool isVolatile, bool ShouldCloseOpenFile) {
std::unique_ptr<llvm::MemoryBuffer> Result;
std::error_code ec;
@@ -405,7 +405,10 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr,
/*RequiresNullTerminator=*/true, isVolatile);
if (ErrorStr)
*ErrorStr = ec.message();
- Entry->closeFile();
+ // FIXME: we need a set of APIs that can make guarantees about whether a
+ // FileEntry is open or not.
+ if (ShouldCloseOpenFile)
+ Entry->closeFile();
return Result.release();
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0c9f263faf1..777ea831981 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -3464,8 +3464,13 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
case OutOfDate:
case VersionMismatch:
case ConfigurationMismatch:
- case HadErrors:
+ case HadErrors: {
+ llvm::SmallPtrSet<ModuleFile *, 4> LoadedSet;
+ for (const ImportedModule &IM : Loaded)
+ LoadedSet.insert(IM.Mod);
+
ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(),
+ LoadedSet,
Context.getLangOpts().Modules
? &PP.getHeaderSearchInfo().getModuleMap()
: nullptr);
@@ -3475,7 +3480,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
GlobalIndex.reset();
ModuleMgr.setGlobalIndex(nullptr);
return ReadResult;
-
+ }
case Success:
break;
}
diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp
index c5b4dd120cb..0a9ea69d695 100644
--- a/clang/lib/Serialization/ModuleManager.cpp
+++ b/clang/lib/Serialization/ModuleManager.cpp
@@ -109,8 +109,15 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
ec = llvm::MemoryBuffer::getSTDIN(New->Buffer);
if (ec)
ErrorStr = ec.message();
- } else
- New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr));
+ } else {
+ // Leave the FileEntry open so if it gets read again by another
+ // ModuleManager it must be the same underlying file.
+ // FIXME: Because FileManager::getFile() doesn't guarantee that it will
+ // give us an open file, this may not be 100% reliable.
+ New->Buffer.reset(FileMgr.getBufferForFile(New->File, &ErrorStr,
+ /*IsVolatile*/false,
+ /*ShouldClose*/false));
+ }
if (!New->Buffer)
return Missing;
@@ -135,31 +142,16 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return NewModule? NewlyLoaded : AlreadyLoaded;
}
-static void getModuleFileAncestors(
- ModuleFile *F,
- llvm::SmallPtrSetImpl<ModuleFile *> &Ancestors) {
- Ancestors.insert(F);
- for (ModuleFile *Importer : F->ImportedBy)
- getModuleFileAncestors(Importer, Ancestors);
-}
-
-void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last,
- ModuleMap *modMap) {
+void ModuleManager::removeModules(
+ ModuleIterator first, ModuleIterator last,
+ llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
+ ModuleMap *modMap) {
if (first == last)
return;
// Collect the set of module file pointers that we'll be removing.
llvm::SmallPtrSet<ModuleFile *, 4> 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<ModuleFile *, 4> 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) {
@@ -178,7 +170,10 @@ void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last,
}
}
- if (Ancestors.count(*victim))
+ // Files that didn't make it through ReadASTCore successfully will be
+ // rebuilt (or there was an error). Invalidate them so that we can load the
+ // new files that will be renamed over the old ones.
+ if (LoadedSuccessfully.count(*victim) == 0)
FileMgr.invalidateCache((*victim)->File);
delete *victim;
OpenPOWER on IntegriCloud