forked from OSchip/llvm-project
[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:
parent
0f2e44a1cb
commit
130190ffff
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue