r321855 - Reapply r321781: [Modules] Allow modules specified by -fmodule-map-file to shadow implicitly found ones

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 8 21:31:05 PST 2018


I haven't done a ton of investigation yet, but I suspect this commit is
responsible for breaking my LLVM module selfhost build, which uses libc++
as the STL, and builds LLD (No bots appear to test this configuration).

The error message can be found here:
https://gist.github.com/EricWF/fb5e1d18eb1069d23788469b5fb15442

I'll investigate further tomorrow, but I wanted to send this your way in
case it looks familiar.

/Eric

On Thu, Jan 4, 2018 at 7:33 PM, Bruno Cardoso Lopes via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: bruno
> Date: Thu Jan  4 18:33:18 2018
> New Revision: 321855
>
> URL: http://llvm.org/viewvc/llvm-project?rev=321855&view=rev
> Log:
> Reapply r321781: [Modules] Allow modules specified by -fmodule-map-file to
> shadow implicitly found ones
>
> When modules come from module map files explicitly specified by
> -fmodule-map-file= arguments, allow those to override/shadow modules
> with the same name that are found implicitly by header search. If such a
> module is looked up by name (e.g. @import), we will always find the one
> from -fmodule-map-file. If we try to use a shadowed module by including
> one of its headers report an error.
>
> This enables developers to force use of a specific copy of their module
> to be used if there are multiple copies that would otherwise be visible,
> for example if they develop modules that are installed in the default
> search paths.
>
> Patch originally by Ben Langmuir,
> http://lists.llvm.org/pipermail/cfe-commits/Week-of-
> Mon-20151116/143425.html
>
> Based on cfe-dev discussion:
> http://lists.llvm.org/pipermail/cfe-dev/2015-November/046164.html
>
> Differential Revision: https://reviews.llvm.org/D31269
>
> rdar://problem/23612102
>
> Added:
>     cfe/trunk/test/Modules/Inputs/shadow/A1/A.h
>     cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap
>     cfe/trunk/test/Modules/Inputs/shadow/A2/A.h
>     cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
>     cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
>     cfe/trunk/test/Modules/shadow.m
>     cfe/trunk/test/Modules/shadowed-submodule.m
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
>     cfe/trunk/include/clang/Basic/Module.h
>     cfe/trunk/include/clang/Lex/HeaderSearch.h
>     cfe/trunk/include/clang/Lex/ModuleMap.h
>     cfe/trunk/lib/Basic/Module.cpp
>     cfe/trunk/lib/Lex/HeaderSearch.cpp
>     cfe/trunk/lib/Lex/ModuleMap.cpp
>     cfe/trunk/lib/Lex/PPDirectives.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticCommonKinds.td?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Thu Jan  4
> 18:33:18 2018
> @@ -94,6 +94,9 @@ def remark_module_lock_failure : Remark<
>    "could not acquire lock file for module '%0': %1">,
> InGroup<ModuleBuild>;
>  def remark_module_lock_timeout : Remark<
>    "timed out waiting to acquire lock file for module '%0'">,
> InGroup<ModuleBuild>;
> +def err_module_shadowed : Error<"import of shadowed module '%0'">,
> DefaultFatal;
> +def err_module_build_shadowed_submodule : Error<
> +  "build a shadowed submodule '%0'">, DefaultFatal;
>  def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
>    DefaultFatal;
>  def err_module_prebuilt : Error<
>
> Modified: cfe/trunk/include/clang/Basic/Module.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/Module.h?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/Module.h (original)
> +++ cfe/trunk/include/clang/Basic/Module.h Thu Jan  4 18:33:18 2018
> @@ -197,6 +197,9 @@ public:
>    /// will be false to indicate that this (sub)module is not available.
>    SmallVector<Requirement, 2> Requirements;
>
> +  /// \brief A module with the same name that shadows this module.
> +  Module *ShadowingModule = nullptr;
> +
>    /// \brief Whether this module is missing a feature from \c
> Requirements.
>    unsigned IsMissingRequirement : 1;
>
> @@ -375,13 +378,20 @@ public:
>    ///
>    /// \param Target The target options used for the current translation
> unit.
>    ///
> -  /// \param Req If this module is unavailable, this parameter
> -  /// will be set to one of the requirements that is not met for use of
> -  /// this module.
> +  /// \param Req If this module is unavailable because of a missing
> requirement,
> +  /// this parameter will be set to one of the requirements that is not
> met for
> +  /// use of this module.
> +  ///
> +  /// \param MissingHeader If this module is unavailable because of a
> missing
> +  /// header, this parameter will be set to one of the missing headers.
> +  ///
> +  /// \param ShadowingModule If this module is unavailable because it is
> +  /// shadowed, this parameter will be set to the shadowing module.
>    bool isAvailable(const LangOptions &LangOpts,
>                     const TargetInfo &Target,
>                     Requirement &Req,
> -                   UnresolvedHeaderDirective &MissingHeader) const;
> +                   UnresolvedHeaderDirective &MissingHeader,
> +                   Module *&ShadowingModule) const;
>
>    /// \brief Determine whether this module is a submodule.
>    bool isSubModule() const { return Parent != nullptr; }
>
> Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Lex/HeaderSearch.h?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
> +++ cfe/trunk/include/clang/Lex/HeaderSearch.h Thu Jan  4 18:33:18 2018
> @@ -726,6 +726,7 @@ private:
>    LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
>                                              bool IsSystem,
>                                              const DirectoryEntry *Dir,
> +                                            bool IsExplicitlyProvided,
>                                              FileID ID = FileID(),
>                                              unsigned *Offset = nullptr);
>
>
> Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Lex/ModuleMap.h?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
> +++ cfe/trunk/include/clang/Lex/ModuleMap.h Thu Jan  4 18:33:18 2018
> @@ -98,6 +98,9 @@ class ModuleMap {
>    /// \brief The top-level modules that are known.
>    llvm::StringMap<Module *> Modules;
>
> +  /// Shadow modules created while building this module map.
> +  llvm::SmallVector<Module*, 2> ShadowModules;
> +
>    /// \brief The number of modules we have created in total.
>    unsigned NumCreatedModules = 0;
>
> @@ -195,6 +198,17 @@ private:
>    /// header.
>    llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
>
> +  /// \brief The set of modules provided explicitly (e.g. by
> -fmodule-map-file),
> +  /// which are allowed to shadow other implicitly discovered modules.
> +  llvm::DenseSet<const Module *> ExplicitlyProvidedModules;
> +
> +  bool mayShadowModuleBeingParsed(Module *ExistingModule,
> +                                  bool IsExplicitlyProvided) {
> +    assert(!ExistingModule->Parent && "expected top-level module");
> +    return !IsExplicitlyProvided &&
> +           ExplicitlyProvidedModules.count(ExistingModule);
> +  }
> +
>    /// \brief The set of attributes that can be attached to a module.
>    struct Attributes {
>      /// \brief Whether this is a system module.
> @@ -475,9 +489,9 @@ public:
>    ///
>    /// \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,
> -                                               bool IsFramework,
> -                                               bool IsExplicit);
> +  std::pair<Module *, bool>
> +  findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
> +                     bool IsExplicit, bool UsesExplicitModuleMapFile =
> false);
>
>    /// \brief Create a 'global module' for a C++ Modules TS module
> interface
>    /// unit.
> @@ -502,6 +516,11 @@ public:
>    Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
>                                 bool IsSystem, Module *Parent);
>
> +  /// \brief Create a new top-level module that is shadowed by
> +  /// \p ShadowingModule.
> +  Module *createShadowedModule(StringRef Name, bool IsFramework,
> +                               Module *ShadowingModule);
> +
>    /// \brief Retrieve the module map file containing the definition of
> the given
>    /// module.
>    ///
> @@ -587,6 +606,8 @@ public:
>    /// \brief Marks this header as being excluded from the given module.
>    void excludeHeader(Module *Mod, Module::Header Header);
>
> +  void setExplicitlyProvided(Module *Mod);
> +
>    /// \brief Parse the given module map file, and record any modules we
>    /// encounter.
>    ///
> @@ -606,10 +627,15 @@ public:
>    /// \param ExternModuleLoc The location of the "extern module"
> declaration
>    ///        that caused us to load this module map file, if any.
>    ///
> +  /// \param IsExplicitlyProvided Whether this module map file was
> provided
> +  /// explicitly by the user (e.g. -fmodule-map-file), rather than found
> +  /// implicitly.
> +  ///
>    /// \returns true if an error occurred, false otherwise.
>    bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
> -                          const DirectoryEntry *HomeDir, FileID ID =
> FileID(),
> -                          unsigned *Offset = nullptr,
> +                          const DirectoryEntry *HomeDir,
> +                          bool IsExplicitlyProvided = false,
> +                          FileID ID = FileID(), unsigned *Offset =
> nullptr,
>                            SourceLocation ExternModuleLoc =
> SourceLocation());
>
>    /// \brief Dump the contents of the module map, for debugging purposes.
>
> Modified: cfe/trunk/lib/Basic/Module.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/
> Module.cpp?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Basic/Module.cpp (original)
> +++ cfe/trunk/lib/Basic/Module.cpp Thu Jan  4 18:33:18 2018
> @@ -95,11 +95,16 @@ static bool hasFeature(StringRef Feature
>
>  bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo
> &Target,
>                           Requirement &Req,
> -                         UnresolvedHeaderDirective &MissingHeader) const {
> +                         UnresolvedHeaderDirective &MissingHeader,
> +                         Module *&ShadowingModule) const {
>    if (IsAvailable)
>      return true;
>
>    for (const Module *Current = this; Current; Current = Current->Parent) {
> +    if (Current->ShadowingModule) {
> +      ShadowingModule = Current->ShadowingModule;
> +      return false;
> +    }
>      for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
>        if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
>                Current->Requirements[I].second) {
>
> Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/
> HeaderSearch.cpp?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
> +++ cfe/trunk/lib/Lex/HeaderSearch.cpp Thu Jan  4 18:33:18 2018
> @@ -1367,7 +1367,8 @@ bool HeaderSearch::loadModuleMapFile(con
>      }
>    }
>
> -  switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) {
> +  switch (loadModuleMapFileImpl(File, IsSystem, Dir,
> +                                /*IsExplictlyProvided=*/true, ID,
> Offset)) {
>    case LMM_AlreadyLoaded:
>    case LMM_NewlyLoaded:
>      return false;
> @@ -1378,10 +1379,9 @@ bool HeaderSearch::loadModuleMapFile(con
>    llvm_unreachable("Unknown load module map result");
>  }
>
> -HeaderSearch::LoadModuleMapResult
> -HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem,
> -                                    const DirectoryEntry *Dir, FileID ID,
> -                                    unsigned *Offset) {
> +HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(
> +    const FileEntry *File, bool IsSystem, const DirectoryEntry *Dir,
> +    bool IsExplicitlyProvided, FileID ID, unsigned *Offset) {
>    assert(File && "expected FileEntry");
>
>    // Check whether we've already loaded this module map, and mark it as
> being
> @@ -1390,14 +1390,16 @@ HeaderSearch::loadModuleMapFileImpl(cons
>    if (!AddResult.second)
>      return AddResult.first->second ? LMM_AlreadyLoaded :
> LMM_InvalidModuleMap;
>
> -  if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) {
> +  if (ModMap.parseModuleMapFile(File, IsSystem, Dir,
> IsExplicitlyProvided, ID,
> +                                Offset)) {
>      LoadedModuleMaps[File] = false;
>      return LMM_InvalidModuleMap;
>    }
>
>    // Try to load a corresponding private module map.
>    if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) {
> -    if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) {
> +    if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir,
> +                                  IsExplicitlyProvided)) {
>        LoadedModuleMaps[File] = false;
>        return LMM_InvalidModuleMap;
>      }
> @@ -1468,8 +1470,8 @@ HeaderSearch::loadModuleMapFile(const Di
>      return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
>
>    if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir,
> IsFramework)) {
> -    LoadModuleMapResult Result =
> -        loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir);
> +    LoadModuleMapResult Result = loadModuleMapFileImpl(
> +        ModuleMapFile, IsSystem, Dir, /*IsExplicitlyProvided=*/false);
>      // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
>      // E.g. Foo.framework/Modules/module.modulemap
>      //      ^Dir                  ^ModuleMapFile
>
> Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/
> ModuleMap.cpp?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
> +++ cfe/trunk/lib/Lex/ModuleMap.cpp Thu Jan  4 18:33:18 2018
> @@ -281,6 +281,8 @@ ModuleMap::ModuleMap(SourceManager &Sour
>  ModuleMap::~ModuleMap() {
>    for (auto &M : Modules)
>      delete M.getValue();
> +  for (auto *M : ShadowModules)
> +    delete M;
>  }
>
>  void ModuleMap::setTarget(const TargetInfo &Target) {
> @@ -744,14 +746,13 @@ Module *ModuleMap::lookupModuleQualified
>    return Context->findSubmodule(Name);
>  }
>
> -std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
> -                                                        Module *Parent,
> -                                                        bool IsFramework,
> -                                                        bool IsExplicit) {
> +std::pair<Module *, bool>
> +ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool
> IsFramework,
> +                              bool IsExplicit, bool
> UsesExplicitModuleMapFile) {
>    // 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, NumCreatedModules++);
> @@ -759,6 +760,8 @@ std::pair<Module *, bool> ModuleMap::fin
>      if (LangOpts.CurrentModule == Name)
>        SourceModule = Result;
>      Modules[Name] = Result;
> +    if (UsesExplicitModuleMapFile)
> +      ExplicitlyProvidedModules.insert(Result);
>    }
>    return std::make_pair(Result, true);
>  }
> @@ -999,6 +1002,20 @@ Module *ModuleMap::inferFrameworkModule(
>    return Result;
>  }
>
> +Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
> +                                        Module *ShadowingModule) {
> +
> +  // Create a new module with this name.
> +  Module *Result =
> +      new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
> +                 /*IsExplicit=*/false, NumCreatedModules++);
> +  Result->ShadowingModule = ShadowingModule;
> +  Result->IsAvailable = false;
> +  ShadowModules.push_back(Result);
> +
> +  return Result;
> +}
> +
>  void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry
> *UmbrellaHeader,
>                                    Twine NameAsWritten) {
>    Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
> @@ -1116,6 +1133,11 @@ void ModuleMap::excludeHeader(Module *Mo
>    Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
>  }
>
> +void ModuleMap::setExplicitlyProvided(Module *Mod) {
> +  assert(Modules[Mod->Name] == Mod && "explicitly provided module is
> shadowed");
> +  ExplicitlyProvidedModules.insert(Mod);
> +}
> +
>  const FileEntry *
>  ModuleMap::getContainingModuleMapFile(const Module *Module) const {
>    if (Module->DefinitionLoc.isInvalid())
> @@ -1319,7 +1341,9 @@ namespace clang {
>
>      /// \brief Consume the current token and return its location.
>      SourceLocation consumeToken();
> -
> +
> +    bool UsesExplicitModuleMapFile = false;
> +
>      /// \brief Skip tokens until we reach the a token with the given kind
>      /// (or the end of the file).
>      void skipUntil(MMToken::TokenKind K);
> @@ -1345,20 +1369,19 @@ namespace clang {
>      bool parseOptionalAttributes(Attributes &Attrs);
>
>    public:
> -    explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
> -                             const TargetInfo *Target,
> -                             DiagnosticsEngine &Diags,
> -                             ModuleMap &Map,
> -                             const FileEntry *ModuleMapFile,
> -                             const DirectoryEntry *Directory,
> -                             bool IsSystem)
> +    explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
> +                             const TargetInfo *Target, DiagnosticsEngine
> &Diags,
> +                             ModuleMap &Map, const FileEntry
> *ModuleMapFile,
> +                             const DirectoryEntry *Directory, bool
> IsSystem,
> +                             bool UsesExplicitModuleMapFile)
>          : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags),
> Map(Map),
>            ModuleMapFile(ModuleMapFile), Directory(Directory),
> -          IsSystem(IsSystem) {
> +          IsSystem(IsSystem),
> +          UsesExplicitModuleMapFile(UsesExplicitModuleMapFile) {
>        Tok.clear();
>        consumeToken();
>      }
> -
> +
>      bool parseModuleMapFile();
>
>      bool terminatedByDirective() { return false; }
> @@ -1787,6 +1810,7 @@ void ModuleMapParser::parseModuleDecl()
>    SourceLocation LBraceLoc = consumeToken();
>
>    // Determine whether this (sub)module has already been defined.
> +  Module *ShadowingModule = nullptr;
>    if (Module *Existing = Map.lookupModuleQualified(ModuleName,
> ActiveModule)) {
>      // We might see a (re)definition of a module that we already have a
>      // definition for in two cases:
> @@ -1812,23 +1836,36 @@ void ModuleMapParser::parseModuleDecl()
>        }
>        return;
>      }
> -
> -    Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
> -      << ModuleName;
> -    Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_
> definition);
> -
> -    // Skip the module definition.
> -    skipUntil(MMToken::RBrace);
> -    if (Tok.is(MMToken::RBrace))
> -      consumeToken();
> -
> -    HadError = true;
> -    return;
> +
> +    if (!Existing->Parent &&
> +        Map.mayShadowModuleBeingParsed(Existing,
> UsesExplicitModuleMapFile)) {
> +      ShadowingModule = Existing;
> +    } else {
> +      // This is not a shawdowed module decl, it is an illegal
> redefinition.
> +      Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
> +          << ModuleName;
> +      Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_
> definition);
> +
> +      // Skip the module definition.
> +      skipUntil(MMToken::RBrace);
> +      if (Tok.is(MMToken::RBrace))
> +        consumeToken();
> +
> +      HadError = true;
> +      return;
> +    }
>    }
>
>    // Start defining this module.
> -  ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule,
> Framework,
> -                                        Explicit).first;
> +  if (ShadowingModule) {
> +    ActiveModule =
> +        Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
> +  } else {
> +    ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule,
> Framework,
> +                                          Explicit,
> UsesExplicitModuleMapFile)
> +                       .first;
> +  }
> +
>    ActiveModule->DefinitionLoc = ModuleNameLoc;
>    if (Attrs.IsSystem || IsSystem)
>      ActiveModule->IsSystem = true;
> @@ -2004,7 +2041,7 @@ void ModuleMapParser::parseExternModuleD
>          Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
>              ? Directory
>              : File->getDir(),
> -        FileID(), nullptr, ExternLoc);
> +        false /*IsExplicitlyProvided*/, FileID(), nullptr, ExternLoc);
>  }
>
>  /// Whether to add the requirement \p Feature to the module \p M.
> @@ -2811,7 +2848,8 @@ bool ModuleMapParser::parseModuleMapFile
>  }
>
>  bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
> -                                   const DirectoryEntry *Dir, FileID ID,
> +                                   const DirectoryEntry *Dir,
> +                                   bool IsExplicitlyProvided, FileID ID,
>                                     unsigned *Offset,
>                                     SourceLocation ExternModuleLoc) {
>    assert(Target && "Missing target information");
> @@ -2841,7 +2879,7 @@ bool ModuleMap::parseModuleMapFile(const
>            Buffer->getBufferEnd());
>    SourceLocation Start = L.getSourceLocation();
>    ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
> -                         IsSystem);
> +                         IsSystem, IsExplicitlyProvided);
>    bool Result = Parser.parseModuleMapFile();
>    ParsedModuleMap[File] = Result;
>
> @@ -2854,5 +2892,6 @@ bool ModuleMap::parseModuleMapFile(const
>    // Notify callbacks that we parsed it.
>    for (const auto &Cb : Callbacks)
>      Cb->moduleMapFileRead(Start, *File, IsSystem);
> +
>    return Result;
>  }
>
> Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/
> PPDirectives.cpp?rev=321855&r1=321854&r2=321855&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
> +++ cfe/trunk/lib/Lex/PPDirectives.cpp Thu Jan  4 18:33:18 2018
> @@ -1655,12 +1655,18 @@ bool Preprocessor::checkModuleIsAvailabl
>                                            DiagnosticsEngine &Diags,
> Module *M) {
>    Module::Requirement Requirement;
>    Module::UnresolvedHeaderDirective MissingHeader;
> -  if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader))
> +  Module *ShadowingModule = nullptr;
> +  if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader,
> +                     ShadowingModule))
>      return false;
>
>    if (MissingHeader.FileNameLoc.isValid()) {
>      Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_
> missing)
>          << MissingHeader.IsUmbrella << MissingHeader.FileName;
> +  } else if (ShadowingModule) {
> +    Diags.Report(M->DefinitionLoc, diag::err_module_shadowed) << M->Name;
> +    Diags.Report(ShadowingModule->DefinitionLoc,
> +                 diag::note_previous_definition);
>    } else {
>      // FIXME: Track the location at which the requirement was specified,
> and
>      // use it here.
> @@ -2024,6 +2030,15 @@ void Preprocessor::HandleIncludeDirectiv
>
>    // Determine if we're switching to building a new submodule, and which
> one.
>    if (auto *M = SuggestedModule.getModule()) {
> +    if (M->getTopLevelModule()->ShadowingModule) {
> +      // We are building a submodule that belongs to a shadowed module.
> This
> +      // means we find header files in the shadowed module.
> +      Diag(M->DefinitionLoc, diag::err_module_build_shadowed_submodule)
> +        << M->getFullModuleName();
> +      Diag(M->getTopLevelModule()->ShadowingModule->DefinitionLoc,
> +           diag::note_previous_definition);
> +      return;
> +    }
>      // When building a pch, -fmodule-name tells the compiler to textually
>      // include headers in the specified module. We are not building the
>      // specified module.
>
> Added: cfe/trunk/test/Modules/Inputs/shadow/A1/A.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadow/A1/A.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadow/A1/A.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadow/A1/A.h Thu Jan  4 18:33:18 2018
> @@ -0,0 +1 @@
> +#define A1_A_h
>
> Added: cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadow/A1/module.modulemap?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap (added)
> +++ cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap Thu Jan  4
> 18:33:18 2018
> @@ -0,0 +1,5 @@
> +module A {
> +  header "A.h"
> +}
> +
> +module A1 {}
>
> Added: cfe/trunk/test/Modules/Inputs/shadow/A2/A.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadow/A2/A.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadow/A2/A.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadow/A2/A.h Thu Jan  4 18:33:18 2018
> @@ -0,0 +1 @@
> +#define A2_A_h
>
> Added: cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadow/A2/module.modulemap?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap (added)
> +++ cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap Thu Jan  4
> 18:33:18 2018
> @@ -0,0 +1,5 @@
> +module A {
> +  header "A.h"
> +}
> +
> +module A2 {}
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A1/Foo.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h Thu Jan  4
> 18:33:18 2018
> @@ -0,0 +1 @@
> +#include <stdarg.h> // expected-error {{could not build module 'A'}}
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.
> modulemap
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A1/module.modulemap?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
> (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
> Thu Jan  4 18:33:18 2018
> @@ -0,0 +1,14 @@
> +module A [system] { // expected-note {{previous definition is here}}
> +  module sub {
> +    header "sys/A.h"
> +  }
> +  module sub2 {
> +    header "sys/A2.h"
> +  }
> +  module stdarg {
> +    header "stdarg.h"
> +    export *
> +  }
> +}
> +
> +module A2 {}
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A1/sys/A.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h Thu Jan
> 4 18:33:18 2018
> @@ -0,0 +1 @@
> +#include <sys/A2.h>
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A1/sys/A2.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h Thu Jan
> 4 18:33:18 2018
> @@ -0,0 +1 @@
> +// nothing
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A2/Foo.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h Thu Jan  4
> 18:33:18 2018
> @@ -0,0 +1 @@
> +#include <stdarg.h>
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.
> modulemap
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A2/module.modulemap?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
> (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
> Thu Jan  4 18:33:18 2018
> @@ -0,0 +1,14 @@
> +module A [system] {
> +  module sub {
> +    header "sys/A.h"
> +  }
> +  module sub2 { // expected-error {{build a shadowed submodule 'A.sub2'}}
> +    header "sys/A2.h"
> +  }
> +  module stdarg {
> +    header "stdarg.h"
> +    export *
> +  }
> +}
> +
> +module A2 {}
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A2/sys/A.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h Thu Jan
> 4 18:33:18 2018
> @@ -0,0 +1 @@
> +#include <sys/A2.h>
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/A2/sys/A2.h?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h Thu Jan
> 4 18:33:18 2018
> @@ -0,0 +1 @@
> +// nothing
>
> Added: cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.
> modulemap
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/Inputs/shadowed-submodule/Foo/module.
> modulemap?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
> (added)
> +++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
> Thu Jan  4 18:33:18 2018
> @@ -0,0 +1,3 @@
> +module Foo {
> +  header "../A1/Foo.h"
> +}
>
> Added: cfe/trunk/test/Modules/shadow.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/shadow.m?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/shadow.m (added)
> +++ cfe/trunk/test/Modules/shadow.m Thu Jan  4 18:33:18 2018
> @@ -0,0 +1,21 @@
> +// RUN: rm -rf %t
> +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps
> -fmodules-cache-path=%t -I %S/Inputs/shadow/A1 -I %S/Inputs/shadow/A2 %s
> -fsyntax-only 2>&1 | FileCheck %s -check-prefix=REDEFINITION
> +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps
> -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/shadow/A1/module.modulemap
> -fmodule-map-file=%S/Inputs/shadow/A2/module.modulemap %s -fsyntax-only
> 2>&1 | FileCheck %s -check-prefix=REDEFINITION
> +// REDEFINITION: error: redefinition of module 'A'
> +// REDEFINITION: note: previously defined
> +
> +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps
> -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/shadow/A1/module.modulemap
> -I %S/Inputs/shadow %s -verify
> +
> + at import A1;
> + at import A2;
> + at import A;
> +
> +#import "A2/A.h" // expected-note {{implicitly imported}}
> +// expected-error at A2/module.modulemap:1 {{import of shadowed module 'A'}}
> +// expected-note at A1/module.modulemap:1 {{previous definition}}
> +
> +#if defined(A2_A_h)
> +#error got the wrong definition of module A
> +#elif !defined(A1_A_h)
> +#error missing definition from A1
> +#endif
>
> Added: cfe/trunk/test/Modules/shadowed-submodule.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> Modules/shadowed-submodule.m?rev=321855&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/shadowed-submodule.m (added)
> +++ cfe/trunk/test/Modules/shadowed-submodule.m Thu Jan  4 18:33:18 2018
> @@ -0,0 +1,5 @@
> +// RUN: rm -rf %t
> +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps
> -fmodules-cache-path=%t -I %S/Inputs/shadowed-submodule/Foo -I
> %S/Inputs/shadowed-submodule/A2 %s -verify
> +
> + at import Foo; // expected-error {{module 'A' was built in directory}}
> +             // expected-note at shadowed-submodule.m:4 {{imported by
> module 'Foo'}}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180108/6daa08d3/attachment-0001.html>


More information about the cfe-commits mailing list