зеркало из https://github.com/microsoft/clang-1.git
When building a module from a module map that isn't simply an umbrella
header, create our own in-memory buffer to parse all of the appropriate headers, and use that to build the module. This isn't end-to-end testable yet; that's coming next. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144797 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
30bb420cfe
Коммит
261e75bd10
|
@ -178,4 +178,6 @@ def err_missing_module_name : Error<
|
|||
DefaultFatal;
|
||||
def err_missing_module : Error<
|
||||
"no module named '%0' declared in module map file '%1'">, DefaultFatal;
|
||||
def err_missing_umbrella_header : Error<
|
||||
"cannot open umbrella header '%0': %1">, DefaultFatal;
|
||||
}
|
||||
|
|
|
@ -126,6 +126,38 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
|
|||
Sysroot, OS);
|
||||
}
|
||||
|
||||
/// \brief Collect the set of header includes needed to construct the given
|
||||
/// module.
|
||||
///
|
||||
/// \param Module The module we're collecting includes from.
|
||||
/// \param ExplicitOnly Whether we should only add headers from explicit
|
||||
static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
|
||||
ModuleMap::Module *Module,
|
||||
bool ExplicitOnly,
|
||||
llvm::SmallString<256> &Includes) {
|
||||
if (!ExplicitOnly || Module->IsExplicit) {
|
||||
// Add includes for each of these headers.
|
||||
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
|
||||
if (LangOpts.ObjC1)
|
||||
Includes += "#import \"";
|
||||
else
|
||||
Includes += "#include \"";
|
||||
Includes += Module->Headers[I]->getName();
|
||||
Includes += "\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse into submodules.
|
||||
for (llvm::StringMap<ModuleMap::Module *>::iterator
|
||||
Sub = Module->SubModules.begin(),
|
||||
SubEnd = Module->SubModules.end();
|
||||
Sub != SubEnd; ++Sub) {
|
||||
collectModuleHeaderIncludes(LangOpts, Sub->getValue(),
|
||||
ExplicitOnly && !Module->IsExplicit,
|
||||
Includes);
|
||||
}
|
||||
}
|
||||
|
||||
bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
|
||||
StringRef Filename) {
|
||||
// Find the module map file.
|
||||
|
@ -161,18 +193,72 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
|
|||
return false;
|
||||
}
|
||||
|
||||
// If there is an umbrella header, use it as our actual input file.
|
||||
if (Module->UmbrellaHeader) {
|
||||
// FIXME: Deal with explicit submodule headers, which won't be contained
|
||||
// within the umbrella header.
|
||||
// Collect the set of #includes we need to build the module.
|
||||
llvm::SmallString<256> HeaderContents;
|
||||
collectModuleHeaderIncludes(CI.getLangOpts(), Module,
|
||||
Module->UmbrellaHeader != 0, HeaderContents);
|
||||
if (Module->UmbrellaHeader && HeaderContents.empty()) {
|
||||
// Simple case: we have an umbrella header and there are no additional
|
||||
// includes, we can just parse the umbrella header directly.
|
||||
setCurrentFile(Module->UmbrellaHeader->getName(), getCurrentFileKind());
|
||||
} else {
|
||||
// FIXME: Deal with the non-umbrella case, where we have to synthesize
|
||||
// a header to parse.
|
||||
// FIXME: Diagnose, at least for now.
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
FileManager &FileMgr = CI.getFileManager();
|
||||
llvm::SmallString<128> HeaderName;
|
||||
time_t ModTime;
|
||||
if (Module->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(Module->UmbrellaHeader, &ErrorStr);
|
||||
if (!UmbrellaContents) {
|
||||
CI.getDiagnostics().Report(diag::err_missing_umbrella_header)
|
||||
<< Module->UmbrellaHeader->getName() << ErrorStr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Combine the contents of the umbrella header with the automatically-
|
||||
// generated includes.
|
||||
llvm::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 = Module->UmbrellaHeader->getName();
|
||||
ModTime = Module->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(),
|
||||
ModTime);
|
||||
llvm::MemoryBuffer *HeaderContentsBuf
|
||||
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
|
||||
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
|
||||
|
||||
setCurrentFile(HeaderName, getCurrentFileKind());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify
|
||||
|
||||
#include "Umbrella/Umbrella.h"
|
||||
|
||||
int getUmbrella() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче