summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r--clang/lib/Serialization/ASTReader.cpp95
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp2
-rw-r--r--clang/lib/Serialization/GlobalModuleIndex.cpp237
-rw-r--r--clang/lib/Serialization/ModuleManager.cpp116
4 files changed, 265 insertions, 185 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index cc9b5d506ac..6530bae5094 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -1616,8 +1616,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
|| StoredTime != File->getModificationTime()
#endif
)) {
- if (Complain)
+ if (Complain) {
Error(diag::err_fe_pch_file_modified, Filename, F.FileName);
+ }
+
IsOutOfDate = true;
}
@@ -1774,6 +1776,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
// location info are setup.
SourceLocation ImportLoc =
SourceLocation::getFromRawEncoding(Record[Idx++]);
+ off_t StoredSize = (off_t)Record[Idx++];
+ time_t StoredModTime = (time_t)Record[Idx++];
unsigned Length = Record[Idx++];
SmallString<128> ImportedFile(Record.begin() + Idx,
Record.begin() + Idx + Length);
@@ -1781,9 +1785,11 @@ ASTReader::ReadControlBlock(ModuleFile &F,
// Load the AST file.
switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
+ StoredSize, StoredModTime,
ClientLoadCapabilities)) {
case Failure: return Failure;
// If we have to ignore the dependency, we'll have to ignore this too.
+ case Missing: return Missing;
case OutOfDate: return OutOfDate;
case VersionMismatch: return VersionMismatch;
case ConfigurationMismatch: return ConfigurationMismatch;
@@ -2774,7 +2780,7 @@ bool ASTReader::loadGlobalIndex() {
StringRef ModuleCachePath
= getPreprocessor().getHeaderSearchInfo().getModuleCachePath();
std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> Result
- = GlobalModuleIndex::readIndex(FileMgr, ModuleCachePath);
+ = GlobalModuleIndex::readIndex(ModuleCachePath);
if (!Result.first)
return true;
@@ -2799,13 +2805,18 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
SmallVector<ImportedModule, 4> Loaded;
switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
/*ImportedBy=*/0, Loaded,
+ 0, 0,
ClientLoadCapabilities)) {
case Failure:
+ case Missing:
case OutOfDate:
case VersionMismatch:
case ConfigurationMismatch:
case HadErrors:
- ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());
+ ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(),
+ Context.getLangOpts().Modules
+ ? &PP.getHeaderSearchInfo().getModuleMap()
+ : 0);
// If we find that any modules are unusable, the global index is going
// to be out-of-date. Just remove it.
@@ -2923,27 +2934,54 @@ ASTReader::ReadASTCore(StringRef FileName,
SourceLocation ImportLoc,
ModuleFile *ImportedBy,
SmallVectorImpl<ImportedModule> &Loaded,
+ off_t ExpectedSize, time_t ExpectedModTime,
unsigned ClientLoadCapabilities) {
ModuleFile *M;
- bool NewModule;
std::string ErrorStr;
- llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportLoc,
- ImportedBy, CurrentGeneration,
- ErrorStr);
-
- if (!M) {
- // We couldn't load the module.
- std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
- + ErrorStr;
- Error(Msg);
- return Failure;
- }
+ ModuleManager::AddModuleResult AddResult
+ = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy,
+ CurrentGeneration, ExpectedSize, ExpectedModTime,
+ M, ErrorStr);
- if (!NewModule) {
- // We've already loaded this module.
+ switch (AddResult) {
+ case ModuleManager::AlreadyLoaded:
return Success;
+
+ case ModuleManager::NewlyLoaded:
+ // Load module file below.
+ break;
+
+ case ModuleManager::Missing:
+ // The module file was missing; if the client handle handle, that, return
+ // it.
+ if (ClientLoadCapabilities & ARR_Missing)
+ return Missing;
+
+ // Otherwise, return an error.
+ {
+ std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
+ + ErrorStr;
+ Error(Msg);
+ }
+ return Failure;
+
+ case ModuleManager::OutOfDate:
+ // We couldn't load the module file because it is out-of-date. If the
+ // client can handle out-of-date, return it.
+ if (ClientLoadCapabilities & ARR_OutOfDate)
+ return OutOfDate;
+
+ // Otherwise, return an error.
+ {
+ std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
+ + ErrorStr;
+ Error(Msg);
+ }
+ return Failure;
}
+ assert(M && "Missing module file");
+
// FIXME: This seems rather a hack. Should CurrentDir be part of the
// module?
if (FileName != "-") {
@@ -2997,6 +3035,7 @@ ASTReader::ReadASTCore(StringRef FileName,
break;
case Failure: return Failure;
+ case Missing: return Missing;
case OutOfDate: return OutOfDate;
case VersionMismatch: return VersionMismatch;
case ConfigurationMismatch: return ConfigurationMismatch;
@@ -3467,18 +3506,22 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
return true;
}
- if (const FileEntry *CurFile = CurrentModule->getASTFile()) {
- if (CurFile != F.File) {
- if (!Diags.isDiagnosticInFlight()) {
- Diag(diag::err_module_file_conflict)
- << CurrentModule->getTopLevelModuleName()
- << CurFile->getName()
- << F.File->getName();
+ if (!ParentModule) {
+ if (const FileEntry *CurFile = CurrentModule->getASTFile()) {
+ if (CurFile != F.File) {
+ if (!Diags.isDiagnosticInFlight()) {
+ Diag(diag::err_module_file_conflict)
+ << CurrentModule->getTopLevelModuleName()
+ << CurFile->getName()
+ << F.File->getName();
+ }
+ return true;
}
- return true;
}
+
+ CurrentModule->setASTFile(F.File);
}
- CurrentModule->setASTFile(F.File);
+
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
CurrentModule->InferSubmodules = InferSubmodules;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 716b1fbb306..724c8cf8254 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1034,6 +1034,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding
AddSourceLocation((*M)->ImportLoc, Record);
+ Record.push_back((*M)->File->getSize());
+ Record.push_back((*M)->File->getModificationTime());
// FIXME: This writes the absolute path for AST files we depend on.
const std::string &FileName = (*M)->FileName;
Record.push_back(FileName.size());
diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 7d34f85fd8b..8b5851dbe5d 100644
--- a/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -57,6 +57,8 @@ static const char * const IndexFileName = "modules.idx";
/// \brief The global index file version.
static const unsigned CurrentVersion = 1;
+ModuleFileNameResolver::~ModuleFileNameResolver() { }
+
//----------------------------------------------------------------------------//
// Global module index reader.
//----------------------------------------------------------------------------//
@@ -115,29 +117,16 @@ public:
typedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable;
-/// \brief Module information as it was loaded from the index file.
-struct LoadedModuleInfo {
- const FileEntry *File;
- SmallVector<unsigned, 2> Dependencies;
- SmallVector<unsigned, 2> ImportedBy;
-};
-
}
-GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr,
- llvm::MemoryBuffer *Buffer,
+GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer,
llvm::BitstreamCursor Cursor)
- : Buffer(Buffer), IdentifierIndex(),
+ : Buffer(Buffer), Resolver(), IdentifierIndex(),
NumIdentifierLookups(), NumIdentifierLookupHits()
{
- typedef llvm::DenseMap<unsigned, LoadedModuleInfo> LoadedModulesMap;
- LoadedModulesMap LoadedModules;
-
// Read the global index.
- unsigned LargestID = 0;
bool InGlobalIndexBlock = false;
bool Done = false;
- bool AnyOutOfDate = false;
while (!Done) {
llvm::BitstreamEntry Entry = Cursor.advance();
@@ -185,41 +174,33 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr,
case MODULE: {
unsigned Idx = 0;
unsigned ID = Record[Idx++];
- if (ID > LargestID)
- LargestID = ID;
-
- off_t Size = Record[Idx++];
- time_t ModTime = Record[Idx++];
+
+ // Make room for this module's information.
+ if (ID == Modules.size())
+ Modules.push_back(ModuleInfo());
+ else
+ Modules.resize(ID + 1);
+
+ // Size/modification time for this module file at the time the
+ // global index was built.
+ Modules[ID].Size = Record[Idx++];
+ Modules[ID].ModTime = Record[Idx++];
// File name.
unsigned NameLen = Record[Idx++];
- llvm::SmallString<64> FileName(Record.begin() + Idx,
- Record.begin() + Idx + NameLen);
+ Modules[ID].FileName.assign(Record.begin() + Idx,
+ Record.begin() + Idx + NameLen);
Idx += NameLen;
// Dependencies
unsigned NumDeps = Record[Idx++];
- llvm::SmallVector<unsigned, 2>
- Dependencies(Record.begin() + Idx, Record.begin() + Idx + NumDeps);
-
- // Find the file. If we can't find it, ignore it.
- const FileEntry *File = FileMgr.getFile(FileName, /*openFile=*/false,
- /*cacheFailure=*/false);
- if (!File) {
- AnyOutOfDate = true;
- break;
- }
-
- // If the module file is newer than the index, ignore it.
- if (File->getSize() != Size || File->getModificationTime() != ModTime) {
- AnyOutOfDate = true;
- break;
- }
+ Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(),
+ Record.begin() + Idx,
+ Record.begin() + Idx + NumDeps);
+ Idx += NumDeps;
- // Record this module. The dependencies will be resolved later.
- LoadedModuleInfo &Info = LoadedModules[ID];
- Info.File = File;
- Info.Dependencies.swap(Dependencies);
+ // Make sure we're at the end of the record.
+ assert(Idx == Record.size() && "More module info?");
break;
}
@@ -235,74 +216,11 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr,
}
}
- // If there are any modules that have gone out-of-date, prune out any modules
- // that depend on them.
- if (AnyOutOfDate) {
- // First, build back links in the module dependency graph.
- SmallVector<unsigned, 4> Stack;
- for (LoadedModulesMap::iterator LM = LoadedModules.begin(),
- LMEnd = LoadedModules.end();
- LM != LMEnd; ++LM) {
- unsigned ID = LM->first;
-
- // If this module is out-of-date, push it onto the stack.
- if (LM->second.File == 0)
- Stack.push_back(ID);
-
- for (unsigned I = 0, N = LM->second.Dependencies.size(); I != N; ++I) {
- unsigned DepID = LM->second.Dependencies[I];
- LoadedModulesMap::iterator Known = LoadedModules.find(DepID);
- if (Known == LoadedModules.end() || !Known->second.File) {
- // The dependency was out-of-date, so mark us as out of date.
- // This is just an optimization.
- if (LM->second.File)
- Stack.push_back(ID);
-
- LM->second.File = 0;
- continue;
- }
-
- // Record this reverse dependency.
- Known->second.ImportedBy.push_back(ID);
- }
- }
-
- // Second, walk the back links from out-of-date modules to those modules
- // that depend on them, making those modules out-of-date as well.
- while (!Stack.empty()) {
- unsigned ID = Stack.back();
- Stack.pop_back();
-
- LoadedModuleInfo &Info = LoadedModules[ID];
- for (unsigned I = 0, N = Info.ImportedBy.size(); I != N; ++I) {
- unsigned FromID = Info.ImportedBy[I];
- if (LoadedModules[FromID].File) {
- LoadedModules[FromID].File = 0;
- Stack.push_back(FromID);
- }
- }
- }
- }
-
- // Allocate the vector containing information about all of the modules.
- Modules.resize(LargestID + 1);
- for (LoadedModulesMap::iterator LM = LoadedModules.begin(),
- LMEnd = LoadedModules.end();
- LM != LMEnd; ++LM) {
- if (!LM->second.File)
- continue;
-
- Modules[LM->first].File = LM->second.File;
-
- // Resolve dependencies. Drop any we can't resolve due to out-of-date
- // module files.
- for (unsigned I = 0, N = LM->second.Dependencies.size(); I != N; ++I) {
- unsigned DepID = LM->second.Dependencies[I];
- LoadedModulesMap::iterator Known = LoadedModules.find(DepID);
- if (Known == LoadedModules.end() || !Known->second.File)
- continue;
-
- Modules[LM->first].Dependencies.push_back(Known->second.File);
+ // Compute imported-by relation.
+ for (unsigned ID = 0, IDEnd = Modules.size(); ID != IDEnd; ++ID) {
+ for (unsigned D = 0, DEnd = Modules[ID].Dependencies.size();
+ D != DEnd; ++D) {
+ Modules[Modules[ID].Dependencies[D]].ImportedBy.push_back(ID);
}
}
}
@@ -310,15 +228,14 @@ GlobalModuleIndex::GlobalModuleIndex(FileManager &FileMgr,
GlobalModuleIndex::~GlobalModuleIndex() { }
std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode>
-GlobalModuleIndex::readIndex(FileManager &FileMgr, StringRef Path) {
+GlobalModuleIndex::readIndex(StringRef Path) {
// Load the index file, if it's there.
llvm::SmallString<128> IndexPath;
IndexPath += Path;
llvm::sys::path::append(IndexPath, IndexFileName);
- llvm::OwningPtr<llvm::MemoryBuffer> Buffer(
- FileMgr.getBufferForFile(IndexPath));
- if (!Buffer)
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ if (llvm::MemoryBuffer::getFile(IndexPath, Buffer) != llvm::errc::success)
return std::make_pair((GlobalModuleIndex *)0, EC_NotFound);
/// \brief The bitstream reader from which we'll read the AST file.
@@ -336,38 +253,41 @@ GlobalModuleIndex::readIndex(FileManager &FileMgr, StringRef Path) {
return std::make_pair((GlobalModuleIndex *)0, EC_IOError);
}
- return std::make_pair(new GlobalModuleIndex(FileMgr, Buffer.take(), Cursor),
- EC_None);
+ return std::make_pair(new GlobalModuleIndex(Buffer.take(), Cursor), EC_None);
}
-void GlobalModuleIndex::getKnownModules(
- SmallVectorImpl<const FileEntry *> &ModuleFiles) {
+void
+GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) {
ModuleFiles.clear();
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
- if (Modules[I].File)
- ModuleFiles.push_back(Modules[I].File);
+ if (ModuleFile *File = resolveModuleFile(I))
+ ModuleFiles.push_back(File);
}
}
void GlobalModuleIndex::getModuleDependencies(
- const clang::FileEntry *ModuleFile,
- SmallVectorImpl<const clang::FileEntry *> &Dependencies) {
+ ModuleFile *File,
+ SmallVectorImpl<ModuleFile *> &Dependencies) {
// If the file -> index mapping is empty, populate it now.
if (ModulesByFile.empty()) {
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
- if (Modules[I].File)
- ModulesByFile[Modules[I].File] = I;
+ resolveModuleFile(I);
}
}
// Look for information about this module file.
- llvm::DenseMap<const FileEntry *, unsigned>::iterator Known
- = ModulesByFile.find(ModuleFile);
+ llvm::DenseMap<ModuleFile *, unsigned>::iterator Known
+ = ModulesByFile.find(File);
if (Known == ModulesByFile.end())
return;
// Record dependencies.
- Dependencies = Modules[Known->second].Dependencies;
+ Dependencies.clear();
+ ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies;
+ for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) {
+ if (ModuleFile *MF = resolveModuleFile(I))
+ Dependencies.push_back(MF);
+ }
}
bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) {
@@ -388,17 +308,62 @@ bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) {
SmallVector<unsigned, 2> ModuleIDs = *Known;
for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) {
- unsigned ID = ModuleIDs[I];
- if (ID >= Modules.size() || !Modules[ID].File)
- continue;
-
- Hits.insert(Modules[ID].File);
+ if (ModuleFile *File = resolveModuleFile(ModuleIDs[I]))
+ Hits.insert(File);
}
++NumIdentifierLookupHits;
return true;
}
+ModuleFile *GlobalModuleIndex::resolveModuleFile(unsigned ID) {
+ assert(ID < Modules.size() && "Out-of-bounds module index");
+
+ // If we already have a module file, return it.
+ if (Modules[ID].File)
+ return Modules[ID].File;
+
+ // If we don't have a file name, or if there is no resolver, we can't
+ // resolve this.
+ if (Modules[ID].FileName.empty() || !Resolver)
+ return 0;
+
+ // Try to resolve this module file.
+ ModuleFile *File;
+ if (Resolver->resolveModuleFileName(Modules[ID].FileName, Modules[ID].Size,
+ Modules[ID].ModTime, File)) {
+ // Clear out the module files for anything that depends on this module.
+ llvm::SmallVector<unsigned, 8> Stack;
+
+ Stack.push_back(ID);
+ while (!Stack.empty()) {
+ unsigned Victim = Stack.back();
+ Stack.pop_back();
+
+ // Mark this file as ignored.
+ Modules[Victim].File = 0;
+ Modules[Victim].FileName.clear();
+
+ // Push any not-yet-ignored imported modules onto the stack.
+ for (unsigned I = 0, N = Modules[Victim].ImportedBy.size(); I != N; ++I) {
+ unsigned NextVictim = Modules[Victim].ImportedBy[I];
+ if (!Modules[NextVictim].FileName.empty())
+ Stack.push_back(NextVictim);
+ }
+ }
+
+ return 0;
+ }
+
+ // If we have a module file, record it.
+ if (File) {
+ Modules[ID].File = File;
+ ModulesByFile[File] = ID;
+ }
+
+ return File;
+}
+
void GlobalModuleIndex::printStats() {
std::fprintf(stderr, "*** Global Module Index Statistics:\n");
if (NumIdentifierLookups) {
@@ -629,6 +594,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Skip the import location
++Idx;
+ // Load stored size/modification time.
+ off_t StoredSize = (off_t)Record[Idx++];
+ time_t StoredModTime = (time_t)Record[Idx++];
+
// Retrieve the imported file name.
unsigned Length = Record[Idx++];
SmallString<128> ImportedFile(Record.begin() + Idx,
@@ -639,7 +608,9 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
const FileEntry *DependsOnFile
= FileMgr.getFile(ImportedFile, /*openFile=*/false,
/*cacheFailure=*/false);
- if (!DependsOnFile)
+ if (!DependsOnFile ||
+ (StoredSize != DependsOnFile->getSize()) ||
+ (StoredModTime != DependsOnFile->getModificationTime()))
return true;
// Record the dependency.
diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp
index b9f4d888f30..a9f4794e106 100644
--- a/clang/lib/Serialization/ModuleManager.cpp
+++ b/clang/lib/Serialization/ModuleManager.cpp
@@ -11,9 +11,11 @@
// modules for the ASTReader.
//
//===----------------------------------------------------------------------===//
+#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/ModuleManager.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PathV2.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
@@ -36,18 +38,28 @@ llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
return InMemoryBuffers[Entry];
}
-std::pair<ModuleFile *, bool>
+ModuleManager::AddModuleResult
ModuleManager::addModule(StringRef FileName, ModuleKind Type,
SourceLocation ImportLoc, ModuleFile *ImportedBy,
- unsigned Generation, std::string &ErrorStr) {
- const FileEntry *Entry = FileMgr.getFile(FileName, /*openFile=*/false,
- /*cacheFailure=*/false);
+ unsigned Generation,
+ off_t ExpectedSize, time_t ExpectedModTime,
+ ModuleFile *&Module,
+ std::string &ErrorStr) {
+ Module = 0;
+
+ // Look for the file entry. This only fails if the expected size or
+ // modification time differ.
+ const FileEntry *Entry;
+ if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry))
+ return OutOfDate;
+
if (!Entry && FileName != "-") {
ErrorStr = "file not found";
- return std::make_pair(static_cast<ModuleFile*>(0), false);
+ return Missing;
}
-
- // Check whether we already loaded this module, before
+
+ // Check whether we already loaded this module, before
+ AddModuleResult Result = AlreadyLoaded;
ModuleFile *&ModuleEntry = Modules[Entry];
bool NewModule = false;
if (!ModuleEntry) {
@@ -77,12 +89,15 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr));
if (!New->Buffer)
- return std::make_pair(static_cast<ModuleFile*>(0), false);
+ return Missing;
}
// Initialize the stream
New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
- (const unsigned char *)New->Buffer->getBufferEnd()); }
+ (const unsigned char *)New->Buffer->getBufferEnd());
+
+ Result = NewlyLoaded;
+ }
if (ImportedBy) {
ModuleEntry->ImportedBy.insert(ImportedBy);
@@ -93,8 +108,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
ModuleEntry->DirectlyImported = true;
}
-
- return std::make_pair(ModuleEntry, NewModule);
+
+ Module = ModuleEntry;
+ return NewModule? NewlyLoaded : AlreadyLoaded;
}
namespace {
@@ -113,7 +129,8 @@ namespace {
};
}
-void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last) {
+void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last,
+ ModuleMap *modMap) {
if (first == last)
return;
@@ -129,6 +146,14 @@ void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last) {
// Delete the modules and erase them from the various structures.
for (ModuleIterator victim = first; victim != last; ++victim) {
Modules.erase((*victim)->File);
+
+ FileMgr.invalidateCache((*victim)->File);
+ if (modMap) {
+ StringRef ModuleName = llvm::sys::path::stem((*victim)->FileName);
+ if (Module *mod = modMap->findModule(ModuleName)) {
+ mod->setASTFile(0);
+ }
+ }
delete *victim;
}
@@ -151,18 +176,8 @@ void ModuleManager::updateModulesInCommonWithGlobalIndex() {
return;
// Collect the set of modules known to the global index.
- SmallVector<const FileEntry *, 16> KnownModules;
- GlobalIndex->getKnownModules(KnownModules);
-
- // Map those modules to AST files known to the module manager.
- for (unsigned I = 0, N = KnownModules.size(); I != N; ++I) {
- llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
- = Modules.find(KnownModules[I]);
- if (Known == Modules.end())
- continue;
-
- ModulesInCommonWithGlobalIndex.push_back(Known->second);
- }
+ GlobalIndex->noteAdditionalModulesLoaded();
+ GlobalIndex->getKnownModules(ModulesInCommonWithGlobalIndex);
}
ModuleManager::VisitState *ModuleManager::allocateVisitState() {
@@ -186,6 +201,9 @@ void ModuleManager::returnVisitState(VisitState *State) {
void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
GlobalIndex = Index;
+ if (GlobalIndex) {
+ GlobalIndex->setResolver(this);
+ }
updateModulesInCommonWithGlobalIndex();
}
@@ -201,7 +219,7 @@ ModuleManager::~ModuleManager() {
void
ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
void *UserData,
- llvm::SmallPtrSet<const FileEntry *, 4> *ModuleFilesHit) {
+ llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit) {
// If the visitation order vector is the wrong size, recompute the order.
if (VisitOrder.size() != Chain.size()) {
unsigned N = size();
@@ -268,7 +286,7 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
{
ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
- if (!ModuleFilesHit->count(M->File))
+ if (!ModuleFilesHit->count(M))
State->VisitNumber[M->Index] = VisitNumber;
}
}
@@ -354,6 +372,52 @@ void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder
}
}
+bool ModuleManager::lookupModuleFile(StringRef FileName,
+ off_t ExpectedSize,
+ time_t ExpectedModTime,
+ const FileEntry *&File) {
+ File = FileMgr.getFile(FileName, /*openFile=*/false, /*cacheFailure=*/false);
+
+ if (!File && FileName != "-") {
+ return false;
+ }
+
+ if ((ExpectedSize && ExpectedSize != File->getSize()) ||
+ (ExpectedModTime && ExpectedModTime != File->getModificationTime())) {
+ return true;
+ }
+
+ return false;
+}
+
+bool ModuleManager::resolveModuleFileName(StringRef FileName,
+ off_t ExpectedSize,
+ time_t ExpectedModTime,
+ ModuleFile *&File) {
+ File = 0;
+
+ // Look for the file entry corresponding to this name.
+ const FileEntry *F;
+ if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, F))
+ return true;
+
+ // If there is no file, we've succeeded (trivially).
+ if (!F)
+ return false;
+
+ // Determine whether we have a module file associated with this file entry.
+ llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
+ = Modules.find(F);
+ if (Known == Modules.end()) {
+ // We don't know about this module file; invalidate the cache.
+ FileMgr.invalidateCache(F);
+ return false;
+ }
+
+ File = Known->second;
+ return false;
+}
+
#ifndef NDEBUG
namespace llvm {
template<>
OpenPOWER on IntegriCloud