r206201 - Allow multiple modules with the same name to coexist in the module cache

Ben Langmuir blangmuir at apple.com
Mon Apr 14 11:00:01 PDT 2014


Author: benlangmuir
Date: Mon Apr 14 13:00:01 2014
New Revision: 206201

URL: http://llvm.org/viewvc/llvm-project?rev=206201&view=rev
Log:
Allow multiple modules with the same name to coexist in the module cache

To differentiate between two modules with the same name, we will
consider the path the module map file that they are defined by* part of
the ‘key’ for looking up the precompiled module (pcm file).
Specifically, this patch renames the precompiled module (pcm) files from
  cache-path/<module hash>/Foo.pcm
to
  cache-path/<module hash>/Foo-<hash of module map path>.pcm

In addition, I’ve taught the ASTReader to re-resolve the names of
imported modules during module loading so that if the header search
context changes between when a module was originally built and when it
is loaded we can rebuild it if necessary.  For example, if module A
imports module B

first time:
clang -I /path/to/A -I /path/to/B ...

second time:
clang -I /path/to/A -I /different/path/to/B ...

will now rebuild A as expected.

* in the case of inferred modules, we use the module map file that
allowed the inference, not the __inferred_module.map file, since the
inferred file path is the same for every inferred module.

Added:
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/DependsOnA.h
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/module.modulemap
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/a.h
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/module.modulemap
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/a.h
    cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/module.modulemap
    cfe/trunk/test/Modules/modules-with-same-name.m
    cfe/trunk/test/Modules/resolution-change.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
    cfe/trunk/include/clang/Basic/Module.h
    cfe/trunk/include/clang/Frontend/FrontendActions.h
    cfe/trunk/include/clang/Lex/HeaderSearch.h
    cfe/trunk/include/clang/Lex/ModuleMap.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/include/clang/Serialization/Module.h
    cfe/trunk/lib/Basic/Module.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/FrontendAction.cpp
    cfe/trunk/lib/Frontend/FrontendActions.cpp
    cfe/trunk/lib/Lex/HeaderSearch.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp
    cfe/trunk/lib/Serialization/ModuleManager.cpp
    cfe/trunk/test/Index/annotate-module.m
    cfe/trunk/test/Index/pch-depending-on-deleted-module.c
    cfe/trunk/test/Modules/dependency-gen-pch.m
    cfe/trunk/test/Modules/diamond-pch.c
    cfe/trunk/test/Modules/macro-undef-through-pch.m
    cfe/trunk/test/Modules/prune.m
    cfe/trunk/test/Modules/redecls/main.m
    cfe/trunk/test/Modules/system_version.m
    cfe/trunk/test/PCH/modified-module-dependency.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Mon Apr 14 13:00:01 2014
@@ -48,7 +48,12 @@ def err_pch_different_branch : Error<
     "PCH file built from a different branch (%0) than the compiler (%1)">;
 def err_pch_with_compiler_errors : Error<
     "PCH file contains compiler errors">;
-    
+
+def err_imported_module_not_found : Error<
+    "module '%0' imported by AST file '%1' not found">, DefaultFatal;
+def err_imported_module_modmap_changed : Error<
+    "module '%0' imported by AST file '%1' found in a different module map file"
+    " (%2) than when the importing AST file was built (%3)">, DefaultFatal;
 def warn_module_conflict : Warning<
     "module '%0' conflicts with already-imported module '%1': %2">, 
     InGroup<ModuleConflict>;

Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Mon Apr 14 13:00:01 2014
@@ -51,10 +51,21 @@ public:
   
   /// \brief The location of the module definition.
   SourceLocation DefinitionLoc;
-  
+
   /// \brief The parent of this module. This will be NULL for the top-level
   /// module.
   Module *Parent;
+
+  /// \brief The module map file that (along with the module name) uniquely
+  /// identifies this module.
+  ///
+  /// The particular module that \c Name refers to may depend on how the module
+  /// was found in header search. However, the combination of \c Name and
+  /// \c ModuleMap will be globally unique for top-level modules. In the case of
+  /// inferred modules, \c ModuleMap will contain the module map that allowed
+  /// the inference (e.g. contained 'Module *') rather than the virtual
+  /// inferred module map file.
+  const FileEntry *ModuleMap;
   
   /// \brief The umbrella header or directory.
   llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
@@ -264,8 +275,10 @@ public:
   std::vector<Conflict> Conflicts;
 
   /// \brief Construct a new module or submodule.
-  Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, 
-         bool IsFramework, bool IsExplicit);
+  ///
+  /// For an explanation of \p ModuleMap, see Module::ModuleMap.
+  Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
+         const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit);
   
   ~Module();
   

Modified: cfe/trunk/include/clang/Frontend/FrontendActions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendActions.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendActions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendActions.h Mon Apr 14 13:00:01 2014
@@ -17,6 +17,7 @@
 namespace clang {
 
 class Module;
+class FileEntry;
   
 //===----------------------------------------------------------------------===//
 // Custom Consumer Actions
@@ -92,7 +93,8 @@ public:
 };
 
 class GenerateModuleAction : public ASTFrontendAction {
-  clang::Module *Module;
+  Module *Module;
+  const FileEntry *ModuleMapForUniquing;
   bool IsSystem;
   
 protected:
@@ -106,8 +108,10 @@ protected:
   bool hasASTFileSupport() const override { return false; }
 
 public:
-  explicit GenerateModuleAction(bool IsSystem = false)
-    : ASTFrontendAction(), IsSystem(IsSystem) { }
+  GenerateModuleAction(const FileEntry *ModuleMap = nullptr,
+                       bool IsSystem = false)
+    : ASTFrontendAction(), ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem)
+  { }
 
   bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
 
@@ -115,11 +119,11 @@ public:
   /// create the PCHGenerator instance returned by CreateASTConsumer.
   ///
   /// \returns true if an error occurred, false otherwise.
