Implement name hiding for declarations deserialized from a non-visible
module. When that module becomes visible, so do those declarations.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145640 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 258baeb..a083e24 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2439,6 +2439,11 @@
   return Success;
 }
 
+void ASTReader::makeNamesVisible(const HiddenNames &Names) {
+  for (unsigned I = 0, N = Names.size(); I != N; ++I)
+    Names[I]->ModulePrivate = false;    
+}
+
 void ASTReader::makeModuleVisible(Module *Mod, 
                                   Module::NameVisibilityKind NameVisibility) {
   llvm::SmallPtrSet<Module *, 4> Visited;
@@ -2457,8 +2462,13 @@
     // Update the module's name visibility.
     Mod->NameVisibility = NameVisibility;
     
-    // FIXME: If we've already deserialized any names from this module,
+    // If we've already deserialized any names from this module,
     // mark them as visible.
+    HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
+    if (Hidden != HiddenNamesMap.end()) {
+      makeNamesVisible(Hidden->second);
+      HiddenNamesMap.erase(Hidden);
+    }
     
     // Push any non-explicit submodules onto the stack to be marked as
     // visible.
@@ -2776,6 +2786,15 @@
   }
 }
 
+void ASTReader::finalizeForWriting() {
+  for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(),
+                                 HiddenEnd = HiddenNamesMap.end();
+       Hidden != HiddenEnd; ++Hidden) {
+    makeNamesVisible(Hidden->second);
+  }
+  HiddenNamesMap.clear();
+}
+
 /// \brief Retrieve the name of the original source file name
 /// directly from the AST file, without actually loading the AST
 /// file.
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 397671f..85cd728 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -86,6 +86,14 @@
       Reader.ReadDeclarationNameInfo(F, NameInfo, R, I);
     }
 
+    serialization::SubmoduleID readSubmoduleID(const RecordData &R, 
+                                               unsigned &I) {
+      if (I >= R.size())
+        return 0;
+      
+      return Reader.getGlobalSubmoduleID(F, R[I++]);
+    }
+    
     void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
                                const RecordData &R, unsigned &I);
 
@@ -253,10 +261,25 @@
   D->setAccess((AccessSpecifier)Record[Idx++]);
   D->FromASTFile = true;
   D->ModulePrivate = Record[Idx++];
-  
-  unsigned SubmoduleID = Record[Idx++];
-  // FIXME: Actual use the submodule ID to determine visibility.
-  (void)SubmoduleID;
+
+  // Determine whether this declaration is part of a (sub)module. If so, it
+  // may not yet be visible.
+  if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
+    // Module-private declarations are never visible, so there is no work to do.
+    if (!D->ModulePrivate) {
+      if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
+        if (Owner->NameVisibility != Module::AllVisible) {
+          // The owning module is not visible. Mark this declaration as
+          // module-private, 
+          D->ModulePrivate = true;
+          
+          // Note that this declaration was hidden because its owning module is 
+          // not yet visible.
+          Reader.HiddenNamesMap[Owner].push_back(D);
+        }
+      }
+    }
+  }
 }
 
 void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index e37aa73..1b554ef 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -2958,6 +2958,10 @@
                              Module *WritingModule) {
   using namespace llvm;
 
+  // Make sure that the AST reader knows to finalize itself.
+  if (Chain)
+    Chain->finalizeForWriting();
+  
   ASTContext &Context = SemaRef.Context;
   Preprocessor &PP = SemaRef.PP;