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_iterator submodule_end() { return SubModules.end(); }
|
||||||
submodule_const_iterator submodule_end() const { 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.
|
/// \brief Print the module map for this module to the given stream.
|
||||||
///
|
///
|
||||||
void print(llvm::raw_ostream &OS, unsigned Indent = 0) const;
|
void print(llvm::raw_ostream &OS, unsigned Indent = 0) const;
|
||||||
|
|
|
@ -131,6 +131,29 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
|
||||||
Sysroot, OS);
|
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
|
/// \brief Collect the set of header includes needed to construct the given
|
||||||
/// module and update the TopHeaders file set of the module.
|
/// module and update the TopHeaders file set of the module.
|
||||||
///
|
///
|
||||||
|
@ -142,7 +165,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
|
||||||
FileManager &FileMgr,
|
FileManager &FileMgr,
|
||||||
ModuleMap &ModMap,
|
ModuleMap &ModMap,
|
||||||
clang::Module *Module,
|
clang::Module *Module,
|
||||||
SmallString<256> &Includes) {
|
SmallVectorImpl<char> &Includes) {
|
||||||
// Don't collect any headers for unavailable modules.
|
// Don't collect any headers for unavailable modules.
|
||||||
if (!Module->isAvailable())
|
if (!Module->isAvailable())
|
||||||
return;
|
return;
|
||||||
|
@ -151,24 +174,14 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
|
||||||
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
|
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
|
||||||
const FileEntry *Header = Module->Headers[I];
|
const FileEntry *Header = Module->Headers[I];
|
||||||
Module->TopHeaders.insert(Header);
|
Module->TopHeaders.insert(Header);
|
||||||
if (LangOpts.ObjC1)
|
addHeaderInclude(Header, Includes, LangOpts);
|
||||||
Includes += "#import \"";
|
|
||||||
else
|
|
||||||
Includes += "#include \"";
|
|
||||||
Includes += Header->getName();
|
|
||||||
Includes += "\"\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
|
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
|
||||||
Module->TopHeaders.insert(UmbrellaHeader);
|
Module->TopHeaders.insert(UmbrellaHeader);
|
||||||
if (Module->Parent) {
|
if (Module->Parent) {
|
||||||
// Include the umbrella header for submodules.
|
// Include the umbrella header for submodules.
|
||||||
if (LangOpts.ObjC1)
|
addHeaderInclude(UmbrellaHeader, Includes, LangOpts);
|
||||||
Includes += "#import \"";
|
|
||||||
else
|
|
||||||
Includes += "#include \"";
|
|
||||||
Includes += UmbrellaHeader->getName();
|
|
||||||
Includes += "\"\n";
|
|
||||||
}
|
}
|
||||||
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
|
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
|
||||||
// Add all of the headers we find in this subdirectory.
|
// 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.
|
// Include this header umbrella header for submodules.
|
||||||
if (LangOpts.ObjC1)
|
addHeaderInclude(Dir->path(), Includes, LangOpts);
|
||||||
Includes += "#import \"";
|
|
||||||
else
|
|
||||||
Includes += "#include \"";
|
|
||||||
Includes += Dir->path();
|
|
||||||
Includes += "\"\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,77 +263,29 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we have an umbrella header for this module?
|
FileManager &FileMgr = CI.getFileManager();
|
||||||
const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader();
|
|
||||||
|
|
||||||
// Collect the set of #includes we need to build the module.
|
// Collect the set of #includes we need to build the module.
|
||||||
SmallString<256> HeaderContents;
|
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(),
|
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
|
||||||
Module, HeaderContents);
|
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();
|
StringRef InputName = Module::getModuleInputBufferName();
|
||||||
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-
|
// We consistently construct a buffer as input to build the module.
|
||||||
// generated includes.
|
// This means the main file for modules will always be a virtual one.
|
||||||
SmallString<256> OldContents = HeaderContents;
|
// FIXME: Maybe allow using a memory buffer as input directly instead of
|
||||||
HeaderContents = UmbrellaContents->getBuffer();
|
// messing with virtual files.
|
||||||
HeaderContents += "\n\n";
|
const FileEntry *HeaderFile = FileMgr.getVirtualFile(InputName,
|
||||||
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,
|
|
||||||
HeaderContents.size(),
|
HeaderContents.size(),
|
||||||
ModTime);
|
time(0));
|
||||||
llvm::MemoryBuffer *HeaderContentsBuf
|
llvm::MemoryBuffer *HeaderContentsBuf
|
||||||
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
|
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
|
||||||
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
|
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
|
||||||
setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind(),
|
setCurrentInput(FrontendInputFile(InputName, getCurrentFileKind(),
|
||||||
Module->IsSystem));
|
Module->IsSystem));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1111,7 +1111,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
|
||||||
return Failure;
|
return Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DisableValidation &&
|
if (!DisableValidation && !OverriddenBuffer &&
|
||||||
((off_t)Record[4] != File->getSize()
|
((off_t)Record[4] != File->getSize()
|
||||||
#if !defined(LLVM_ON_WIN32)
|
#if !defined(LLVM_ON_WIN32)
|
||||||
// In our regression testing, the Windows file system seems to
|
// In our regression testing, the Windows file system seems to
|
||||||
|
|
Loading…
Reference in New Issue