Introduce a cc1-level option to provide the path to the module cache,
where the compiler will look for module files. Eliminates the
egregious hack where we looked into the header search paths for
modules.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139538 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index c1ceba8..e3d79ac 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -605,6 +605,10 @@
   HelpText<"Disable standard #include directories for the C++ standard library">;
 def nobuiltininc : Flag<"-nobuiltininc">,
   HelpText<"Disable builtin #include directories">;
+def fmodule_cache_path : JoinedOrSeparate<"-fmodule-cache-path">, 
+  MetaVarName<"<directory>">,
+  HelpText<"Specify the module cache path">;           
+
 def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,
   HelpText<"Add directory to framework include search path">;
 def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h
index e1b1273..a81a0cb 100644
--- a/include/clang/Frontend/HeaderSearchOptions.h
+++ b/include/clang/Frontend/HeaderSearchOptions.h
@@ -75,6 +75,9 @@
   /// etc.).
   std::string ResourceDir;
 
+  /// \brief The directory used for the module cache.
+  std::string ModuleCachePath;
+  
   /// Include the compiler builtin includes.
   unsigned UseBuiltinIncludes : 1;
 
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 676a245..f6552a4 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -129,6 +129,9 @@
   unsigned SystemDirIdx;
   bool NoCurDirSearch;
 
+  /// \brief The path to the module cache.
+  std::string ModuleCachePath;
+  
   /// FileInfo - This contains all of the preprocessor-specific data about files
   /// that are included.  The vector is indexed by the FileEntry's UID.
   ///
@@ -193,6 +196,11 @@
     //LookupFileCache.clear();
   }
 
+  /// \brief Set the path to the module cache.
+  void setModuleCachePath(StringRef Path) {
+    ModuleCachePath = Path;
+  }
+  
   /// ClearFileInfo - Forget everything we know about headers so far.
   void ClearFileInfo() {
     FileInfo.clear();
@@ -308,6 +316,13 @@
   /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
   const HeaderMap *CreateHeaderMap(const FileEntry *FE);
 
+  /// \brief Search in the module cache path for a module with the given
+  /// name.
+  ///
+  /// \returns A file describing the named module, if available, or NULL to
+  /// indicate that the module could not be found.
+  const FileEntry *lookupModule(StringRef ModuleName);
+  
   void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
 
   typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator;
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index bd019e0..1106e48 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -636,14 +636,8 @@
     CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
 
   // Search for a module with the given name.
-  std::string Filename = ModuleName.getName().str();
-  Filename += ".pcm";
-  const DirectoryLookup *CurDir = 0;  
   const FileEntry *ModuleFile
-    = PP->getHeaderSearchInfo().LookupFile(Filename, /*isAngled=*/false,
-                                           /*FromDir=*/0, CurDir, CurFile, 
-                                           /*SearchPath=*/0, 
-                                           /*RelativePath=*/0);
+    = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName());
   if (!ModuleFile) {
     getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
       << ModuleName.getName()
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 7ea3161..e7b8854 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -576,6 +576,10 @@
     Res.push_back("-resource-dir");
     Res.push_back(Opts.ResourceDir);
   }
+  if (!Opts.ModuleCachePath.empty()) {
+    Res.push_back("-fmodule-cache-path");
+    Res.push_back(Opts.ModuleCachePath);
+  }
   if (!Opts.UseStandardIncludes)
     Res.push_back("-nostdinc");
   if (!Opts.UseStandardCXXIncludes)
@@ -1378,7 +1382,8 @@
   if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
     Opts.UseLibcxx = (strcmp(A->getValue(Args), "libc++") == 0);
   Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
-
+  Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodule_cache_path);
+  
   // Add -I..., -F..., and -index-header-map options in order.
   bool IsIndexHeaderMap = false;
   for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F, 
@@ -1426,7 +1431,7 @@
                  ((*it)->getOption().matches(OPT_cxx_isystem) ?
                    frontend::CXXSystem : frontend::System),
                  true, false, !(*it)->getOption().matches(OPT_iwithsysroot));
