diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-11-16 17:04:00 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-11-16 17:04:00 +0000 |
commit | 4332b32c5ea9a6c404c20a3d911acfda6e1c8aaa (patch) | |
tree | 2190c354637e64197a4ccd98efdb9e251625fb4c /clang/lib/Frontend/FrontendActions.cpp | |
parent | d4756b9eceba71e8c61ecf85e9f536e350b36658 (diff) | |
download | bcm5719-llvm-4332b32c5ea9a6c404c20a3d911acfda6e1c8aaa.tar.gz bcm5719-llvm-4332b32c5ea9a6c404c20a3d911acfda6e1c8aaa.zip |
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.
llvm-svn: 144797
Diffstat (limited to 'clang/lib/Frontend/FrontendActions.cpp')
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 104 |
1 files changed, 95 insertions, 9 deletions
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 243f5277ab1..8e2e21564ff 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -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; } |