-  static bool ComputeASTConsumerArguments(CompilerInstance &CI,
-                                          StringRef InFile,
-                                          std::string &Sysroot,
-                                          std::string &OutputFile,
-                                          raw_ostream *&OS);
+  bool ComputeASTConsumerArguments(CompilerInstance &CI,
+                                   StringRef InFile,
+                                   std::string &Sysroot,
+                                   std::string &OutputFile,
+                                   raw_ostream *&OS);
 };
 
 class SyntaxOnlyAction : public ASTFrontendAction {

Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Mon Apr 14 13:00:01 2014
@@ -493,9 +493,12 @@ public:
   ///
   /// \param ModuleName The module whose module file name will be returned.
   ///
+  /// \param ModuleMapPath A path that when combined with \c ModuleName
+  /// uniquely identifies this module. See Module::ModuleMap.
+  ///
   /// \returns The name of the module file that corresponds to this module,
   /// or an empty string if this module does not correspond to any module file.
-  std::string getModuleFileName(StringRef ModuleName);
+  std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath);
 
   /// \brief Lookup a module Search for a module with the given name.
   ///

Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Mon Apr 14 13:00:01 2014
@@ -131,6 +131,10 @@ private:
     /// \brief Whether the modules we infer are [system] modules.
     unsigned InferSystemModules : 1;
 
+    /// \brief If \c InferModules is non-zero, the module map file that allowed
+    /// inferred modules.  Otherwise, nullptr.
+    const FileEntry *ModuleMapFile;
+
     /// \brief The names of modules that cannot be inferred within this
     /// directory.
     SmallVector<std::string, 2> ExcludedModules;
@@ -293,13 +297,17 @@ public:
   /// \param Parent The module that will act as the parent of this submodule,
   /// or NULL to indicate that this is a top-level module.
   ///
+  /// \param ModuleMap The module map that defines or allows the inference of
+  /// this module.
+  ///
   /// \param IsFramework Whether this is a framework module.
   ///
   /// \param IsExplicit Whether this is an explicit submodule.
   ///
   /// \returns The found or newly-created module, along with a boolean value
   /// that will be true if the module is newly-created.
-  std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, 
+  std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
+                                               const FileEntry *ModuleMap,
                                                bool IsFramework,
                                                bool IsExplicit);
 

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Mon Apr 14 13:00:01 2014
@@ -281,7 +281,14 @@ namespace clang {
       HEADER_SEARCH_OPTIONS = 11,
 
       /// \brief Record code for the preprocessor options table.
-      PREPROCESSOR_OPTIONS = 12
+      PREPROCESSOR_OPTIONS = 12,
+
+      /// \brief Record code for the module name.
+      MODULE_NAME = 13,
+
+      /// \brief Record code for the module map file that was used to build this
+      /// AST file.
+      MODULE_MAP_FILE = 14
     };
 
     /// \brief Record types that occur within the input-files block

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Mon Apr 14 13:00:01 2014
@@ -1079,6 +1079,7 @@ private:
                             unsigned ClientLoadCapabilities);
   ASTReadResult ReadControlBlock(ModuleFile &F,
                                  SmallVectorImpl<ImportedModule> &Loaded,
+                                 const ModuleFile *ImportedBy,
                                  unsigned ClientLoadCapabilities);
   ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
   bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);

Modified: cfe/trunk/include/clang/Serialization/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/Module.h (original)
+++ cfe/trunk/include/clang/Serialization/Module.h Mon Apr 14 13:00:01 2014
@@ -116,6 +116,9 @@ public:
   /// \brief The file name of the module file.
   std::string FileName;
 
+  /// \brief The name of the module.
+  std::string ModuleName;
+
   std::string getTimestampFilename() const {
     return FileName + ".timestamp";
   }
@@ -137,6 +140,8 @@ public:
   /// allow resolving headers even after headers+PCH was moved to a new path.
   std::string OriginalDir;
 
+  std::string ModuleMapPath;
+
   /// \brief Whether this precompiled header is a relocatable PCH file.
   bool RelocatablePCH;
 

Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Mon Apr 14 13:00:01 2014
@@ -25,8 +25,8 @@
 using namespace clang;
 
 Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
-               bool IsFramework, bool IsExplicit)
-  : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
+               const FileEntry *File, bool IsFramework, bool IsExplicit)
+  : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), ModuleMap(File),
     Umbrella(), ASTFile(0), IsAvailable(true), IsFromModuleFile(false),
     IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
     IsExternC(false), InferSubmodules(false), InferExplicitSubmodules(false),

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Mon Apr 14 13:00:01 2014
@@ -870,8 +870,9 @@ static void compileModuleImpl(CompilerIn
     SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer);
   }
 
-  // Construct a module-generating action.
-  GenerateModuleAction CreateModuleAction(Module->IsSystem);
+  // Construct a module-generating action. Passing through Module->ModuleMap is
+  // safe because the FileManager is shared between the compiler instances.
+  GenerateModuleAction CreateModuleAction(Module->ModuleMap, Module->IsSystem);
   
   // Execute the action to actually build the module in-place. Use a separate
   // thread so that we get a stack large enough.

Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendAction.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendAction.cpp Mon Apr 14 13:00:01 2014
@@ -256,6 +256,10 @@ bool FrontendAction::BeginSourceFile(Com
     if (!BeginSourceFileAction(CI, InputFile))
       goto failure;
 
+    // Initialize the main file entry.
+    if (!CI.InitializeSourceManager(CurrentInput))
+      goto failure;
+
     return true;
   }
 
