summaryrefslogtreecommitdiffstats
path: root/clang/lib/Frontend/FrontendActions.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-11-16 17:04:00 +0000
committerDouglas Gregor <dgregor@apple.com>2011-11-16 17:04:00 +0000
commit4332b32c5ea9a6c404c20a3d911acfda6e1c8aaa (patch)
tree2190c354637e64197a4ccd98efdb9e251625fb4c /clang/lib/Frontend/FrontendActions.cpp
parentd4756b9eceba71e8c61ecf85e9f536e350b36658 (diff)
downloadbcm5719-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.cpp104
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;
}
OpenPOWER on IntegriCloud