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

Ben Langmuir blangmuir at apple.com
Thu Dec 11 11:00:06 PST 2014


> On Dec 11, 2014, at 10:55 AM, Ben Langmuir <blangmuir at apple.com> wrote:
> 
>> 
>> On Dec 10, 2014, at 5:42 PM, Richard Smith <richard at metafoo.co.uk <mailto:richard at metafoo.co.uk>> wrote:
>> 
>> On Mon, Apr 14, 2014 at 11:00 AM, Ben Langmuir <blangmuir at apple.com <mailto:blangmuir at apple.com>> wrote:
>> Author: benlangmuir
>> Date: Mon Apr 14 13:00:01 2014
>> New Revision: 206201
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=206201&view=rev <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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.
>> 
>> Consider:
>> 
>>   foo/module.modulemap defines a module X
>>   FOO/module.modulemap also defines a module X
>> 
>> If we cause foo/module.modulemap's X to be built, and then we try to import X from FOO/module.modulemap, won't we import the wrong module from the module cache? (Put another way, if this were correct, why would we ever need to include the module map file's hash in the filename?)
> 
> The hash in the filename isn’t functionally necessary, since we can rebuild a module if the module map path has changed since it was built.  If we attempt to load a module with a hash collision (as in this case) we will discover that the module map path has changed in ReadModuleMapFileBlock, and rebuild it.  Obviously that sucks if you really have both FOO and foo.

To be clear: the hash prevents excessive rebuilding, but currently falls over in edge case.

> 
> The problem this code solves on a case-insensitive filesystem:
> * I have two modules, A and B.  A imports B.  B is in some directory name foo.
> * I build A.pcm with -I FOO
> * I build a TU that imports B and then A, but specify -I foo.
> 
> So when I import B, it will be “missing” if the hash of “foo" is different than “FOO".  And then when I load A, it will pull in the other B.pcm, leading to an error.
> 
> 
> I’m open to solving this some other way if you have ideas :-)  I looked at getting the canonical casing for the path, but IIRC it was really expensive on Windows and basically required doing a listdir on every component of the path.
> 
> Ben
> 
>>  
>> +    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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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
>> 
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu <mailto:cfe-commits at cs.uiuc.edu>
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits <http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141211/6ee3308c/attachment.html>


More information about the cfe-commits mailing list