@@ -302,6 +306,11 @@ bool FrontendAction::BeginSourceFile(Com
   if (!BeginSourceFileAction(CI, InputFile))
     goto failure;
 
+  // Initialize the main file entry. It is important that this occurs after
+  // BeginSourceFileAction, which may change CurrentInput during module builds.
+  if (!CI.InitializeSourceManager(CurrentInput))
+    goto failure;
+
   // Create the AST context and consumer unless this is a preprocessor only
   // action.
   if (!usesPreprocessorOnly()) {
@@ -389,13 +398,6 @@ bool FrontendAction::BeginSourceFile(Com
 bool FrontendAction::Execute() {
   CompilerInstance &CI = getCompilerInstance();
 
-  // Initialize the main file entry. This needs to be delayed until after PCH
-  // has loaded.
-  if (!isCurrentFileAST()) {
-    if (!CI.InitializeSourceManager(getCurrentInput()))
-      return false;
-  }
-
   if (CI.hasFrontendTimer()) {
     llvm::TimeRegion Timer(CI.getFrontendTimer());
     ExecuteAction();

Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Mon Apr 14 13:00:01 2014
@@ -299,6 +299,11 @@ bool GenerateModuleAction::BeginSourceFi
     return false;
   }
 
+  if (!ModuleMapForUniquing)
+    ModuleMapForUniquing = ModuleMap;
+  Module->ModuleMap = ModuleMapForUniquing;
+  assert(Module->ModuleMap && "missing module map file");
+
   FileManager &FileMgr = CI.getFileManager();
 
   // Collect the set of #includes we need to build the module.
@@ -337,10 +342,9 @@ bool GenerateModuleAction::ComputeASTCon
   // in the module cache.
   if (CI.getFrontendOpts().OutputFile.empty()) {
     HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
-    SmallString<256> ModuleFileName(HS.getModuleCachePath());
-    llvm::sys::path::append(ModuleFileName, 
-                            CI.getLangOpts().CurrentModule + ".pcm");
-    CI.getFrontendOpts().OutputFile = ModuleFileName.str();
+    CI.getFrontendOpts().OutputFile =
+        HS.getModuleFileName(CI.getLangOpts().CurrentModule,
+                             ModuleMapForUniquing->getName());
   }
   
   // We use createOutputFile here because this is exposed via libclang, and we

Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Mon Apr 14 13:00:01 2014
@@ -18,6 +18,8 @@
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/Lexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Capacity.h"
 #include "llvm/Support/FileSystem.h"
@@ -112,24 +114,33 @@ const HeaderMap *HeaderSearch::CreateHea
 }
 
 std::string HeaderSearch::getModuleFileName(Module *Module) {
-  // If we don't have a module cache path, we can't do anything.
-  if (ModuleCachePath.empty()) 
-    return std::string();
-
-
-  SmallString<256> Result(ModuleCachePath);
-  llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm");
-  return Result.str().str();
+  return getModuleFileName(Module->Name, Module->ModuleMap->getName());
 }
 
-std::string HeaderSearch::getModuleFileName(StringRef ModuleName) {
+std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
+                                            StringRef ModuleMapPath) {
   // If we don't have a module cache path, we can't do anything.
   if (ModuleCachePath.empty()) 
     return std::string();
-  
-  
+
   SmallString<256> Result(ModuleCachePath);
-  llvm::sys::path::append(Result, ModuleName + ".pcm");
+  llvm::sys::fs::make_absolute(Result);
+
+  if (HSOpts->DisableModuleHash) {
+    llvm::sys::path::append(Result, ModuleName + ".pcm");
+  } else {
+    // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
+    // be globally unique to this particular module. To avoid false-negatives
+    // on case-insensitive filesystems, we use lower-case, which is safe because
+    // to cause a collision the modules must have the same name, which is an
+    // error if they are imported in the same translation.
+    SmallString<256> AbsModuleMapPath(ModuleMapPath);
+    llvm::sys::fs::make_absolute(AbsModuleMapPath);
+    llvm::APInt Code(64, llvm::hash_value(AbsModuleMapPath.str().lower()));
+    SmallString<128> HashStr;
+    Code.toStringUnsigned(HashStr, /*Radix*/36);
+    llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
+  }
   return Result.str().str();
 }
 

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Apr 14 13:00:01 2014
@@ -363,8 +363,8 @@ ModuleMap::findModuleForHeader(const Fil
         SmallString<32> NameBuf;
         StringRef Name = sanitizeFilenameAsIdentifier(
             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
-        Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
-                                    Explicit).first;
+        Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap,
+                                    /*IsFramework=*/false, Explicit).first;
 
         // Associate the module and the directory.
         UmbrellaDirs[SkippedDirs[I-1]] = Result;
@@ -378,9 +378,9 @@ ModuleMap::findModuleForHeader(const Fil
       // Infer a submodule with the same name as this header file.
       SmallString<32> NameBuf;
       StringRef Name = sanitizeFilenameAsIdentifier(
-                                                    llvm::sys::path::stem(File->getName()), NameBuf);
-      Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
-                                  Explicit).first;
+                         llvm::sys::path::stem(File->getName()), NameBuf);
+      Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap,
+                                  /*IsFramework=*/false, Explicit).first;
       Result->addTopHeader(File);
 
       // If inferred submodules export everything they import, add a
@@ -518,15 +518,16 @@ Module *ModuleMap::lookupModuleQualified
 }
 
 std::pair<Module *, bool> 
-ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
+ModuleMap::findOrCreateModule(StringRef Name, Module *Parent,
+                              const FileEntry *ModuleMap, bool IsFramework,
                               bool IsExplicit) {
   // Try to find an existing module with this name.
   if (Module *Sub = lookupModuleQualified(Name, Parent))
     return std::make_pair(Sub, false);
   
   // Create a new module with this name.
-  Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 
-                              IsExplicit);
+  Module *Result = new Module(Name, SourceLocation(), Parent, ModuleMap,
+                              IsFramework, IsExplicit);
   if (LangOpts.CurrentModule == Name) {
     SourceModule = Result;
     SourceModuleName = Name;
@@ -595,6 +596,7 @@ ModuleMap::inferFrameworkModule(StringRe
 
   // If the framework has a parent path from which we're allowed to infer
   // a framework module, do so.
+  const FileEntry *ModuleMapFile = nullptr;
   if (!Parent) {
     // Determine whether we're allowed to infer a module map.
 
@@ -639,6 +641,7 @@ ModuleMap::inferFrameworkModule(StringRe
 
           if (inferred->second.InferSystemModules)
             IsSystem = true;
+          ModuleMapFile = inferred->second.ModuleMapFile;
         }
       }
     }
@@ -646,7 +649,8 @@ ModuleMap::inferFrameworkModule(StringRe
     // If we're not allowed to infer a framework module, don't.
     if (!canInfer)
       return 0;
-  }
+  } else
+    ModuleMapFile = Parent->ModuleMap;
 
 
   // Look for an umbrella header.
