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

Richard Smith richard at metafoo.co.uk
Wed Dec 10 17:42:50 PST 2014


On Mon, Apr 14, 2014 at 11:00 AM, Ben Langmuir <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
> 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.
>

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?)


> +    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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> 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/20141210/1a79aae2/attachment.html>


More information about the cfe-commits mailing list