Move functionality for handling module maps as inputs from the -emit-module
action to the general FrontendAction infrastructure.

This permits applying -E, -ast-dump, -fsyntax-only, and so on to a module map
compilation. (The -E form is not currently especially useful yet as there's no
good way to take the output and use it to actually build a module.)

In order to support this, -cc1 now accepts -x <lang>-module-map in all cases
where it accepts -x <lang> for a language we can parse (not ir/ast). And for
uniformity, we also accept -x <lang>-header for all such languages (we used
to reject for cuda and renderscript), and -x <lang>-cpp-output for all such
languages (we used to reject for c, cl, and renderscript).

(None of these new alternatives are accepted by the driver yet, so no
user-visible changes.)

llvm-svn: 301610
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 1fce1e5..dd7c12f 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -164,242 +164,9 @@
   return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
 }
 
-bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, 
-                                                 StringRef Filename) {
-  // Set up embedding for any specified files. Do this before we load any
-  // source files, including the primary module map for the compilation.
-  for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
-    if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true))
-      CI.getSourceManager().setFileIsTransient(FE);
-    else
-      CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
-  }
-  if (CI.getFrontendOpts().ModulesEmbedAllFiles)
-    CI.getSourceManager().setAllFilesAreTransient(true);
-
-  return true;
-}
-
-
-static SmallVectorImpl<char> &
-operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
-  Includes.append(RHS.begin(), RHS.end());
-  return Includes;
-}
-
-static void addHeaderInclude(StringRef HeaderName,
-                             SmallVectorImpl<char> &Includes,
-                             const LangOptions &LangOpts,
-                             bool IsExternC) {
-  if (IsExternC && LangOpts.CPlusPlus)
-    Includes += "extern \"C\" {\n";
-  if (LangOpts.ObjC1)
-    Includes += "#import \"";
-  else
-    Includes += "#include \"";
-
-  Includes += HeaderName;
-
-  Includes += "\"\n";
-  if (IsExternC && LangOpts.CPlusPlus)
-    Includes += "}\n";
-}
-
-/// \brief Collect the set of header includes needed to construct the given 
-/// module and update the TopHeaders file set of the module.
-///
-/// \param Module The module we're collecting includes from.
-///
-/// \param Includes Will be augmented with the set of \#includes or \#imports
-/// needed to load all of the named headers.
-static std::error_code
-collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
-                            ModuleMap &ModMap, clang::Module *Module,
-                            SmallVectorImpl<char> &Includes) {
-  // Don't collect any headers for unavailable modules.
-  if (!Module->isAvailable())
-    return std::error_code();
-
-  // Add includes for each of these headers.
-  for (auto HK : {Module::HK_Normal, Module::HK_Private}) {
-    for (Module::Header &H : Module->Headers[HK]) {
-      Module->addTopHeader(H.Entry);
-      // Use the path as specified in the module map file. We'll look for this
-      // file relative to the module build directory (the directory containing
-      // the module map file) so this will find the same file that we found
-      // while parsing the module map.
-      addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC);
-    }
-  }
-  // Note that Module->PrivateHeaders will not be a TopHeader.
-
-  if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) {
-    Module->addTopHeader(UmbrellaHeader.Entry);
-    if (Module->Parent)
-      // Include the umbrella header for submodules.
-      addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts,
-                       Module->IsExternC);
-  } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
-    // Add all of the headers we find in this subdirectory.
-    std::error_code EC;
-    SmallString<128> DirNative;
-    llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative);
-
-    vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
-    for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
-         Dir != End && !EC; Dir.increment(EC)) {
-      // Check whether this entry has an extension typically associated with 
-      // headers.
-      if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName()))
-          .Cases(".h", ".H", ".hh", ".hpp", true)
-          .Default(false))
-        continue;
-
-      const FileEntry *Header = FileMgr.getFile(Dir->getName());
-      // FIXME: This shouldn't happen unless there is a file system race. Is
-      // that worth diagnosing?
-      if (!Header)
-        continue;
-
-      // If this header is marked 'unavailable' in this module, don't include 
-      // it.
-      if (ModMap.isHeaderUnavailableInModule(Header, Module))
-        continue;
-
-      // Compute the relative path from the directory to this file.
-      SmallVector<StringRef, 16> Components;
-      auto PathIt = llvm::sys::path::rbegin(Dir->getName());
-      for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
-        Components.push_back(*PathIt);
-      SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten);
-      for (auto It = Components.rbegin(), End = Components.rend(); It != End;
-           ++It)
-        llvm::sys::path::append(RelativeHeader, *It);
-
-      // Include this header as part of the umbrella directory.
-      Module->addTopHeader(Header);
-      addHeaderInclude(RelativeHeader, Includes, LangOpts, Module->IsExternC);
-    }
-
-    if (EC)
-      return EC;
-  }
-
-  // Recurse into submodules.
-  for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
-                                      SubEnd = Module->submodule_end();
-       Sub != SubEnd; ++Sub)
-    if (std::error_code Err = collectModuleHeaderIncludes(
-            LangOpts, FileMgr, ModMap, *Sub, Includes))
-      return Err;
-
-  return std::error_code();
-}
-
 bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
     CompilerInstance &CI, StringRef Filename) {
-  CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);
-
-  if (!GenerateModuleAction::BeginSourceFileAction(CI, Filename))
-    return false;
-
-  // Find the module map file.
-  const FileEntry *ModuleMap =
-      CI.getFileManager().getFile(Filename, /*openFile*/true);
-  if (!ModuleMap)  {
-    CI.getDiagnostics().Report(diag::err_module_map_not_found)
-      << Filename;
-    return false;
-  }
-  
-  // Parse the module map file.
-  HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
-  if (HS.loadModuleMapFile(ModuleMap, IsSystem))
-    return false;
-  
-  if (CI.getLangOpts().CurrentModule.empty()) {
-    CI.getDiagnostics().Report(diag::err_missing_module_name);
-    
-    // FIXME: Eventually, we could consider asking whether there was just
-    // a single module described in the module map, and use that as a 
-    // default. Then it would be fairly trivial to just "compile" a module
-    // map with a single module (the common case).
-    return false;
-  }
-
-  // If we're being run from the command-line, the module build stack will not
-  // have been filled in yet, so complete it now in order to allow us to detect
-  // module cycles.
-  SourceManager &SourceMgr = CI.getSourceManager();
-  if (SourceMgr.getModuleBuildStack().empty())
-    SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,
-                                   FullSourceLoc(SourceLocation(), SourceMgr));
-
-  // Dig out the module definition.
-  Module = HS.lookupModule(CI.getLangOpts().CurrentModule, 
-                           /*AllowSearch=*/false);
-  if (!Module) {
-    CI.getDiagnostics().Report(diag::err_missing_module)
-      << CI.getLangOpts().CurrentModule << Filename;
-    
-    return false;
-  }
-
-  // Check whether we can build this module at all.
-  clang::Module::Requirement Requirement;
-  clang::Module::UnresolvedHeaderDirective MissingHeader;
-  if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
-                           MissingHeader)) {
-    if (MissingHeader.FileNameLoc.isValid()) {
-      CI.getDiagnostics().Report(MissingHeader.FileNameLoc,
-                                 diag::err_module_header_missing)
-        << MissingHeader.IsUmbrella << MissingHeader.FileName;
-    } else {
-      CI.getDiagnostics().Report(diag::err_module_unavailable)
-        << Module->getFullModuleName()
-        << Requirement.second << Requirement.first;
-    }
-
-    return false;
-  }
-
-  if (ModuleMapForUniquing && ModuleMapForUniquing != ModuleMap) {
-    Module->IsInferred = true;
-    HS.getModuleMap().setInferredModuleAllowedBy(Module, ModuleMapForUniquing);
-  } else {
-    ModuleMapForUniquing = ModuleMap;
-  }
-
-  FileManager &FileMgr = CI.getFileManager();
-
-  // Collect the set of #includes we need to build the module.
-  SmallString<256> HeaderContents;
-  std::error_code Err = std::error_code();
-  if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader())
-    addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents,
-                     CI.getLangOpts(), Module->IsExternC);
-  Err = collectModuleHeaderIncludes(
-        CI.getLangOpts(), FileMgr,
-        CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module,
-        HeaderContents);
-
-  if (Err) {
-    CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)
-      << Module->getFullModuleName() << Err.message();
-    return false;
-  }
-
-  // Inform the preprocessor that includes from within the input buffer should
-  // be resolved relative to the build directory of the module map file.
-  CI.getPreprocessor().setMainFileDir(Module->Directory);
-
-  std::unique_ptr<llvm::MemoryBuffer> InputBuffer =
-      llvm::MemoryBuffer::getMemBufferCopy(HeaderContents,
-                                           Module::getModuleInputBufferName());
-  // Ownership of InputBuffer will be transferred to the SourceManager.
-  setCurrentInput(FrontendInputFile(InputBuffer.release(), getCurrentFileKind(),
-                                    Module->IsSystem));
-  return true;
+  return GenerateModuleAction::BeginSourceFileAction(CI, Filename);
 }
 
 std::unique_ptr<raw_pwrite_stream>
@@ -408,10 +175,13 @@
   // If no output file was provided, figure out where this module would go
   // in the module cache.
   if (CI.getFrontendOpts().OutputFile.empty()) {
+    StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap;
+    if (ModuleMapFile.empty())
+      ModuleMapFile = InFile;
+
     HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
     CI.getFrontendOpts().OutputFile =
-        HS.getModuleFileName(CI.getLangOpts().CurrentModule,
-                             ModuleMapForUniquing->getName(),
+        HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapFile,
                              /*UsePrebuiltPath=*/false);
   }