-
+  
   // FIXME: Need options for the various environment variables!
 }
 
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 08af532..05152a7 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -1161,5 +1161,7 @@
   if (HSOpts.UseStandardIncludes)
     Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts);
 
+  HS.setModuleCachePath(HSOpts.ModuleCachePath);
+  
   Init.Realize(Lang);
 }
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 0ba7632..3682675 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -98,6 +98,16 @@
   return 0;
 }
 
+const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName) {
+  // If we don't have a module cache path, we can't do anything.
+  if (ModuleCachePath.empty())
+    return 0;
+  
+  llvm::SmallString<256> FileName(ModuleCachePath);
+  llvm::sys::path::append(FileName, ModuleName + ".pcm");
+  return getFileMgr().getFile(FileName);
+}
+
 //===----------------------------------------------------------------------===//
 // File lookup within a DirectoryLookup scope
 //===----------------------------------------------------------------------===//
diff --git a/test/Modules/diamond.c b/test/Modules/diamond.c
index 6f6ff7b..13389e2 100644
--- a/test/Modules/diamond.c
+++ b/test/Modules/diamond.c
@@ -21,7 +21,7 @@
 }
 
 // RUN: %clang_cc1 -emit-module -o %T/diamond_top.pcm %S/Inputs/diamond_top.h
-// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_left.pcm %S/Inputs/diamond_left.h
-// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_right.pcm %S/Inputs/diamond_right.h
-// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_bottom.pcm %S/Inputs/diamond_bottom.h
-// RUN: %clang_cc1 -I %T %s -verify
+// RUN: %clang_cc1 -fmodule-cache-path %T -emit-module -o %T/diamond_left.pcm %S/Inputs/diamond_left.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -emit-module -o %T/diamond_right.pcm %S/Inputs/diamond_right.h
+// RUN: %clang_cc1 -fmodule-cache-path %T -emit-module -o %T/diamond_bottom.pcm %S/Inputs/diamond_bottom.h
+// RUN: %clang_cc1 -fmodule-cache-path %T %s -verify
diff --git a/test/Modules/load_failure.c b/test/Modules/load_failure.c
index f034c78..4685a41 100644
--- a/test/Modules/load_failure.c
+++ b/test/Modules/load_failure.c
@@ -7,10 +7,10 @@
 #endif
 
 // RUN: %clang_cc1 -x c++ -emit-module -o %T/load_failure.pcm %S/Inputs/load_failure.h
-// RUN: %clang_cc1 -I %T %s -DNONEXISTENT 2>&1 | FileCheck -check-prefix=CHECK-NONEXISTENT %s
+// RUN: %clang_cc1 -fmodule-cache-path %T %s -DNONEXISTENT 2>&1 | FileCheck -check-prefix=CHECK-NONEXISTENT %s
 // CHECK-NONEXISTENT: load_failure.c:2:19: fatal error: module 'load_nonexistent' not found
 
-// RUN: not %clang_cc1 -I %T %s -DFAILURE 2> %t
+// RUN: not %clang_cc1 -fmodule-cache-path %T %s -DFAILURE 2> %t
 // RUN: FileCheck -check-prefix=CHECK-FAILURE %s < %t
 
 // FIXME: Clean up diagnostic text below and give it a location
diff --git a/test/Modules/lookup.cpp b/test/Modules/lookup.cpp
index 7c53106..c8f7993 100644
--- a/test/Modules/lookup.cpp
+++ b/test/Modules/lookup.cpp
@@ -16,8 +16,8 @@
 
 // RUN: %clang_cc1 -emit-module -x c++ -verify -o %T/lookup_left_cxx.pcm %S/Inputs/lookup_left.hpp
 // RUN: %clang_cc1 -emit-module -x c++ -o %T/lookup_right_cxx.pcm %S/Inputs/lookup_right.hpp
