[cfe-commits] r144797 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td lib/Frontend/FrontendActions.cpp test/Modules/normal-module-map.cpp
Douglas Gregor
dgregor at apple.com
Wed Nov 16 09:04:00 PST 2011
Author: dgregor
Date: Wed Nov 16 11:04:00 2011
New Revision: 144797
URL: http://llvm.org/viewvc/llvm-project?rev=144797&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
cfe/trunk/lib/Frontend/FrontendActions.cpp
cfe/trunk/test/Modules/normal-module-map.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=144797&r1=144796&r2=144797&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Wed Nov 16 11:04:00 2011
@@ -178,4 +178,6 @@
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;
}
Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=144797&r1=144796&r2=144797&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Wed Nov 16 11:04:00 2011
@@ -126,6 +126,38 @@
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 @@
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;
}
Modified: cfe/trunk/test/Modules/normal-module-map.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/normal-module-map.cpp?rev=144797&r1=144796&r2=144797&view=diff
==============================================================================
--- cfe/trunk/test/Modules/normal-module-map.cpp (original)
+++ cfe/trunk/test/Modules/normal-module-map.cpp Wed Nov 16 11:04:00 2011
@@ -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() {
More information about the cfe-commits
mailing list