@@ -660,7 +664,7 @@ ModuleMap::inferFrameworkModule(StringRe
   if (!UmbrellaHeader)
     return 0;
   
-  Module *Result = new Module(ModuleName, SourceLocation(), Parent,
+  Module *Result = new Module(ModuleName, SourceLocation(), Parent, ModuleMapFile,
                               /*IsFramework=*/true, /*IsExplicit=*/false);
   if (LangOpts.CurrentModule == ModuleName) {
     SourceModule = Result;
@@ -954,6 +958,9 @@ namespace clang {
 
     DiagnosticsEngine &Diags;
     ModuleMap ⤅
+
+    /// \brief The current module map file.
+    const FileEntry *ModuleMapFile;
     
     /// \brief The directory that this module map resides in.
     const DirectoryEntry *Directory;
@@ -1007,12 +1014,14 @@ namespace clang {
                              const TargetInfo *Target,
                              DiagnosticsEngine &Diags,
                              ModuleMap &Map,
+                             const FileEntry *ModuleMapFile,
                              const DirectoryEntry *Directory,
                              const DirectoryEntry *BuiltinIncludeDir,
                              bool IsSystem)
       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 
-        Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
-        IsSystem(IsSystem), HadError(false), ActiveModule(0)
+        ModuleMapFile(ModuleMapFile), Directory(Directory),
+        BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem),
+        HadError(false), ActiveModule(0)
     {
       Tok.clear();
       consumeToken();
@@ -1359,9 +1368,14 @@ void ModuleMapParser::parseModuleDecl()
     return;
   }
 
+  // If this is a submodule, use the parent's module map, since we don't want
+  // the private module map file.
+  const FileEntry *ModuleMap = ActiveModule ? ActiveModule->ModuleMap
+                                            : ModuleMapFile;
+
   // Start defining this module.
-  ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
-                                        Explicit).first;
+  ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, ModuleMap,
+                                        Framework, Explicit).first;
   ActiveModule->DefinitionLoc = ModuleNameLoc;
   if (Attrs.IsSystem || IsSystem)
     ActiveModule->IsSystem = true;
@@ -2020,6 +2034,7 @@ void ModuleMapParser::parseInferredModul
     // We'll be inferring framework modules for this directory.
     Map.InferredDirectories[Directory].InferModules = true;
     Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
+    Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
     // FIXME: Handle the 'framework' keyword.
   }
 
@@ -2256,7 +2271,7 @@ bool ModuleMap::parseModuleMapFile(const
   
   // Parse this module map file.
   Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
-  ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, Dir,
+  ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
                          BuiltinIncludeDir, IsSystem);
   bool Result = Parser.parseModuleMapFile();
   ParsedModuleMap[File] = Result;

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Apr 14 13:00:01 2014
@@ -1161,7 +1161,7 @@ std::pair<SourceLocation, StringRef> AST
 
   // FIXME: Can we map this down to a particular submodule? That would be
   // ideal.
-  return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));
+  return std::make_pair(M->ImportLoc, StringRef(M->ModuleName));
 }
 
 /// \brief Find the location where the module F is imported.
@@ -1172,14 +1172,10 @@ SourceLocation ASTReader::getImportLocat
   // Otherwise we have a PCH. It's considered to be "imported" at the first
   // location of its includer.
   if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
-    // Main file is the importer. We assume that it is the first entry in the
-    // entry table. We can't ask the manager, because at the time of PCH loading
-    // the main file entry doesn't exist yet.
-    // The very first entry is the invalid instantiation loc, which takes up
-    // offsets 0 and 1.
-    return SourceLocation::getFromRawEncoding(2U);
+    // Main file is the importer.
+    assert(!SourceMgr.getMainFileID().isInvalid() && "missing main file");
+    return SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
   }
-  //return F->Loaders[0]->FirstLoc;
   return F->ImportedBy[0]->FirstLoc;
 }
 
