Teach the module import mechanism how to rebuild modules expressed via
module map, rather than assuming that there is an umbrella
header. This allows us to automatically build umbrella-less modules. 

llvm-svn: 145415
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index c6a5583..433b2cc 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -710,6 +710,21 @@
 }
 
 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 @@
   // 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 @@
     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 @@
   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();