summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Lex/ModuleMap.h11
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp72
-rw-r--r--clang/lib/Lex/ModuleMap.cpp9
-rw-r--r--clang/test/Modules/normal-module-map.cpp4
4 files changed, 83 insertions, 13 deletions
diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index d38bbe672bd..4f89f1e7288 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -166,7 +166,16 @@ public:
/// framework directory.
Module *inferFrameworkModule(StringRef ModuleName,
const DirectoryEntry *FrameworkDir);
-
+
+ /// \brief Retrieve the module map file containing the definition of the given
+ /// module.
+ ///
+ /// \param Module The module whose module map file will be returned, if known.
+ ///
+ /// \returns The file entry for the module map file containing the given
+ /// module, or NULL if the module definition was inferred.
+ const FileEntry *getContainingModuleMapFile(ModuleMap::Module *Module);
+
/// \brief Parse the given module map file, and record any modules we
/// encounter.
///
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index c6a55839848..433b2cceb7d 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -710,6 +710,21 @@ static void doCompileModule(void *UserData) {
}
namespace {
+ struct CompileModuleMapData {
+ CompilerInstance &Instance;
+ GenerateModuleAction &CreateModuleAction;
+ };
+}
+
+/// \brief Helper function that executes the module-generating action under
+/// a crash recovery context.
+static void doCompileMapModule(void *UserData) {
+ CompileModuleMapData &Data
+ = *reinterpret_cast<CompileModuleMapData *>(UserData);
+ Data.Instance.ExecuteAction(Data.CreateModuleAction);
+}
+
+namespace {
/// \brief Class that manages the creation of a lock file to aid
/// implicit coordination between different processes.
///
@@ -958,17 +973,11 @@ void LockFileManager::waitForUnlock() {
// Give up.
}
-/// \brief Compile a module file for the given module name with the given
-/// umbrella header, using the options provided by the importing compiler
-/// instance.
+/// \brief Compile a module file for the given module, using the options
+/// provided by the importing compiler instance.
static void compileModule(CompilerInstance &ImportingInstance,
ModuleMap::Module *Module,
StringRef ModuleFileName) {
- // FIXME: Currently, we can only handle modules that have an umbrella
- // header. That's lame.
- if (!Module->UmbrellaHeader)
- return;
-
LockFileManager Locked(ModuleFileName);
switch (Locked) {
case LockFileManager::LFS_Error:
@@ -985,6 +994,9 @@ static void compileModule(CompilerInstance &ImportingInstance,
break;
}
+ ModuleMap &ModMap
+ = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
+
// Construct a compiler invocation for creating this module.
llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation
(new CompilerInvocation(ImportingInstance.getInvocation()));
@@ -1002,6 +1014,50 @@ static void compileModule(CompilerInstance &ImportingInstance,
Invocation->getPreprocessorOpts().ModuleBuildPath
.push_back(Module->getTopLevelModuleName());
+ if (const FileEntry *ModuleMapFile
+ = ModMap.getContainingModuleMapFile(Module)) {
+ // If there is a module map file, build the module using the module map.
+ // Set up the inputs/outputs so that we build the module from its umbrella
+ // header.
+ FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
+ FrontendOpts.OutputFile = ModuleFileName.str();
+ FrontendOpts.DisableFree = false;
+ FrontendOpts.Inputs.clear();
+ FrontendOpts.Inputs.push_back(
+ std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()),
+ ModuleMapFile->getName()));
+
+ Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
+
+
+ assert(ImportingInstance.getInvocation().getModuleHash() ==
+ Invocation->getModuleHash() && "Module hash mismatch!");
+
+ // Construct a compiler instance that will be used to actually create the
+ // module.
+ CompilerInstance Instance;
+ Instance.setInvocation(&*Invocation);
+ Instance.createDiagnostics(/*argc=*/0, /*argv=*/0,
+ &ImportingInstance.getDiagnosticClient(),
+ /*ShouldOwnClient=*/true,
+ /*ShouldCloneClient=*/true);
+
+ // Construct a module-generating action.
+ GenerateModuleAction CreateModuleAction;
+
+ // Execute the action to actually build the module in-place. Use a separate
+ // thread so that we get a stack large enough.
+ const unsigned ThreadStackSize = 8 << 20;
+ llvm::CrashRecoveryContext CRC;
+ CompileModuleMapData Data = { Instance, CreateModuleAction };
+ CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
+ return;
+ }
+
+ // FIXME: Temporary fallback: generate the module from the umbrella header.
+ // This is currently used when we infer a module map from a framework.
+ assert(Module->UmbrellaHeader && "Inferred module map needs umbrella header");
+
// Set up the inputs/outputs so that we build the module from its umbrella
// header.
FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index a25c93bfca4..3cc6478acf6 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -206,6 +206,15 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
return Result;
}
+const FileEntry *
+ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
+ if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
+ return 0;
+
+ return SourceMgr->getFileEntryForID(
+ SourceMgr->getFileID(Module->DefinitionLoc));
+}
+
void ModuleMap::dump() {
llvm::errs() << "Modules:";
for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
diff --git a/clang/test/Modules/normal-module-map.cpp b/clang/test/Modules/normal-module-map.cpp
index c87657f5a9b..19294950d49 100644
--- a/clang/test/Modules/normal-module-map.cpp
+++ b/clang/test/Modules/normal-module-map.cpp
@@ -1,8 +1,4 @@
// RUN: rm -rf %t
-// FIXME: Eventually, we should be able to remove these explicit module creation lines
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libA -emit-module-from-map %S/Inputs/normal-module-map/module.map
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libB -emit-module-from-map %S/Inputs/normal-module-map/module.map
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libNested -emit-module-from-map %S/Inputs/normal-module-map/nested/module.map
// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify
#include "Umbrella/umbrella_sub.h"
OpenPOWER on IntegriCloud