forked from OSchip/llvm-project
When loading a module fails because it is out of date, rebuild that
module in place. <rdar://problem/10138913> llvm-svn: 167539
This commit is contained in:
parent
b9db60fbce
commit
188dbef26d
|
@ -105,7 +105,10 @@ public:
|
|||
std::pair<ModuleFile *, bool>
|
||||
addModule(StringRef FileName, ModuleKind Type, ModuleFile *ImportedBy,
|
||||
unsigned Generation, std::string &ErrorStr);
|
||||
|
||||
|
||||
/// \brief Remove the given set of modules.
|
||||
void removeModules(ModuleIterator first, ModuleIterator last);
|
||||
|
||||
/// \brief Add an in-memory buffer the list of known buffers
|
||||
void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer);
|
||||
|
||||
|
|
|
@ -762,7 +762,7 @@ static void compileModule(CompilerInstance &ImportingInstance,
|
|||
// Someone else is responsible for building the module. Wait for them to
|
||||
// finish.
|
||||
Locked.waitForUnlock();
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
ModuleMap &ModMap
|
||||
|
@ -975,13 +975,36 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
}
|
||||
|
||||
// Try to load the module we found.
|
||||
unsigned ARRFlags = ASTReader::ARR_None;
|
||||
if (Module)
|
||||
ARRFlags |= ASTReader::ARR_OutOfDate;
|
||||
switch (ModuleManager->ReadAST(ModuleFile->getName(),
|
||||
serialization::MK_Module,
|
||||
ASTReader::ARR_None)) {
|
||||
ARRFlags)) {
|
||||
case ASTReader::Success:
|
||||
break;
|
||||
|
||||
case ASTReader::OutOfDate:
|
||||
case ASTReader::OutOfDate: {
|
||||
// The module file is out-of-date. Rebuild it.
|
||||
getFileManager().invalidateCache(ModuleFile);
|
||||
bool Existed;
|
||||
llvm::sys::fs::remove(ModuleFileName, Existed);
|
||||
compileModule(*this, Module, ModuleFileName);
|
||||
|
||||
// Try loading the module again.
|
||||
ModuleFile = FileMgr->getFile(ModuleFileName);
|
||||
if (!ModuleFile ||
|
||||
ModuleManager->ReadAST(ModuleFileName,
|
||||
serialization::MK_Module,
|
||||
ASTReader::ARR_None) != ASTReader::Success) {
|
||||
KnownModules[Path[0].first] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Okay, we've rebuilt and now loaded the module.
|
||||
break;
|
||||
}
|
||||
|
||||
case ASTReader::VersionMismatch:
|
||||
case ASTReader::ConfigurationMismatch:
|
||||
case ASTReader::HadErrors:
|
||||
|
|
|
@ -2675,16 +2675,21 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
|||
// Bump the generation number.
|
||||
unsigned PreviousGeneration = CurrentGeneration++;
|
||||
|
||||
// Load the core of the AST files.
|
||||
unsigned NumModules = ModuleMgr.size();
|
||||
llvm::SmallVector<ModuleFile *, 4> Loaded;
|
||||
switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0, Loaded,
|
||||
ClientLoadCapabilities)) {
|
||||
case Failure: return Failure;
|
||||
case OutOfDate: return OutOfDate;
|
||||
case VersionMismatch: return VersionMismatch;
|
||||
case ConfigurationMismatch: return ConfigurationMismatch;
|
||||
case HadErrors: return HadErrors;
|
||||
case Success: break;
|
||||
switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type,
|
||||
/*ImportedBy=*/0, Loaded,
|
||||
ClientLoadCapabilities)) {
|
||||
case Failure:
|
||||
case OutOfDate:
|
||||
case VersionMismatch:
|
||||
case ConfigurationMismatch:
|
||||
case HadErrors:
|
||||
ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());
|
||||
return ReadResult;
|
||||
|
||||
case Success:
|
||||
break;
|
||||
}
|
||||
|
||||
// Here comes stuff that we only do once the entire chain is loaded.
|
||||
|
|
|
@ -88,6 +88,45 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
|
|||
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) {
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
int getA();
|
|
@ -0,0 +1,2 @@
|
|||
#include "A.h"
|
||||
int getB();
|
|
@ -0,0 +1,2 @@
|
|||
module A { header "A.h" }
|
||||
module B { header "B.h" }
|
|
@ -0,0 +1,23 @@
|
|||
// Test that if we modify one of the input files used to form a
|
||||
// header, that module and dependent modules get rebuilt.
|
||||
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir -p %t/include
|
||||
// RUN: cp %S/Inputs/Modified/A.h %t/include
|
||||
// RUN: cp %S/Inputs/Modified/B.h %t/include
|
||||
// RUN: cp %S/Inputs/Modified/module.map %t/include
|
||||
// RUN: %clang_cc1 -fmodule-cache-path %t/cache -fmodules -I %t/include %s -verify
|
||||
// expected-no-diagnostics
|
||||
// RUN: touch %t/include/B.h
|
||||
// RUN: %clang_cc1 -fmodule-cache-path %t/cache -fmodules -I %t/include %s -verify
|
||||
// RUN: echo 'int getA(); int getA2();' > %t/include/A.h
|
||||
// RUN: %clang_cc1 -fmodule-cache-path %t/cache -fmodules -I %t/include %s -verify
|
||||
|
||||
@__experimental_modules_import B;
|
||||
|
||||
int getValue() { return getA() + getB(); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue