[modules] Consistently construct a buffer as input to build the module.

This means the main file for modules will always be a virtual one.

llvm-svn: 165591
This commit is contained in:
Argyrios Kyrtzidis 2012-10-10 02:12:39 +00:00
parent 0f2e44a1cb
commit 130190ffff
3 changed files with 46 additions and 82 deletions

View File

@ -290,6 +290,10 @@ public:
submodule_iterator submodule_end() { return SubModules.end(); }
submodule_const_iterator submodule_end() const { return SubModules.end(); }
static StringRef getModuleInputBufferName() {
return "<module-includes>";
}
/// \brief Print the module map for this module to the given stream.
///
void print(llvm::raw_ostream &OS, unsigned Indent = 0) const;

View File

@ -131,6 +131,29 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
Sysroot, OS);
}
static SmallVectorImpl<char> &
operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
Includes.append(RHS.begin(), RHS.end());
return Includes;
}
static void addHeaderInclude(StringRef HeaderName,
SmallVectorImpl<char> &Includes,
const LangOptions &LangOpts) {
if (LangOpts.ObjC1)
Includes += "#import \"";
else
Includes += "#include \"";
Includes += HeaderName;
Includes += "\"\n";
}
static void addHeaderInclude(const FileEntry *Header,
SmallVectorImpl<char> &Includes,
const LangOptions &LangOpts) {
addHeaderInclude(Header->getName(), Includes, LangOpts);
}
/// \brief Collect the set of header includes needed to construct the given
/// module and update the TopHeaders file set of the module.
///
@ -142,7 +165,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
FileManager &FileMgr,
ModuleMap &ModMap,
clang::Module *Module,
SmallString<256> &Includes) {
SmallVectorImpl<char> &Includes) {
// Don't collect any headers for unavailable modules.
if (!Module->isAvailable())
return;
@ -151,24 +174,14 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
const FileEntry *Header = Module->Headers[I];
Module->TopHeaders.insert(Header);
if (LangOpts.ObjC1)
Includes += "#import \"";
else
Includes += "#include \"";
Includes += Header->getName();
Includes += "\"\n";
addHeaderInclude(Header, Includes, LangOpts);
}
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
Module->TopHeaders.insert(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
if (LangOpts.ObjC1)
Includes += "#import \"";
else
Includes += "#include \"";
Includes += UmbrellaHeader->getName();
Includes += "\"\n";
addHeaderInclude(UmbrellaHeader, Includes, LangOpts);
}
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
@ -194,12 +207,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
}
// Include this header umbrella header for submodules.
if (LangOpts.ObjC1)
Includes += "#import \"";
else
Includes += "#include \"";
Includes += Dir->path();
Includes += "\"\n";
addHeaderInclude(Dir->path(), Includes, LangOpts);
}
}
@ -255,77 +263,29 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
// Do we have an umbrella header for this module?
const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader();
FileManager &FileMgr = CI.getFileManager();
// Collect the set of #includes we need to build the module.
SmallString<256> HeaderContents;
collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(),
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts());
collectModuleHeaderIncludes(CI.getLangOpts(), FileMgr,
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
Module, HeaderContents);
if (UmbrellaHeader && HeaderContents.empty()) {
// Simple case: we have an umbrella header and there are no additional
// includes, we can just parse the umbrella header directly.
setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(),
getCurrentFileKind(),
Module->IsSystem));
return true;
}
FileManager &FileMgr = CI.getFileManager();
SmallString<128> HeaderName;
time_t ModTime;
if (UmbrellaHeader) {
// Read in the umbrella header.
// FIXME: Go through the source manager; the umbrella header may have
// been overridden.
std::string ErrorStr;
llvm::MemoryBuffer *UmbrellaContents
= FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr);
if (!UmbrellaContents) {
CI.getDiagnostics().Report(diag::err_missing_umbrella_header)
<< UmbrellaHeader->getName() << ErrorStr;
return false;
}
// Combine the contents of the umbrella header with the automatically-
// generated includes.
SmallString<256> OldContents = HeaderContents;
HeaderContents = UmbrellaContents->getBuffer();
HeaderContents += "\n\n";
HeaderContents += "/* Module includes */\n";
HeaderContents += OldContents;
// Pretend that we're parsing the umbrella header.
HeaderName = UmbrellaHeader->getName();
ModTime = UmbrellaHeader->getModificationTime();
delete UmbrellaContents;
} else {
// Pick an innocuous-sounding name for the umbrella header.
HeaderName = Module->Name + ".h";
if (FileMgr.getFile(HeaderName, /*OpenFile=*/false,
/*CacheFailure=*/false)) {
// Try again!
HeaderName = Module->Name + "-module.h";
if (FileMgr.getFile(HeaderName, /*OpenFile=*/false,
/*CacheFailure=*/false)) {
// Pick something ridiculous and go with it.
HeaderName = Module->Name + "-module.hmod";
}
}
ModTime = time(0);
}
// Remap the contents of the header name we're using to our synthesized
// buffer.
const FileEntry *HeaderFile = FileMgr.getVirtualFile(HeaderName,
StringRef InputName = Module::getModuleInputBufferName();
// We consistently construct a buffer as input to build the module.
// This means the main file for modules will always be a virtual one.
// FIXME: Maybe allow using a memory buffer as input directly instead of
// messing with virtual files.
const FileEntry *HeaderFile = FileMgr.getVirtualFile(InputName,
HeaderContents.size(),
ModTime);
time(0));
llvm::MemoryBuffer *HeaderContentsBuf
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind(),
setCurrentInput(FrontendInputFile(InputName, getCurrentFileKind(),
Module->IsSystem));
return true;
}

View File

@ -1111,7 +1111,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
return Failure;
}
if (!DisableValidation &&
if (!DisableValidation && !OverriddenBuffer &&
((off_t)Record[4] != File->getSize()
#if !defined(LLVM_ON_WIN32)
// In our regression testing, the Windows file system seems to