-// RUN: %clang_cc1 -x c++ -I %T %s -verify
-// RUN: %clang_cc1 -ast-print -x c++ -I %T %s | FileCheck -check-prefix=CHECK-PRINT %s
+// RUN: %clang_cc1 -x c++ -fmodule-cache-path %T %s -verify
+// RUN: %clang_cc1 -ast-print -x c++ -fmodule-cache-path %T %s | FileCheck -check-prefix=CHECK-PRINT %s
 
 // CHECK-PRINT: int *f0(int *);
 // CHECK-PRINT: float *f0(float *);
diff --git a/test/Modules/lookup.m b/test/Modules/lookup.m
index 02898a5..ca68e89 100644
--- a/test/Modules/lookup.m
+++ b/test/Modules/lookup.m
@@ -10,8 +10,8 @@
 
 // RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_left_objc.pcm %S/Inputs/lookup_left.h
 // RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_right_objc.pcm %S/Inputs/lookup_right.h
-// RUN: %clang_cc1 -x objective-c -I %T -verify %s
-// RUN: %clang_cc1 -ast-print -x objective-c -I %T %s | FileCheck -check-prefix=CHECK-PRINT %s
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %T -verify %s
+// RUN: %clang_cc1 -ast-print -x objective-c -fmodule-cache-path %T %s | FileCheck -check-prefix=CHECK-PRINT %s
 
 // CHECK-PRINT: - (int) method;
 // CHECK-PRINT: - (double) method
diff --git a/test/Modules/macros.c b/test/Modules/macros.c
index 691e8ec..346f91f 100644
--- a/test/Modules/macros.c
+++ b/test/Modules/macros.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -emit-module -o %t/macros.pcm -DMODULE %s
-// RUN: %clang_cc1 -verify -I %t %s
+// RUN: %clang_cc1 -verify -fmodule-cache-path %t %s
 
 #if defined(MODULE)
 #define INTEGER(X) int
diff --git a/test/Modules/module-private.cpp b/test/Modules/module-private.cpp
index 33ec320..539e591 100644
--- a/test/Modules/module-private.cpp
+++ b/test/Modules/module-private.cpp
@@ -1,7 +1,7 @@
 // RUN: mkdir -p %t
 // RUN: %clang_cc1 -x c++ -emit-module -o %t/left.pcm %s -D MODULE_LEFT
 // RUN: %clang_cc1 -x c++ -emit-module -o %t/right.pcm %s -D MODULE_RIGHT
-// RUN: %clang_cc1 -I %t %s -verify
+// RUN: %clang_cc1 -fmodule-cache-path %t %s -verify
 
 #if defined(MODULE_LEFT)
 
diff --git a/test/Modules/objc-categories.m b/test/Modules/objc-categories.m
index 3bae4b8..5797858 100644
--- a/test/Modules/objc-categories.m
+++ b/test/Modules/objc-categories.m
@@ -1,9 +1,9 @@
 // RUN: mkdir -p %t
 // RUN: %clang_cc1 -emit-module -o %t/diamond_top.pcm %s -D MODULE_TOP
-// RUN: %clang_cc1 -I %t -emit-module -o %t/diamond_left.pcm %s -D MODULE_LEFT
-// RUN: %clang_cc1 -I %t -emit-module -o %t/diamond_right.pcm %s -D MODULE_RIGHT
-// RUN: %clang_cc1 -I %t -emit-module -o %t/diamond_bottom.pcm %s -D MODULE_BOTTOM
-// RUN: %clang_cc1 -I %t %s -verify
+// RUN: %clang_cc1 -fmodule-cache-path %t -emit-module -o %t/diamond_left.pcm %s -D MODULE_LEFT
+// RUN: %clang_cc1 -fmodule-cache-path %t -emit-module -o %t/diamond_right.pcm %s -D MODULE_RIGHT
+// RUN: %clang_cc1 -fmodule-cache-path %t -emit-module -o %t/diamond_bottom.pcm %s -D MODULE_BOTTOM
+// RUN: %clang_cc1 -fmodule-cache-path %t %s -verify
 
 /*============================================================================*/
 #ifdef MODULE_TOP