Add -fmodule-map-file option.

With this option, arbitrarily named module map files can be specified
to be loaded as required for headers in the respective (sub)directories.

This, together with the extern module declaration allows for specifying
module maps in a modular fashion without the need for files called
"module.map".

Among other things, this allows a directory to contain two modules that
are completely independent of one another.

Review: http://llvm-reviews.chandlerc.com/D1697.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191284 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index c8c6768..afba109 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -896,6 +896,9 @@
     StringRef MacroDef = (*it)->getValue();
     Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first);
   }
+  std::vector<std::string> ModuleMapFiles =
+      Args.getAllArgValues(OPT_fmodule_map_file);
+  Opts.ModuleMapFiles.insert(ModuleMapFiles.begin(), ModuleMapFiles.end());
 
   // Add -I..., -F..., and -index-header-map options in order.
   bool IsIndexHeaderMap = false;
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index ec84bb1..5bcc4ea 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -941,28 +941,50 @@
     DirName = llvm::sys::path::parent_path(DirName);
     if (DirName.empty())
       return false;
-    
+
     // Determine whether this directory exists.
     const DirectoryEntry *Dir = FileMgr.getDirectory(DirName);
     if (!Dir)
       return false;
     
-    // Try to load the module map file in this directory.
+    // Load user-specified module map files in 'Dir'.
+    bool ModuleMapFound = false;
+    for (llvm::SetVector<std::string>::iterator
+             I = HSOpts->ModuleMapFiles.begin(),
+             E = HSOpts->ModuleMapFiles.end();
+         I != E; ++I) {
+      StringRef ModuleMapFileDir = llvm::sys::path::parent_path(*I);
+      if (!llvm::sys::fs::equivalent(ModuleMapFileDir, DirName))
+        continue;
+
+      const FileEntry *File = FileMgr.getFile(*I);
+      if (!File)
+        continue;
+
+      loadModuleMapFile(File, /*IsSystem=*/false);
+      ModuleMapFound = true;
+    }
+
+    // Try to load the "module.map" file in this directory.
     switch (loadModuleMapFile(Dir, IsSystem)) {
     case LMM_NewlyLoaded:
     case LMM_AlreadyLoaded:
-      // Success. All of the directories we stepped through inherit this module
-      // map file.
-      for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
-        DirectoryHasModuleMap[FixUpDirectories[I]] = true;
-      
-      return true;
+      ModuleMapFound = true;
+      break;
 
     case LMM_NoDirectory:
     case LMM_InvalidModuleMap:
       break;
     }
 
+    if (ModuleMapFound) {
+      // Success. All of the directories we stepped through inherit this module
+      // map file.
+      for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
+        DirectoryHasModuleMap[FixUpDirectories[I]] = true;
+      return true;
+    }
+
     // If we hit the top of our search, we're done.
     if (Dir == Root)
       return false;