@@ -2089,6 +2085,7 @@ void ASTReader::MaybeAddSystemRootToFile
 ASTReader::ASTReadResult
 ASTReader::ReadControlBlock(ModuleFile &F,
                             SmallVectorImpl<ImportedModule> &Loaded,
+                            const ModuleFile *ImportedBy,
                             unsigned ClientLoadCapabilities) {
   BitstreamCursor &Stream = F.Stream;
 
@@ -2314,6 +2311,44 @@ ASTReader::ReadControlBlock(ModuleFile &
       F.OriginalDir = Blob;
       break;
 
+    case MODULE_NAME:
+      F.ModuleName = Blob;
+      break;
+
+    case MODULE_MAP_FILE:
+      F.ModuleMapPath = Blob;
+
+      // Try to resolve ModuleName in the current header search context and
+      // verify that it is found in the same module map file as we saved. If the
+      // top-level AST file is a main file, skip this check because there is no
+      // usable header search context.
+      assert(!F.ModuleName.empty() &&
+             "MODULE_NAME should come before MOUDLE_MAP_FILE");
+      if (F.Kind == MK_Module &&
+          (*ModuleMgr.begin())->Kind != MK_MainFile) {
+        Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
+        if (!M) {
+          assert(ImportedBy && "top-level import should be verified");
+          if ((ClientLoadCapabilities & ARR_Missing) == 0)
+            Diag(diag::err_imported_module_not_found)
+              << F.ModuleName << ImportedBy->FileName;
+          return Missing;
+        }
+
+        const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath);
+        if (StoredModMap == nullptr || StoredModMap != M->ModuleMap) {
+          assert(M->ModuleMap && "found module is missing module map file");
+          assert(M->Name == F.ModuleName && "found module with different name");
+          assert(ImportedBy && "top-level import should be verified");
+          if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+            Diag(diag::err_imported_module_modmap_changed)
+              << F.ModuleName << ImportedBy->FileName
+              << M->ModuleMap->getName() << F.ModuleMapPath;
+          return OutOfDate;
+        }
+      }
+      break;
+
     case INPUT_FILE_OFFSETS:
       F.InputFileOffsets = (const uint32_t *)Blob.data();
       F.InputFilesLoaded.resize(Record[0]);
@@ -3537,7 +3572,7 @@ ASTReader::ReadASTCore(StringRef FileNam
       break;
     case CONTROL_BLOCK_ID:
       HaveReadControlBlock = true;
-      switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {
+      switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) {
       case Success:
         break;
 
@@ -4059,13 +4094,19 @@ ASTReader::ReadSubmoduleBlock(ModuleFile
       bool InferExportWildcard = Record[Idx++];
       bool ConfigMacrosExhaustive = Record[Idx++];
 
-      Module *ParentModule = 0;
-      if (Parent)
+      Module *ParentModule = nullptr;
+      const FileEntry *ModuleMap = nullptr;
+      if (Parent) {
         ParentModule = getSubmodule(Parent);
-      
+        ModuleMap = ParentModule->ModuleMap;
+      }
+
+      if (!F.ModuleMapPath.empty())
+        ModuleMap = FileMgr.getFile(F.ModuleMapPath);
+
       // Retrieve this (sub)module from the module map, creating it if
       // necessary.
-      CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, 
+      CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, ModuleMap,
                                                 IsFramework, 
                                                 IsExplicit).first;
       SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
@@ -4090,7 +4131,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile
 
         CurrentModule->setASTFile(F.File);
       }
-      
+
       CurrentModule->IsFromModuleFile = true;
       CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
       CurrentModule->IsExternC = IsExternC;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Apr 14 13:00:01 2014
@@ -798,6 +798,8 @@ void ASTWriter::WriteBlockInfoBlock() {
   // Control Block.
   BLOCK(CONTROL_BLOCK);
   RECORD(METADATA);
+  RECORD(MODULE_NAME);
+  RECORD(MODULE_MAP_FILE);
   RECORD(IMPORTS);
   RECORD(LANGUAGE_OPTIONS);
   RECORD(TARGET_OPTIONS);
@@ -1050,6 +1052,32 @@ void ASTWriter::WriteControlBlock(Prepro
   Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
                             getClangFullRepositoryVersion());
 
+  // Module name
+  if (WritingModule) {
+    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+    Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+    unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+    RecordData Record;
+    Record.push_back(MODULE_NAME);
+    Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);
+  }
+
+  // Module map file
+  if (WritingModule) {
+    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+    Abbrev->Add(BitCodeAbbrevOp(MODULE_MAP_FILE));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename
+    unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+
+    assert(WritingModule->ModuleMap && "missing module map");
+    SmallString<128> ModuleMap(WritingModule->ModuleMap->getName());
+    llvm::sys::fs::make_absolute(ModuleMap);
+    RecordData Record;
+    Record.push_back(MODULE_MAP_FILE);
+    Stream.EmitRecordWithBlob(AbbrevCode, Record, ModuleMap.str());
+  }
+
   // Imports
   if (Chain) {
     serialization::ModuleManager &Mgr = Chain->getModuleManager();
@@ -1065,7 +1093,6 @@ void ASTWriter::WriteControlBlock(Prepro
       AddSourceLocation((*M)->ImportLoc, Record);
       Record.push_back((*M)->File->getSize());
       Record.push_back((*M)->File->getModificationTime());
-      // FIXME: This writes the absolute path for AST files we depend on.
       const std::string &FileName = (*M)->FileName;
       Record.push_back(FileName.size());
       Record.append(FileName.begin(), FileName.end());

Modified: cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp (original)
+++ cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp Mon Apr 14 13:00:01 2014
@@ -14,6 +14,7 @@
 #include "ASTReaderInternals.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Lex/HeaderSearch.h"
 #include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Serialization/GlobalModuleIndex.h"
 #include "clang/Serialization/Module.h"
@@ -203,7 +204,12 @@ GlobalModuleIndex::GlobalModuleIndex(llv
       assert(Idx == Record.size() && "More module info?");
 
       // Record this module as an unresolved module.
-      UnresolvedModules[llvm::sys::path::stem(Modules[ID].FileName)] = ID;
+      // FIXME: this doesn't work correctly for module names containing path
+      // separators.
+      StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName);
+      // Remove the -<hash of ModuleMapPath>
+      ModuleName = ModuleName.rsplit('-').first;
+      UnresolvedModules[ModuleName] = ID;
       break;
     }
 
@@ -308,7 +314,7 @@ bool GlobalModuleIndex::lookupIdentifier
 
 bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) {
   // Look for the module in the global module index based on the module name.
-  StringRef Name = llvm::sys::path::stem(File->FileName);
+  StringRef Name = File->ModuleName;
   llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name);
   if (Known == UnresolvedModules.end()) {
     return true;

Modified: cfe/trunk/lib/Serialization/ModuleManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ModuleManager.cpp?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ModuleManager.cpp (original)
+++ cfe/trunk/lib/Serialization/ModuleManager.cpp Mon Apr 14 13:00:01 2014
@@ -11,6 +11,7 @@
 //  modules for the ASTReader.
 //
 //===----------------------------------------------------------------------===//
+#include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/ModuleMap.h"
 #include "clang/Serialization/GlobalModuleIndex.h"
 #include "clang/Serialization/ModuleManager.h"
@@ -155,7 +156,7 @@ void ModuleManager::removeModules(Module
 
     FileMgr.invalidateCache((*victim)->File);
     if (modMap) {
-      StringRef ModuleName = llvm::sys::path::stem((*victim)->FileName);
+      StringRef ModuleName = (*victim)->ModuleName;
       if (Module *mod = modMap->findModule(ModuleName)) {
         mod->setASTFile(0);
       }
@@ -429,7 +430,7 @@ namespace llvm {
     }
 
     std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
-      return llvm::sys::path::stem(M->FileName);
+      return M->ModuleName;
     }
   };
 }

Modified: cfe/trunk/test/Index/annotate-module.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-module.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Index/annotate-module.m (original)
+++ cfe/trunk/test/Index/annotate-module.m Mon Apr 14 13:00:01 2014
@@ -44,6 +44,6 @@ int glob;
 // RUN: c-index-test -cursor-at=%s:3:11 %s -fmodules-cache-path=%t.cache -fmodules -F %S/../Modules/Inputs \
 // RUN:     | FileCheck %s -check-prefix=CHECK-CURSOR
 
-// CHECK-CURSOR:      3:1 ModuleImport=DependsOnModule:3:1 (Definition) Extent=[3:1 - 3:24] Spelling=DependsOnModule ([3:9 - 3:24]) ModuleName=DependsOnModule ({{.*}}DependsOnModule.pcm) Headers(2):
+// CHECK-CURSOR:      3:1 ModuleImport=DependsOnModule:3:1 (Definition) Extent=[3:1 - 3:24] Spelling=DependsOnModule ([3:9 - 3:24]) ModuleName=DependsOnModule ({{.*}}DependsOnModule-{{[^.]*}}.pcm) Headers(2):
 // CHECK-CURSOR-NEXT: {{.*}}other.h
 // CHECK-CURSOR-NEXT: {{.*}}DependsOnModule.h

Modified: cfe/trunk/test/Index/pch-depending-on-deleted-module.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/pch-depending-on-deleted-module.c?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Index/pch-depending-on-deleted-module.c (original)
+++ cfe/trunk/test/Index/pch-depending-on-deleted-module.c Mon Apr 14 13:00:01 2014
@@ -4,10 +4,10 @@
 // RUN: mkdir %t
 
 // RUN: %clang_cc1 -x c-header -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -emit-pch -I %S/Inputs/Headers -o %t/use_LibA.pch %s
-// RUN: %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -verify-pch %t/use_LibA.pch
+// RUN: %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -verify-pch %t/use_LibA.pch
 // RUN: rm -f %t/modules-cache/LibA.pcm
-// RUN: not %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=modules-cache -verify-pch %t/use_LibA.pch 2>&1 | FileCheck -check-prefix=VERIFY %s
-// RUN: not c-index-test -test-load-source all -x c -fmodules -fdisable-module-hash -fmodules-cache-path=modules-cache -include-pch %t/use_LibA.pch %s 2>&1 | FileCheck -check-prefix=INDEX %s
+// RUN: not %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -verify-pch %t/use_LibA.pch 2>&1 | FileCheck -check-prefix=VERIFY %s
+// RUN: not c-index-test -test-load-source all -x c -fmodules -Xclang -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -include-pch %t/use_LibA.pch %s 2>&1 | FileCheck -check-prefix=INDEX %s
 
 // VERIFY: fatal error: malformed or corrupted AST file: 'Unable to load module
 // INDEX: {{^}}Failure: AST deserialization error occurred{{$}}

Added: cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/DependsOnA.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/DependsOnA.h?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/DependsOnA.h (added)
+++ cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/DependsOnA.h Mon Apr 14 13:00:01 2014
@@ -0,0 +1 @@
+ at import A;

Added: cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/module.modulemap?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/modules-with-same-name/DependsOnA/module.modulemap Mon Apr 14 13:00:01 2014
@@ -0,0 +1,4 @@
+module DependsOnA {
+  header "DependsOnA.h"
+  export *
+}

Added: cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/a.h?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/a.h Mon Apr 14 13:00:01 2014
@@ -0,0 +1 @@
+#define FROM_PATH 1

Added: cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/module.modulemap?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/modules-with-same-name/path1/A/module.modulemap Mon Apr 14 13:00:01 2014
@@ -0,0 +1,3 @@
+module A {
+  header "a.h"
+}

Added: cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/a.h?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/a.h Mon Apr 14 13:00:01 2014
@@ -0,0 +1 @@
+#define FROM_PATH 2

Added: cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/module.modulemap?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/modules-with-same-name/path2/A/module.modulemap Mon Apr 14 13:00:01 2014
@@ -0,0 +1,3 @@
+module A {
+  header "a.h"
+}

Modified: cfe/trunk/test/Modules/dependency-gen-pch.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/dependency-gen-pch.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Modules/dependency-gen-pch.m (original)
+++ cfe/trunk/test/Modules/dependency-gen-pch.m Mon Apr 14 13:00:01 2014
@@ -1,7 +1,7 @@
 // RUN: rm -rf %t-mcp
 // RUN: mkdir -p %t-mcp
 
-// RUN: %clang_cc1 -isysroot %S/Inputs/System -triple x86_64-apple-darwin10 -module-file-deps -dependency-file %t.d -MT %s.o -I %S/Inputs -fmodules -fmodules-cache-path=%t-mcp -emit-pch -o %t.pch %s
+// RUN: %clang_cc1 -isysroot %S/Inputs/System -triple x86_64-apple-darwin10 -module-file-deps -dependency-file %t.d -MT %s.o -I %S/Inputs -fmodules -fdisable-module-hash -fmodules-cache-path=%t-mcp -emit-pch -o %t.pch %s
 // RUN: FileCheck %s < %t.d
 // CHECK: dependency-gen-pch.m.o
 // CHECK-NEXT: dependency-gen-pch.m

Modified: cfe/trunk/test/Modules/diamond-pch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/diamond-pch.c?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Modules/diamond-pch.c (original)
+++ cfe/trunk/test/Modules/diamond-pch.c Mon Apr 14 13:00:01 2014
@@ -4,7 +4,7 @@
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_right %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_bottom %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-pch -fmodules-cache-path=%t -I %S/Inputs -o %t.pch %S/Inputs/diamond.h
-// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -include-pch %t.pch %s -verify
+// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -include-pch %t.pch %s -I %S/Inputs -verify
 // FIXME: When we have a syntax for modules in C, use that.
 
 void test_diamond(int i, float f, double d, char c) {

Modified: cfe/trunk/test/Modules/macro-undef-through-pch.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/macro-undef-through-pch.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Modules/macro-undef-through-pch.m (original)
+++ cfe/trunk/test/Modules/macro-undef-through-pch.m Mon Apr 14 13:00:01 2014
@@ -2,7 +2,9 @@
 // RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t \
 // RUN:            -I%S/Inputs/macro-undef-through-pch -emit-pch \
 // RUN:            %S/Inputs/macro-undef-through-pch/foo.h -o %t.pch
-// RUN: %clang_cc1 -x objective-c -fmodules -fmodules-cache-path=%t -include-pch %t.pch %s
+// RUN: %clang_cc1 -x objective-c -fmodules -fmodules-cache-path=%t \
+// RUN:            -I%S/Inputs/macro-undef-through-pch -emit-pch \
+// RUN:            -include-pch %t.pch %s
 
 // PR19215
 #undef AB

Added: cfe/trunk/test/Modules/modules-with-same-name.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/modules-with-same-name.m?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/modules-with-same-name.m (added)
+++ cfe/trunk/test/Modules/modules-with-same-name.m Mon Apr 14 13:00:01 2014
@@ -0,0 +1,35 @@
+// REQUIRES: shell
+// RUN: rm -rf %t
+
+// A from path 1
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-ignore-macro=EXPECTED_PATH -fmodules-ignore-macro=DIRECT -fsyntax-only %s -verify -I %S/Inputs/modules-with-same-name/path1/A -DDIRECT -DEXPECTED_PATH=1
+
+// A from path 2
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-ignore-macro=EXPECTED_PATH -fmodules-ignore-macro=DIRECT -fsyntax-only %s -verify -I %S/Inputs/modules-with-same-name/path2/A -DDIRECT -DEXPECTED_PATH=2
+
+// Confirm that we have two pcm files (one for each 'A').
+// RUN: find %t -name "A-*.pcm" | count 2
+
+// DependsOnA, using A from path 1
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-ignore-macro=EXPECTED_PATH -fmodules-ignore-macro=DIRECT -fsyntax-only %s -verify -I %S/Inputs/modules-with-same-name/DependsOnA -I %S/Inputs/modules-with-same-name/path1/A -DEXPECTED_PATH=1
+
+// Confirm that we have three pcm files (one for each 'A', and one for 'DependsOnA')
+// RUN: find %t -name "*.pcm" | count 3
+
+// DependsOnA, using A from path 2
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-ignore-macro=EXPECTED_PATH -fmodules-ignore-macro=DIRECT -fsyntax-only %s -verify -I %S/Inputs/modules-with-same-name/DependsOnA -I %S/Inputs/modules-with-same-name/path2/A -DEXPECTED_PATH=2
+
+// Confirm that we still have three pcm files, since DependsOnA will be rebuilt
+// RUN: find %t -name "*.pcm" | count 3
+
+#ifdef DIRECT
+ at import A;
+#else
+ at import DependsOnA;
+#endif
+
+#if FROM_PATH != EXPECTED_PATH
+#error "Got the wrong module!"
+#endif
+
+// expected-no-diagnostics

Modified: cfe/trunk/test/Modules/prune.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/prune.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Modules/prune.m (original)
+++ cfe/trunk/test/Modules/prune.m Mon Apr 14 13:00:01 2014
@@ -14,33 +14,33 @@
 // RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -F %S/Inputs -fmodules-cache-path=%t %s -verify
 // RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -F %S/Inputs -fmodules-cache-path=%t %s -verify
 // RUN: ls %t | grep modules.timestamp
-// RUN: ls -R %t | grep ^Module.pcm
-// RUN: ls -R %t | grep DependsOnModule.pcm
+// RUN: ls -R %t | grep ^Module.*pcm
+// RUN: ls -R %t | grep DependsOnModule.*pcm
 
 // Set the timestamp back more than two days. We should try to prune,
 // but nothing gets pruned because the module files are new enough.
 // RUN: touch -m -a -t 201101010000 %t/modules.timestamp 
 // RUN: %clang_cc1 -fmodules -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
 // RUN: ls %t | grep modules.timestamp
-// RUN: ls -R %t | grep ^Module.pcm
-// RUN: ls -R %t | grep DependsOnModule.pcm
+// RUN: ls -R %t | grep ^Module.*pcm
+// RUN: ls -R %t | grep DependsOnModule.*pcm
 
 // Set the DependsOnModule access time back more than four days.
 // This shouldn't prune anything, because the timestamp has been updated, so
 // the pruning mechanism won't fire.
-// RUN: find %t -name DependsOnModule.pcm | xargs touch -a -t 201101010000
+// RUN: find %t -name DependsOnModule*.pcm | xargs touch -a -t 201101010000
 // RUN: %clang_cc1 -fmodules -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
 // RUN: ls %t | grep modules.timestamp
-// RUN: ls -R %t | grep ^Module.pcm
-// RUN: ls -R %t | grep DependsOnModule.pcm
+// RUN: ls -R %t | grep ^Module.*pcm
+// RUN: ls -R %t | grep DependsOnModule.*pcm
 
 // Set both timestamp and DependsOnModule.pcm back beyond the cutoff.
 // This should trigger pruning, which will remove DependsOnModule but not Module.
 // RUN: touch -m -a -t 201101010000 %t/modules.timestamp 
-// RUN: find %t -name DependsOnModule.pcm | xargs touch -a -t 201101010000
+// RUN: find %t -name DependsOnModule..pcm | xargs touch -a -t 201101010000
 // RUN: %clang_cc1 -fmodules -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
 // RUN: ls %t | grep modules.timestamp
-// RUN: ls -R %t | grep ^Module.pcm
-// RUN: ls -R %t | not grep DependsOnModule.pcm
+// RUN: ls -R %t | grep ^Module.*pcm
+// RUN: ls -R %t | not grep DependsOnModule.*pcm
 
 // expected-no-diagnostics

Modified: cfe/trunk/test/Modules/redecls/main.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/redecls/main.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Modules/redecls/main.m (original)
+++ cfe/trunk/test/Modules/redecls/main.m Mon Apr 14 13:00:01 2014
@@ -3,7 +3,7 @@
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-name=b %S/module.map -fmodules-cache-path=%t.mcp
 // RUN: %clang_cc1 -fmodules %s -emit-pch -o %t1.pch -fmodules-cache-path=%t.mcp -I %S
 // RUN: %clang_cc1 -fmodules %s -emit-pch -o %t2.pch -include-pch %t1.pch -fmodules-cache-path=%t.mcp -I %S
-// RUN: %clang_cc1 -fmodules %s -fsyntax-only -include-pch %t2.pch -fmodules-cache-path=%t.mcp -verify
+// RUN: %clang_cc1 -fmodules %s -fsyntax-only -include-pch %t2.pch -I %S -fmodules-cache-path=%t.mcp -verify
 
 #ifndef HEADER1
 #define HEADER1

Added: cfe/trunk/test/Modules/resolution-change.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/resolution-change.m?rev=206201&view=auto
==============================================================================
--- cfe/trunk/test/Modules/resolution-change.m (added)
+++ cfe/trunk/test/Modules/resolution-change.m Mon Apr 14 13:00:01 2014
@@ -0,0 +1,24 @@
+// RUN: rm -rf %t
+
+// Build PCH using A from path 1
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/modules-with-same-name/DependsOnA -I %S/Inputs/modules-with-same-name/path1/A -emit-pch -o %t-A.pch %s
+
+// Use the PCH with the same header search options; should be fine
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/modules-with-same-name/DependsOnA -I %S/Inputs/modules-with-same-name/path1/A -include-pch %t-A.pch %s -fsyntax-only -Werror
+
+// Use the PCH with no way to resolve DependsOnA
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -include-pch %t-A.pch %s -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-NODOA %s
+// CHECK-NODOA: module 'DependsOnA' imported by AST file '{{.*A.pch}}' not found
+
+// Use the PCH with no way to resolve A
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/modules-with-same-name/DependsOnA -include-pch %t-A.pch %s -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-NOA %s
+// CHECK-NOA: module 'A' imported by AST file '{{.*DependsOnA.*pcm}}' not found
+
+// Use the PCH and have it resolve the the other A
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/modules-with-same-name/DependsOnA -I %S/Inputs/modules-with-same-name/path2/A -include-pch %t-A.pch %s -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-WRONGA %s
+// CHECK-WRONGA: module 'A' imported by AST file '{{.*DependsOnA.*pcm}}' found in a different module map file ({{.*path2.*}}) than when the importing AST file was built ({{.*path1.*}})
+
+#ifndef HEADER
+#define HEADER
+ at import DependsOnA;
+#endif

Modified: cfe/trunk/test/Modules/system_version.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/system_version.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/Modules/system_version.m (original)
+++ cfe/trunk/test/Modules/system_version.m Mon Apr 14 13:00:01 2014
@@ -11,21 +11,21 @@
 
 // Run once with no system version file. We should end up with one module.
 // RUN: %clang_cc1 -fmodules-cache-path=%t/cache -fmodules -isysroot %t -I %t/usr/include %s -verify
-// RUN: ls -R %t | grep -c ModA.pcm| grep 1
+// RUN: ls -R %t | grep -c "ModA.*pcm" | grep 1
 
 // Add a system version file and run again. We should now have two
 // module variants.
 // RUN: mkdir -p %t/System/Library/CoreServices
 // RUN: echo "hello" > %t/System/Library/CoreServices/SystemVersion.plist
 // RUN: %clang_cc1 -fmodules-cache-path=%t/cache -fmodules -isysroot %t -I %t/usr/include %s -verify
-// RUN: ls -R %t | grep -c ModA.pcm| grep 2
+// RUN: ls -R %t | grep -c "ModA.*pcm" | grep 2
 
 // Change the system version file and run again. We should now have three
 // module variants.
 // RUN: mkdir -p %t/System/Library/CoreServices
 // RUN: echo "modules" > %t/System/Library/CoreServices/SystemVersion.plist
 // RUN: %clang_cc1 -fmodules-cache-path=%t/cache -fmodules -isysroot %t -I %t/usr/include %s -verify
-// RUN: ls -R %t | grep -c ModA.pcm| grep 3
+// RUN: ls -R %t | grep -c "ModA.*pcm" | grep 3
 
 // expected-no-diagnostics
 @import ModA;

Modified: cfe/trunk/test/PCH/modified-module-dependency.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/modified-module-dependency.m?rev=206201&r1=206200&r2=206201&view=diff
==============================================================================
--- cfe/trunk/test/PCH/modified-module-dependency.m (original)
+++ cfe/trunk/test/PCH/modified-module-dependency.m Mon Apr 14 13:00:01 2014
@@ -5,13 +5,13 @@
 // RUN: cp %S/modified-module-dependency.module.map %t-dir/module.map
 
 // Precompile prefix.pch.
-// RUN: %clang_cc1 -x objective-c -I %t-dir -fmodules -fmodules-cache-path=%t-dir/cache -emit-pch %t-dir/prefix.h -o %t-dir/prefix.pch
+// RUN: %clang_cc1 -x objective-c -I %t-dir -fmodules -fmodules-cache-path=%t-dir/cache -fdisable-module-hash -emit-pch %t-dir/prefix.h -o %t-dir/prefix.pch
 
 // Modify the dependency.
 // RUN: echo ' ' >> %t-dir/test.h
 
 // Run and check the diagnostics.
-// RUN: not %clang_cc1 -x objective-c -include-pch %t-dir/prefix.pch -fmodules -fmodules-cache-path=%t-dir/cache -fsyntax-only %s 2> %t-dir/log
+// RUN: not %clang_cc1 -x objective-c -I %t-dir -include-pch %t-dir/prefix.pch -fmodules -fmodules-cache-path=%t-dir/cache -fdisable-module-hash -fsyntax-only %s 2> %t-dir/log
 // RUN: FileCheck %s < %t-dir/log
 
 // CHECK: file '[[TEST_H:.*[/\\]test\.h]]' has been modified since the precompiled header '[[PREFIX_PCH:.*/prefix\.pch]]' was built





More information about the cfe-commits mailing list