[modules] Start moving the module visibility information off the Module itself.

It has no place there; it's not a property of the Module, and it makes
restoring the visibility set when we leave a submodule more difficult.

llvm-svn: 236300
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 5fad1a9..97f0a03 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -25,14 +25,14 @@
 using namespace clang;
 
 Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
-               bool IsFramework, bool IsExplicit)
+               bool IsFramework, bool IsExplicit, unsigned VisibilityID)
     : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
-      Umbrella(), ASTFile(nullptr), IsMissingRequirement(false),
-      IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
-      IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
-      IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
-      InferExportWildcard(false), ConfigMacrosExhaustive(false),
-      NameVisibility(Hidden) {
+      Umbrella(), ASTFile(nullptr), VisibilityID(VisibilityID),
+      IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false),
+      IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
+      IsExternC(false), IsInferred(false), InferSubmodules(false),
+      InferExplicitSubmodules(false), InferExportWildcard(false),
+      ConfigMacrosExhaustive(false), NameVisibility(Hidden) {
   if (Parent) {
     if (!Parent->isAvailable())
       IsAvailable = false;
@@ -475,4 +475,47 @@
   print(llvm::errs());
 }
 
+void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
+                                  VisibleCallback Vis, ConflictCallback Cb) {
+  if (isVisible(M))
+    return;
 
+  ++Generation;
+
+  struct Visiting {
+    Module *M;
+    Visiting *ExportedBy;
+  };
+
+  std::function<void(Visiting)> VisitModule = [&](Visiting V) {
+    // Modules that aren't available cannot be made visible.
+    if (!V.M->isAvailable())
+      return;
+
+    // Nothing to do for a module that's already visible.
+    unsigned ID = V.M->getVisibilityID();
+    if (ImportLocs.size() <= ID)
+      ImportLocs.resize(ID + 1);
+    else if (ImportLocs[ID].isValid())
+      return;
+
+    ImportLocs[ID] = Loc;
+    Vis(M);
+
+    // Make any exported modules visible.
+    SmallVector<Module *, 16> Exports;
+    V.M->getExportedModules(Exports);
+    for (Module *E : Exports)
+      VisitModule({E, &V});
+
+    for (auto &C : V.M->Conflicts) {
+      if (isVisible(C.Other)) {
+        llvm::SmallVector<Module*, 8> Path;
+        for (Visiting *I = &V; I; I = I->ExportedBy)
+          Path.push_back(I->M);
+        Cb(Path, C.Other, C.Message);
+      }
+    }
+  };
+  VisitModule({M, nullptr});
+}