This revision was automatically updated to reflect the committed changes.
Closed by commit rL321781: [Modules] Allow modules specified by 
-fmodule-map-file to shadow implicitly… (authored by bruno, committed by ).
Changed prior to commit:
  https://reviews.llvm.org/D31269?vs=92738&id=128590#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D31269

Files:
  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
  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

Index: cfe/trunk/include/clang/Lex/ModuleMap.h
===================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h
+++ cfe/trunk/include/clang/Lex/ModuleMap.h
@@ -195,6 +195,17 @@
   /// 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 +486,9 @@
   ///
   /// \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 +513,11 @@
   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 +603,8 @@
   /// \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 +624,15 @@
   /// \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.
Index: cfe/trunk/include/clang/Lex/HeaderSearch.h
===================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h
@@ -726,6 +726,7 @@
   LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
                                             bool IsSystem,
                                             const DirectoryEntry *Dir,
+                                            bool IsExplicitlyProvided,
                                             FileID ID = FileID(),
                                             unsigned *Offset = nullptr);
 
Index: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
===================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
@@ -94,6 +94,9 @@
   "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<
Index: cfe/trunk/include/clang/Basic/Module.h
===================================================================
--- cfe/trunk/include/clang/Basic/Module.h
+++ cfe/trunk/include/clang/Basic/Module.h
@@ -197,6 +197,9 @@
   /// 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 @@
   ///
   /// \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; }
Index: cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap
+++ cfe/trunk/test/Modules/Inputs/shadow/A2/module.modulemap
@@ -0,0 +1,5 @@
+module A {
+  header "A.h"
+}
+
+module A2 {}
Index: cfe/trunk/test/Modules/Inputs/shadow/A2/A.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadow/A2/A.h
+++ cfe/trunk/test/Modules/Inputs/shadow/A2/A.h
@@ -0,0 +1 @@
+#define A2_A_h
Index: cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap
+++ cfe/trunk/test/Modules/Inputs/shadow/A1/module.modulemap
@@ -0,0 +1,5 @@
+module A {
+  header "A.h"
+}
+
+module A1 {}
Index: cfe/trunk/test/Modules/Inputs/shadow/A1/A.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadow/A1/A.h
+++ cfe/trunk/test/Modules/Inputs/shadow/A1/A.h
@@ -0,0 +1 @@
+#define A1_A_h
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/Foo/module.modulemap
@@ -0,0 +1,3 @@
+module Foo {
+  header "../A1/Foo.h"
+}
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A2.h
@@ -0,0 +1 @@
+// nothing
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/sys/A.h
@@ -0,0 +1 @@
+#include <sys/A2.h>
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/Foo.h
@@ -0,0 +1 @@
+#include <stdarg.h>
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A2/module.modulemap
@@ -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 {}
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/Foo.h
@@ -0,0 +1 @@
+#include <stdarg.h> // expected-error {{could not build module 'A'}}
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/module.modulemap
@@ -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 {}
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A2.h
@@ -0,0 +1 @@
+// nothing
Index: cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
===================================================================
--- cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
+++ cfe/trunk/test/Modules/Inputs/shadowed-submodule/A1/sys/A.h
@@ -0,0 +1 @@
+#include <sys/A2.h>
Index: cfe/trunk/test/Modules/shadowed-submodule.m
===================================================================
--- cfe/trunk/test/Modules/shadowed-submodule.m
+++ cfe/trunk/test/Modules/shadowed-submodule.m
@@ -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
+
+@import Foo; // expected-error {{module 'A' was built in directory}}
+             // expected-note@shadowed-submodule.m:4 {{imported by module 'Foo'}}
Index: cfe/trunk/test/Modules/shadow.m
===================================================================
--- cfe/trunk/test/Modules/shadow.m
+++ cfe/trunk/test/Modules/shadow.m
@@ -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
+
+@import A1;
+@import A2;
+@import A;
+
+#import "A2/A.h" // expected-note {{implicitly imported}}
+// expected-error@A2/module.modulemap:1 {{import of shadowed module 'A'}}
+// expected-note@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
Index: cfe/trunk/lib/Lex/HeaderSearch.cpp
===================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp
@@ -1367,7 +1367,8 @@
     }
   }
 
-  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,26 +1379,27 @@
   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
   // loaded in case we recursively try to load it from itself.
   auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));
   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 @@
     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
Index: cfe/trunk/lib/Lex/PPDirectives.cpp
===================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp
+++ cfe/trunk/lib/Lex/PPDirectives.cpp
@@ -1655,12 +1655,18 @@
                                           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 @@
 
   // 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.
Index: cfe/trunk/lib/Lex/ModuleMap.cpp
===================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp
+++ cfe/trunk/lib/Lex/ModuleMap.cpp
@@ -744,21 +744,22 @@
   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++);
   if (!Parent) {
     if (LangOpts.CurrentModule == Name)
       SourceModule = Result;
     Modules[Name] = Result;
+    if (UsesExplicitModuleMapFile)
+      ExplicitlyProvidedModules.insert(Result);
   }
   return std::make_pair(Result, true);
 }
@@ -999,6 +1000,19 @@
   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;
+
+  return Result;
+}
+
 void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
                                   Twine NameAsWritten) {
   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
@@ -1116,6 +1130,11 @@
   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 +1338,9 @@
 
     /// \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 +1366,19 @@
     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 +1807,7 @@
   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 +1833,36 @@
       }
       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 +2038,7 @@
         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 +2845,8 @@
 }
 
 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 +2876,7 @@
           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 +2889,6 @@
   // Notify callbacks that we parsed it.
   for (const auto &Cb : Callbacks)
     Cb->moduleMapFileRead(Start, *File, IsSystem);
+
   return Result;
 }
Index: cfe/trunk/lib/Basic/Module.cpp
===================================================================
--- cfe/trunk/lib/Basic/Module.cpp
+++ cfe/trunk/lib/Basic/Module.cpp
@@ -95,11 +95,16 @@
 
 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) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D31269: [Modul... Bruno Cardoso Lopes via Phabricator via cfe-commits
    • [PATCH] D31269: [... Bruno Cardoso Lopes via Phabricator via cfe-commits

Reply via email to