<div dir="rtl"><div dir="ltr">Thanks!</div><div dir="ltr"><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div dir="ltr">2015-09-01 16:24 GMT+03:00 Aaron Ballman via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span>:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: aaronballman<br>
Date: Tue Sep  1 08:24:39 2015<br>
New Revision: 246546<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=246546&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=246546&view=rev</a><br>
Log:<br>
Reverting r246497 (which requires also reverting r246524 and r246521 to avoid merge conflicts). It broke the build on MSVC 2015. It also broke an MSVC 2013 bot with testing issues.<br>
<br>
llvm\tools\clang\lib\serialization\MultiOnDiskHashTable.h(117):<br>
error C2065: 'Files': undeclared identifier<br>
<br>
<a href="http://bb.pgr.jp/builders/ninja-clang-i686-msc18-R/builds/2917" rel="noreferrer" target="_blank">http://bb.pgr.jp/builders/ninja-clang-i686-msc18-R/builds/2917</a><br>
<br>
Removed:<br>
    cfe/trunk/lib/Serialization/MultiOnDiskHashTable.h<br>
Modified:<br>
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
    cfe/trunk/include/clang/Serialization/ASTReader.h<br>
    cfe/trunk/include/clang/Serialization/ASTWriter.h<br>
    cfe/trunk/include/clang/Serialization/Module.h<br>
    cfe/trunk/lib/Serialization/ASTReader.cpp<br>
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
    cfe/trunk/lib/Serialization/ASTReaderInternals.h<br>
    cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp<br>
    cfe/trunk/lib/Serialization/Module.cpp<br>
    cfe/trunk/test/Modules/cxx-templates.cpp<br>
    cfe/trunk/test/Modules/merge-using-decls.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Sep  1 08:24:39 2015<br>
@@ -1530,23 +1530,4 @@ namespace clang {<br>
   }<br>
 } // end namespace clang<br>
<br>
-namespace llvm {<br>
-  template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {<br>
-    static clang::serialization::DeclarationNameKey getEmptyKey() {<br>
-      return clang::serialization::DeclarationNameKey(-1, 1);<br>
-    }<br>
-    static clang::serialization::DeclarationNameKey getTombstoneKey() {<br>
-      return clang::serialization::DeclarationNameKey(-1, 2);<br>
-    }<br>
-    static unsigned<br>
-    getHashValue(const clang::serialization::DeclarationNameKey &Key) {<br>
-      return Key.getHash();<br>
-    }<br>
-    static bool isEqual(const clang::serialization::DeclarationNameKey &L,<br>
-                        const clang::serialization::DeclarationNameKey &R) {<br>
-      return L == R;<br>
-    }<br>
-  };<br>
-}<br>
-<br>
 #endif<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Sep  1 08:24:39 2015<br>
@@ -282,8 +282,9 @@ class ReadMethodPoolVisitor;<br>
<br>
 namespace reader {<br>
   class ASTIdentifierLookupTrait;<br>
-  /// \brief The on-disk hash table(s) used for DeclContext name lookup.<br>
-  struct DeclContextLookupTable;<br>
+  /// \brief The on-disk hash table used for the DeclContext's Name lookup table.<br>
+  typedef llvm::OnDiskIterableChainedHashTable<ASTDeclContextNameLookupTrait><br>
+    ASTDeclContextNameLookupTable;<br>
 }<br>
<br>
 } // end namespace serialization<br>
@@ -506,10 +507,6 @@ private:<br>
   /// \brief Map from the TU to its lexical contents from each module file.<br>
   std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;<br>
<br>
-  /// \brief Map from a DeclContext to its lookup tables.<br>
-  llvm::DenseMap<const DeclContext *,<br>
-                 serialization::reader::DeclContextLookupTable> Lookups;<br>
-<br>
   // Updates for visible decls can occur for other contexts than just the<br>
   // TU, and when we read those update records, the actual context may not<br>
   // be available yet, so have this pending map using the ID as a key. It<br>
@@ -517,6 +514,7 @@ private:<br>
   struct PendingVisibleUpdate {<br>
     ModuleFile *Mod;<br>
     const unsigned char *Data;<br>
+    unsigned BucketOffset;<br>
   };<br>
   typedef SmallVector<PendingVisibleUpdate, 1> DeclContextVisibleUpdates;<br>
<br>
@@ -1091,10 +1089,6 @@ public:<br>
         Visit(GetExistingDecl(ID));<br>
   }<br>
<br>
-  /// \brief Get the loaded lookup tables for \p Primary, if any.<br>
-  const serialization::reader::DeclContextLookupTable *<br>
-  getLoadedLookupTables(DeclContext *Primary) const;<br>
-<br>
 private:<br>
   struct ImportedModule {<br>
     ModuleFile *Mod;<br>
@@ -1876,13 +1870,6 @@ public:<br>
   /// Note: overrides method in ExternalASTSource<br>
   Module *getModule(unsigned ID) override;<br>
<br>
-  /// \brief Retrieve the module file with a given local ID within the specified<br>
-  /// ModuleFile.<br>
-  ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID);<br>
-<br>
-  /// \brief Get an ID for the given module file.<br>
-  unsigned getModuleFileID(ModuleFile *M);<br>
-<br>
   /// \brief Return a descriptor for the corresponding module.<br>
   llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;<br>
   /// \brief Return a descriptor for the module.<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Tue Sep  1 08:24:39 2015<br>
@@ -529,8 +529,8 @@ private:<br>
   bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);<br>
   bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC);<br>
<br>
-  void GenerateNameLookupTable(const DeclContext *DC,<br>
-                               llvm::SmallVectorImpl<char> &LookupTable);<br>
+  uint32_t GenerateNameLookupTable(const DeclContext *DC,<br>
+                                   llvm::SmallVectorImpl<char> &LookupTable);<br>
   uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);<br>
   uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);<br>
   void WriteTypeDeclOffsets();<br>
@@ -849,7 +849,6 @@ public:<br>
   unsigned getExprImplicitCastAbbrev() const { return ExprImplicitCastAbbrev; }<br>
<br>
   bool hasChain() const { return Chain; }<br>
-  ASTReader *getChain() const { return Chain; }<br>
<br>
   // ASTDeserializationListener implementation<br>
   void ReaderInitialized(ASTReader *Reader) override;<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/Module.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/Module.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/Module.h Tue Sep  1 08:24:39 2015<br>
@@ -50,6 +50,14 @@ enum ModuleKind {<br>
   MK_MainFile        ///< File is a PCH file treated as the actual main file.<br>
 };<br>
<br>
+/// \brief Information about the contents of a DeclContext.<br>
+struct DeclContextInfo {<br>
+  DeclContextInfo() : NameLookupTableData() {}<br>
+<br>
+  llvm::OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait><br>
+    *NameLookupTableData; // an ASTDeclContextNameLookupTable.<br>
+};<br>
+<br>
 /// \brief The input file that has been loaded from this AST file, along with<br>
 /// bools indicating whether this was an overridden buffer or if it was<br>
 /// out-of-date or not-found.<br>
@@ -408,6 +416,13 @@ public:<br>
   /// indexed by the C++ ctor initializer list ID minus 1.<br>
   const uint32_t *CXXCtorInitializersOffsets;<br>
<br>
+  typedef llvm::DenseMap<const DeclContext *, DeclContextInfo><br>
+  DeclContextInfosMap;<br>
+<br>
+  /// \brief Information about the lexical and visible declarations<br>
+  /// for each DeclContext.<br>
+  DeclContextInfosMap DeclContextInfos;<br>
+<br>
   /// \brief Array of file-level DeclIDs sorted by file.<br>
   const serialization::DeclID *FileSortedDecls;<br>
   unsigned NumFileSortedDecls;<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Sep  1 08:24:39 2015<br>
@@ -20,7 +20,6 @@<br>
 #include "clang/AST/Expr.h"<br>
 #include "clang/AST/ExprCXX.h"<br>
 #include "clang/Frontend/PCHContainerOperations.h"<br>
-#include "clang/AST/ASTMutationListener.h"<br>
 #include "clang/AST/NestedNameSpecifier.h"<br>
 #include "clang/AST/Type.h"<br>
 #include "clang/AST/TypeLocVisitor.h"<br>
@@ -904,13 +903,6 @@ unsigned DeclarationNameKey::getHash() c<br>
   return ID.ComputeHash();<br>
 }<br>
<br>
-ModuleFile *<br>
-ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) {<br>
-  using namespace llvm::support;<br>
-  uint32_t ModuleFileID = endian::readNext<uint32_t, little, unaligned>(d);<br>
-  return Reader.getLocalModuleFile(F, ModuleFileID);<br>
-}<br>
-<br>
 std::pair<unsigned, unsigned><br>
 ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char *&d) {<br>
   using namespace llvm::support;<br>
@@ -956,15 +948,15 @@ ASTDeclContextNameLookupTrait::ReadKey(c<br>
   return DeclarationNameKey(Kind, Data);<br>
 }<br>
<br>
-void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type,<br>
-                                                 const unsigned char *d,<br>
-                                                 unsigned DataLen,<br>
-                                                 data_type_builder &Val) {<br>
+ASTDeclContextNameLookupTrait::data_type<br>
+ASTDeclContextNameLookupTrait::ReadData(internal_key_type,<br>
+                                        const unsigned char *d,<br>
+                                        unsigned DataLen) {<br>
   using namespace llvm::support;<br>
-  for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) {<br>
-    uint32_t LocalID = endian::readNext<uint32_t, little, unaligned>(d);<br>
-    Val.insert(Reader.getGlobalDeclID(F, LocalID));<br>
-  }<br>
+  unsigned NumDecls = DataLen / 4;<br>
+  LE32DeclID *Start = reinterpret_cast<LE32DeclID *>(<br>
+                        const_cast<unsigned char *>(d));<br>
+  return std::make_pair(Start, Start + NumDecls);<br>
 }<br>
<br>
 bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,<br>
@@ -1023,8 +1015,9 @@ bool ASTReader::ReadVisibleDeclContextSt<br>
<br>
   // We can't safely determine the primary context yet, so delay attaching the<br>
   // lookup table until we're done with recursive deserialization.<br>
-  auto *Data = (const unsigned char*)Blob.data();<br>
-  PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&M, Data});<br>
+  unsigned BucketOffset = Record[0];<br>
+  PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{<br>
+      &M, (const unsigned char *)Blob.data(), BucketOffset});<br>
   return false;<br>
 }<br>
<br>
@@ -2559,7 +2552,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, u<br>
       unsigned Idx = 0;<br>
       serialization::DeclID ID = ReadDeclID(F, Record, Idx);<br>
       auto *Data = (const unsigned char*)Blob.data();<br>
-      PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&F, Data});<br>
+      unsigned BucketOffset = Record[Idx++];<br>
+      PendingVisibleUpdates[ID].push_back(<br>
+          PendingVisibleUpdate{&F, Data, BucketOffset});<br>
       // If we've already loaded the decl, perform the updates when we finish<br>
       // loading this block.<br>
       if (Decl *D = GetExistingDecl(ID))<br>
@@ -6360,48 +6355,196 @@ void ASTReader::FindFileRegionDecls(File<br>
     Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));<br>
 }<br>
<br>
+/// \brief Retrieve the "definitive" module file for the definition of the<br>
+/// given declaration context, if there is one.<br>
+///<br>
+/// The "definitive" module file is the only place where we need to look to<br>
+/// find information about the declarations within the given declaration<br>
+/// context. For example, C++ and Objective-C classes, C structs/unions, and<br>
+/// Objective-C protocols, categories, and extensions are all defined in a<br>
+/// single place in the source code, so they have definitive module files<br>
+/// associated with them. C++ namespaces, on the other hand, can have<br>
+/// definitions in multiple different module files.<br>
+///<br>
+/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's<br>
+/// NDEBUG checking.<br>
+static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,<br>
+                                              ASTReader &Reader) {<br>
+  if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))<br>
+    return Reader.getOwningModuleFile(cast<Decl>(DefDC));<br>
+<br>
+  return nullptr;<br>
+}<br>
+<br>
+namespace {<br>
+  /// \brief ModuleFile visitor used to perform name lookup into a<br>
+  /// declaration context.<br>
+  class DeclContextNameLookupVisitor {<br>
+    ASTReader &Reader;<br>
+    const DeclContext *Context;<br>
+    DeclarationName Name;<br>
+    DeclarationNameKey NameKey;<br>
+    unsigned NameHash;<br>
+    SmallVectorImpl<NamedDecl *> &Decls;<br>
+    llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet;<br>
+<br>
+  public:<br>
+    DeclContextNameLookupVisitor(ASTReader &Reader, const DeclContext *Context,<br>
+                                 DeclarationName Name,<br>
+                                 SmallVectorImpl<NamedDecl *> &Decls,<br>
+                                 llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet)<br>
+        : Reader(Reader), Context(Context), Name(Name), NameKey(Name),<br>
+          NameHash(NameKey.getHash()), Decls(Decls), DeclSet(DeclSet) {}<br>
+<br>
+    bool operator()(ModuleFile &M) {<br>
+      // Check whether we have any visible declaration information for<br>
+      // this context in this module.<br>
+      auto Info = M.DeclContextInfos.find(Context);<br>
+      if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData)<br>
+        return false;<br>
+<br>
+      // Look for this name within this module.<br>
+      ASTDeclContextNameLookupTable *LookupTable =<br>
+          Info->second.NameLookupTableData;<br>
+      ASTDeclContextNameLookupTable::iterator Pos =<br>
+          LookupTable->find_hashed(NameKey, NameHash);<br>
+      if (Pos == LookupTable->end())<br>
+        return false;<br>
+<br>
+      bool FoundAnything = false;<br>
+      ASTDeclContextNameLookupTrait::data_type Data = *Pos;<br>
+      for (; Data.first != Data.second; ++Data.first) {<br>
+        NamedDecl *ND = Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);<br>
+        if (!ND)<br>
+          continue;<br>
+<br>
+        if (ND->getDeclName() != Name) {<br>
+          // Not all names map to a unique DeclarationNameKey.<br>
+          assert(DeclarationNameKey(ND->getDeclName()) == NameKey &&<br>
+                 "mismatched name for decl in decl context lookup table?");<br>
+          continue;<br>
+        }<br>
+<br>
+        // Record this declaration.<br>
+        FoundAnything = true;<br>
+        if (DeclSet.insert(ND).second)<br>
+          Decls.push_back(ND);<br>
+      }<br>
+<br>
+      return FoundAnything;<br>
+    }<br>
+  };<br>
+}<br>
+<br>
 bool<br>
 ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,<br>
                                           DeclarationName Name) {<br>
-  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&<br>
+  assert(DC->hasExternalVisibleStorage() &&<br>
          "DeclContext has no visible decls in storage");<br>
   if (!Name)<br>
     return false;<br>
<br>
-  auto It = Lookups.find(DC);<br>
-  if (It == Lookups.end())<br>
-    return false;<br>
-<br>
   Deserializing LookupResults(this);<br>
<br>
-  // Load the list of declarations.<br>
   SmallVector<NamedDecl *, 64> Decls;<br>
-  for (DeclID ID : It->second.Table.find(Name)) {<br>
-    NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));<br>
-    if (ND->getDeclName() == Name)<br>
-      Decls.push_back(ND);<br>
-  }<br>
+  llvm::SmallPtrSet<NamedDecl*, 64> DeclSet;<br>
+<br>
+  DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls, DeclSet);<br>
+<br>
+  // If we can definitively determine which module file to look into,<br>
+  // only look there. Otherwise, look in all module files.<br>
+  if (ModuleFile *Definitive = getDefinitiveModuleFileFor(DC, *this))<br>
+    Visitor(*Definitive);<br>
+  else<br>
+    ModuleMgr.visit(Visitor);<br>
<br>
   ++NumVisibleDeclContextsRead;<br>
   SetExternalVisibleDeclsForName(DC, Name, Decls);<br>
   return !Decls.empty();<br>
 }<br>
<br>
+namespace {<br>
+  /// \brief ModuleFile visitor used to retrieve all visible names in a<br>
+  /// declaration context.<br>
+  class DeclContextAllNamesVisitor {<br>
+    ASTReader &Reader;<br>
+    SmallVectorImpl<const DeclContext *> &Contexts;<br>
+    DeclsMap &Decls;<br>
+    llvm::SmallPtrSet<NamedDecl *, 256> DeclSet;<br>
+    bool VisitAll;<br>
+<br>
+  public:<br>
+    DeclContextAllNamesVisitor(ASTReader &Reader,<br>
+                               SmallVectorImpl<const DeclContext *> &Contexts,<br>
+                               DeclsMap &Decls, bool VisitAll)<br>
+      : Reader(Reader), Contexts(Contexts), Decls(Decls), VisitAll(VisitAll) { }<br>
+<br>
+    bool operator()(ModuleFile &M) {<br>
+      // Check whether we have any visible declaration information for<br>
+      // this context in this module.<br>
+      ModuleFile::DeclContextInfosMap::iterator Info;<br>
+      bool FoundInfo = false;<br>
+      for (unsigned I = 0, N = Contexts.size(); I != N; ++I) {<br>
+        Info = M.DeclContextInfos.find(Contexts[I]);<br>
+        if (Info != M.DeclContextInfos.end() &&<br>
+            Info->second.NameLookupTableData) {<br>
+          FoundInfo = true;<br>
+          break;<br>
+        }<br>
+      }<br>
+<br>
+      if (!FoundInfo)<br>
+        return false;<br>
+<br>
+      ASTDeclContextNameLookupTable *LookupTable =<br>
+        Info->second.NameLookupTableData;<br>
+      bool FoundAnything = false;<br>
+      for (ASTDeclContextNameLookupTable::data_iterator<br>
+             I = LookupTable->data_begin(), E = LookupTable->data_end();<br>
+           I != E;<br>
+           ++I) {<br>
+        ASTDeclContextNameLookupTrait::data_type Data = *I;<br>
+        for (; Data.first != Data.second; ++Data.first) {<br>
+          NamedDecl *ND = Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);<br>
+          if (!ND)<br>
+            continue;<br>
+<br>
+          // Record this declaration.<br>
+          FoundAnything = true;<br>
+          if (DeclSet.insert(ND).second)<br>
+            Decls[ND->getDeclName()].push_back(ND);<br>
+        }<br>
+      }<br>
+<br>
+      return FoundAnything && !VisitAll;<br>
+    }<br>
+  };<br>
+}<br>
+<br>
 void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {<br>
   if (!DC->hasExternalVisibleStorage())<br>
     return;<br>
-<br>
-  auto It = Lookups.find(DC);<br>
-  assert(It != Lookups.end() &&<br>
-         "have external visible storage but no lookup tables");<br>
-<br>
   DeclsMap Decls;<br>
<br>
-  for (DeclID ID : It->second.Table.findAll()) {<br>
-    NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));<br>
-    Decls[ND->getDeclName()].push_back(ND);<br>
+  // Compute the declaration contexts we need to look into. Multiple such<br>
+  // declaration contexts occur when two declaration contexts from disjoint<br>
+  // modules get merged, e.g., when two namespaces with the same name are<br>
+  // independently defined in separate modules.<br>
+  SmallVector<const DeclContext *, 2> Contexts;<br>
+  Contexts.push_back(DC);<br>
+<br>
+  if (DC->isNamespace()) {<br>
+    KeyDeclsMap::iterator Key =<br>
+        KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));<br>
+    if (Key != KeyDecls.end()) {<br>
+      for (unsigned I = 0, N = Key->second.size(); I != N; ++I)<br>
+        Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));<br>
+    }<br>
   }<br>
<br>
+  DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls,<br>
+                                     /*VisitAll=*/DC->isFileContext());<br>
+  ModuleMgr.visit(Visitor);<br>
   ++NumVisibleDeclContextsRead;<br>
<br>
   for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {<br>
@@ -6410,12 +6553,6 @@ void ASTReader::completeVisibleDeclsMap(<br>
   const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);<br>
 }<br>
<br>
-const serialization::reader::DeclContextLookupTable *<br>
-ASTReader::getLoadedLookupTables(DeclContext *Primary) const {<br>
-  auto I = Lookups.find(Primary);<br>
-  return I == Lookups.end() ? nullptr : &I->second;<br>
-}<br>
-<br>
 /// \brief Under non-PCH compilation the consumer receives the objc methods<br>
 /// before receiving the implementation, and codegen depends on this.<br>
 /// We simulate this by deserializing and passing to consumer the methods of the<br>
@@ -7247,36 +7384,6 @@ Module *ASTReader::getModule(unsigned ID<br>
   return getSubmodule(ID);<br>
 }<br>
<br>
-ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) {<br>
-  if (ID & 1) {<br>
-    // It's a module, look it up by submodule ID.<br>
-    auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(F, ID >> 1));<br>
-    return I == GlobalSubmoduleMap.end() ? nullptr : I->second;<br>
-  } else {<br>
-    // It's a prefix (preamble, PCH, ...). Look it up by index.<br>
-    unsigned IndexFromEnd = ID >> 1;<br>
-    assert(IndexFromEnd && "got reference to unknown module file");<br>
-    return getModuleManager().pch_modules().end()[-IndexFromEnd];<br>
-  }<br>
-}<br>
-<br>
-unsigned ASTReader::getModuleFileID(ModuleFile *F) {<br>
-  if (!F)<br>
-    return 1;<br>
-<br>
-  // For a file representing a module, use the submodule ID of the top-level<br>
-  // module as the file ID. For any other kind of file, the number of such<br>
-  // files loaded beforehand will be the same on reload.<br>
-  // FIXME: Is this true even if we have an explicit module file and a PCH?<br>
-  if (F->isModule())<br>
-    return ((F->BaseSubmoduleID + NUM_PREDEF_SUBMODULE_IDS) << 1) | 1;<br>
-<br>
-  auto PCHModules = getModuleManager().pch_modules();<br>
-  auto I = std::find(PCHModules.begin(), PCHModules.end(), F);<br>
-  assert(I != PCHModules.end() && "emitting reference to unknown file");<br>
-  return (I - PCHModules.end()) << 1;<br>
-}<br>
-<br>
 ExternalASTSource::ASTSourceDescriptor<br>
 ASTReader::getSourceDescriptor(const Module &M) {<br>
   StringRef Dir, Filename;<br>
@@ -8325,8 +8432,6 @@ void ASTReader::FinishedDeserializing()<br>
       for (auto Update : Updates) {<br>
         auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();<br>
         auto ESI = FPT->getExtProtoInfo().ExceptionSpec;<br>
-        if (auto *Listener = Context.getASTMutationListener())<br>
-          Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second));<br>
         for (auto *Redecl : Update.second->redecls())<br>
           Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);<br>
       }<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Sep  1 08:24:39 2015<br>
@@ -1489,8 +1489,6 @@ void ASTDeclReader::MergeDefinitionData(<br>
     Reader.PendingDefinitions.erase(MergeDD.Definition);<br>
     MergeDD.Definition->IsCompleteDefinition = false;<br>
     mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);<br>
-    assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&<br>
-           "already loaded pending lookups for merged definition");<br>
   }<br>
<br>
   auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);<br>
@@ -3348,10 +3346,15 @@ void ASTReader::loadDeclUpdateRecords(se<br>
     PendingVisibleUpdates.erase(I);<br>
<br>
     auto *DC = cast<DeclContext>(D)->getPrimaryContext();<br>
-    for (const PendingVisibleUpdate &Update : VisibleUpdates)<br>
-      Lookups[DC].Table.add(<br>
-          Update.Mod, Update.Data,<br>
+    for (const PendingVisibleUpdate &Update : VisibleUpdates) {<br>
+      auto *&LookupTable = Update.Mod->DeclContextInfos[DC].NameLookupTableData;<br>
+      assert(!LookupTable && "multiple lookup tables for DC in module");<br>
+      LookupTable = reader::ASTDeclContextNameLookupTable::Create(<br>
+          Update.Data + Update.BucketOffset,<br>
+          Update.Data + sizeof(uint32_t),<br>
+          Update.Data,<br>
           reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod));<br>
+    }<br>
     DC->setHasExternalVisibleStorage(true);<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReaderInternals.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderInternals.h?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderInternals.h?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReaderInternals.h (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReaderInternals.h Tue Sep  1 08:24:39 2015<br>
@@ -15,12 +15,8 @@<br>
<br>
 #include "clang/AST/DeclarationName.h"<br>
 #include "clang/Serialization/ASTBitCodes.h"<br>
-#include "llvm/ADT/DenseSet.h"<br>
-#include "llvm/ADT/PointerUnion.h"<br>
-#include "llvm/ADT/TinyPtrVector.h"<br>
 #include "llvm/Support/Endian.h"<br>
 #include "llvm/Support/OnDiskHashTable.h"<br>
-#include "MultiOnDiskHashTable.h"<br>
 #include <utility><br>
<br>
 namespace clang {<br>
@@ -43,38 +39,14 @@ class ASTDeclContextNameLookupTrait {<br>
   ModuleFile &F;<br>
<br>
 public:<br>
-  // Maximum number of lookup tables we allow before condensing the tables.<br>
-  static const int MaxTables = 4;<br>
-<br>
-  /// The lookup result is a list of global declaration IDs.<br>
-  typedef llvm::SmallVector<DeclID, 4> data_type;<br>
-  struct data_type_builder {<br>
-    data_type &Data;<br>
-    llvm::DenseSet<DeclID> Found;<br>
-<br>
-    data_type_builder(data_type &D) : Data(D) {}<br>
-    void insert(DeclID ID) {<br>
-      // Just use a linear scan unless we have more than a few IDs.<br>
-      if (Found.empty() && !Data.empty()) {<br>
-        if (Data.size() <= 4) {<br>
-          for (auto I : Found)<br>
-            if (I == ID)<br>
-              return;<br>
-          Data.push_back(ID);<br>
-          return;<br>
-        }<br>
-<br>
-        // Switch to tracking found IDs in the set.<br>
-        Found.insert(Data.begin(), Data.end());<br>
-      }<br>
-<br>
-      if (Found.insert(ID).second)<br>
-        Data.push_back(ID);<br>
-    }<br>
-  };<br>
+  /// \brief Pair of begin/end iterators for DeclIDs.<br>
+  ///<br>
+  /// Note that these declaration IDs are local to the module that contains this<br>
+  /// particular lookup t<br>
+  typedef llvm::support::ulittle32_t LE32DeclID;<br>
+  typedef std::pair<LE32DeclID *, LE32DeclID *> data_type;<br>
   typedef unsigned hash_value_type;<br>
   typedef unsigned offset_type;<br>
-  typedef ModuleFile *file_type;<br>
<br>
   typedef DeclarationName external_key_type;<br>
   typedef DeclarationNameKey internal_key_type;<br>
@@ -82,7 +54,8 @@ public:<br>
   explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F)<br>
     : Reader(Reader), F(F) { }<br>
<br>
-  static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {<br>
+  static bool EqualKey(const internal_key_type& a,<br>
+                       const internal_key_type& b) {<br>
     return a == b;<br>
   }<br>
<br>
@@ -98,20 +71,8 @@ public:<br>
<br>
   internal_key_type ReadKey(const unsigned char *d, unsigned);<br>
<br>
-  void ReadDataInto(internal_key_type, const unsigned char *d,<br>
-                    unsigned DataLen, data_type_builder &Val);<br>
-<br>
-  static void MergeDataInto(const data_type &From, data_type_builder &To) {<br>
-    To.Data.reserve(To.Data.size() + From.size());<br>
-    for (DeclID ID : From)<br>
-      To.insert(ID);<br>
-  }<br>
-<br>
-  file_type ReadFileRef(const unsigned char *&d);<br>
-};<br>
-<br>
-struct DeclContextLookupTable {<br>
-  MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table;<br>
+  data_type ReadData(internal_key_type, const unsigned char *d,<br>
+                     unsigned DataLen);<br>
 };<br>
<br>
 /// \brief Base class for the trait describing the on-disk hash table for the<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Sep  1 08:24:39 2015<br>
@@ -13,8 +13,6 @@<br>
<br>
 #include "clang/Serialization/ASTWriter.h"<br>
 #include "ASTCommon.h"<br>
-#include "ASTReaderInternals.h"<br>
-#include "MultiOnDiskHashTable.h"<br>
 #include "clang/AST/ASTContext.h"<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/DeclContextInternals.h"<br>
@@ -3379,14 +3377,12 @@ namespace {<br>
 // Trait used for the on-disk hash table used in the method pool.<br>
 class ASTDeclContextNameLookupTrait {<br>
   ASTWriter &Writer;<br>
-  llvm::SmallVector<DeclID, 64> DeclIDs;<br>
<br>
 public:<br>
   typedef DeclarationNameKey key_type;<br>
   typedef key_type key_type_ref;<br>
<br>
-  /// A start and end index into DeclIDs, representing a sequence of decls.<br>
-  typedef std::pair<unsigned, unsigned> data_type;<br>
+  typedef DeclContext::lookup_result data_type;<br>
   typedef const data_type& data_type_ref;<br>
<br>
   typedef unsigned hash_value_type;<br>
@@ -3394,40 +3390,10 @@ public:<br>
<br>
   explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }<br>
<br>
-  template<typename Coll><br>
-  data_type getData(const Coll &Decls) {<br>
-    unsigned Start = DeclIDs.size();<br>
-    for (NamedDecl *D : Decls) {<br>
-      DeclIDs.push_back(<br>
-          Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D)));<br>
-    }<br>
-    return std::make_pair(Start, DeclIDs.size());<br>
-  }<br>
-<br>
-  data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {<br>
-    unsigned Start = DeclIDs.size();<br>
-    for (auto ID : FromReader)<br>
-      DeclIDs.push_back(ID);<br>
-    return std::make_pair(Start, DeclIDs.size());<br>
-  }<br>
-<br>
-  static bool EqualKey(key_type_ref a, key_type_ref b) {<br>
-    return a == b;<br>
-  }<br>
-<br>
   hash_value_type ComputeHash(DeclarationNameKey Name) {<br>
     return Name.getHash();<br>
   }<br>
<br>
-  void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {<br>
-    assert(Writer.hasChain() &&<br>
-           "have reference to loaded module file but no chain?");<br>
-<br>
-    using namespace llvm::support;<br>
-    endian::Writer<little>(Out)<br>
-        .write<uint32_t>(Writer.getChain()->getModuleFileID(F));<br>
-  }<br>
-<br>
   std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,<br>
                                                   DeclarationNameKey Name,<br>
                                                   data_type_ref Lookup) {<br>
@@ -3454,9 +3420,7 @@ public:<br>
     LE.write<uint16_t>(KeyLen);<br>
<br>
     // 4 bytes for each DeclID.<br>
-    unsigned DataLen = 4 * (Lookup.second - Lookup.first);<br>
-    assert(uint16_t(DataLen) == DataLen &&<br>
-           "too many decls for serialized lookup result");<br>
+    unsigned DataLen = 4 * Lookup.size();<br>
     LE.write<uint16_t>(DataLen);<br>
<br>
     return std::make_pair(KeyLen, DataLen);<br>
@@ -3496,8 +3460,11 @@ public:<br>
     using namespace llvm::support;<br>
     endian::Writer<little> LE(Out);<br>
     uint64_t Start = Out.tell(); (void)Start;<br>
-    for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)<br>
-      LE.write<uint32_t>(DeclIDs[I]);<br>
+    for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end();<br>
+         I != E; ++I)<br>
+      LE.write<uint32_t>(<br>
+          Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), *I)));<br>
+<br>
     assert(Out.tell() - Start == DataLen && "Data length is wrong");<br>
   }<br>
 };<br>
@@ -3517,7 +3484,7 @@ bool ASTWriter::isLookupResultEntirelyEx<br>
   return true;<br>
 }<br>
<br>
-void<br>
+uint32_t<br>
 ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,<br>
                                    llvm::SmallVectorImpl<char> &LookupTable) {<br>
   assert(!ConstDC->HasLazyLocalLexicalLookups &&<br>
@@ -3529,8 +3496,8 @@ ASTWriter::GenerateNameLookupTable(const<br>
   assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");<br>
<br>
   // Create the on-disk hash table representation.<br>
-  MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,<br>
-                                ASTDeclContextNameLookupTrait> Generator;<br>
+  llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait><br>
+      Generator;<br>
   ASTDeclContextNameLookupTrait Trait(*this);<br>
<br>
   // The first step is to collect the declaration names which we need to<br>
@@ -3665,7 +3632,7 @@ ASTWriter::GenerateNameLookupTable(const<br>
<br>
     switch (Name.getNameKind()) {<br>
     default:<br>
-      Generator.insert(Name, Trait.getData(Result), Trait);<br>
+      Generator.insert(Name, Result, Trait);<br>
       break;<br>
<br>
     case DeclarationName::CXXConstructorName:<br>
@@ -3683,15 +3650,17 @@ ASTWriter::GenerateNameLookupTable(const<br>
   // the key, only the kind of name is used.<br>
   if (!ConstructorDecls.empty())<br>
     Generator.insert(ConstructorDecls.front()->getDeclName(),<br>
-                     Trait.getData(ConstructorDecls), Trait);<br>
+                     DeclContext::lookup_result(ConstructorDecls), Trait);<br>
   if (!ConversionDecls.empty())<br>
     Generator.insert(ConversionDecls.front()->getDeclName(),<br>
-                     Trait.getData(ConversionDecls), Trait);<br>
+                     DeclContext::lookup_result(ConversionDecls), Trait);<br>
<br>
-  // Create the on-disk hash table. Also emit the existing imported and<br>
-  // merged table if there is one.<br>
-  auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr;<br>
-  Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr);<br>
+  // Create the on-disk hash table in a buffer.<br>
+  llvm::raw_svector_ostream Out(LookupTable);<br>
+  // Make sure that no bucket is at offset 0<br>
+  using namespace llvm::support;<br>
+  endian::Writer<little>(Out).write<uint32_t>(0);<br>
+  return Generator.Emit(Out, Trait);<br>
 }<br>
<br>
 /// \brief Write the block containing all of the declaration IDs<br>
@@ -3774,11 +3743,12 @@ uint64_t ASTWriter::WriteDeclContextVisi<br>
<br>
   // Create the on-disk hash table in a buffer.<br>
   SmallString<4096> LookupTable;<br>
-  GenerateNameLookupTable(DC, LookupTable);<br>
+  uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);<br>
<br>
   // Write the lookup table<br>
   RecordData Record;<br>
   Record.push_back(DECL_CONTEXT_VISIBLE);<br>
+  Record.push_back(BucketOffset);<br>
   Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,<br>
                             LookupTable);<br>
   ++NumVisibleDeclContexts;<br>
@@ -3801,7 +3771,7 @@ void ASTWriter::WriteDeclContextVisibleU<br>
<br>
   // Create the on-disk hash table in a buffer.<br>
   SmallString<4096> LookupTable;<br>
-  GenerateNameLookupTable(DC, LookupTable);<br>
+  uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);<br>
<br>
   // If we're updating a namespace, select a key declaration as the key for the<br>
   // update record; those are the only ones that will be checked on reload.<br>
@@ -3812,6 +3782,7 @@ void ASTWriter::WriteDeclContextVisibleU<br>
   RecordData Record;<br>
   Record.push_back(UPDATE_VISIBLE);<br>
   Record.push_back(getDeclID(cast<Decl>(DC)));<br>
+  Record.push_back(BucketOffset);<br>
   Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);<br>
 }<br>
<br>
@@ -4275,6 +4246,7 @@ void ASTWriter::WriteASTCore(Sema &SemaR<br>
   Abv = new llvm::BitCodeAbbrev();<br>
   Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));<br>
   Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));<br>
+  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32));<br>
   Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));<br>
   UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv);<br>
   WriteDeclContextVisibleUpdate(TU);<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Sep  1 08:24:39 2015<br>
@@ -2049,6 +2049,7 @@ void ASTWriter::WriteDeclAbbrevs() {<br>
<br>
   Abv = new BitCodeAbbrev();<br>
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE));<br>
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));<br>
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));<br>
   DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(Abv);<br>
 }<br>
<br>
Modified: cfe/trunk/lib/Serialization/Module.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/Module.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/Module.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/Module.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/Module.cpp Tue Sep  1 08:24:39 2015<br>
@@ -45,6 +45,13 @@ ModuleFile::ModuleFile(ModuleKind Kind,<br>
 {}<br>
<br>
 ModuleFile::~ModuleFile() {<br>
+  for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(),<br>
+       E = DeclContextInfos.end();<br>
+       I != E; ++I) {<br>
+    if (I->second.NameLookupTableData)<br>
+      delete I->second.NameLookupTableData;<br>
+  }<br>
+<br>
   delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);<br>
   delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);<br>
   delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);<br>
<br>
Removed: cfe/trunk/lib/Serialization/MultiOnDiskHashTable.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/MultiOnDiskHashTable.h?rev=246545&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/MultiOnDiskHashTable.h?rev=246545&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/MultiOnDiskHashTable.h (original)<br>
+++ cfe/trunk/lib/Serialization/MultiOnDiskHashTable.h (removed)<br>
@@ -1,323 +0,0 @@<br>
-//===--- MultiOnDiskHashTable.h - Merged set of hash tables -----*- C++ -*-===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-//  This file provides a hash table data structure suitable for incremental and<br>
-//  distributed storage across a set of files.<br>
-//<br>
-//  Multiple hash tables from different files are implicitly merged to improve<br>
-//  performance, and on reload the merged table will override those from other<br>
-//  files.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-#ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H<br>
-#define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H<br>
-<br>
-#include "llvm/ADT/PointerUnion.h"<br>
-#include "llvm/Support/EndianStream.h"<br>
-#include "llvm/Support/OnDiskHashTable.h"<br>
-<br>
-namespace clang {<br>
-namespace serialization {<br>
-<br>
-class ModuleFile;<br>
-<br>
-/// \brief A collection of on-disk hash tables, merged when relevant for performance.<br>
-template<typename Info> class MultiOnDiskHashTable {<br>
-public:<br>
-  /// A handle to a file, used when overriding tables.<br>
-  typedef typename Info::file_type file_type;<br>
-  /// A pointer to an on-disk representation of the hash table.<br>
-  typedef const unsigned char *storage_type;<br>
-<br>
-  typedef typename Info::external_key_type external_key_type;<br>
-  typedef typename Info::internal_key_type internal_key_type;<br>
-  typedef typename Info::data_type data_type;<br>
-  typedef typename Info::data_type_builder data_type_builder;<br>
-  typedef unsigned hash_value_type;<br>
-<br>
-private:<br>
-  /// \brief A hash table stored on disk.<br>
-  struct OnDiskTable {<br>
-    typedef llvm::OnDiskIterableChainedHashTable<Info> HashTable;<br>
-<br>
-    file_type File;<br>
-    HashTable Table;<br>
-<br>
-    OnDiskTable(file_type File, unsigned NumBuckets, unsigned NumEntries,<br>
-                storage_type Buckets, storage_type Payload, storage_type Base,<br>
-                const Info &InfoObj)<br>
-        : File(File),<br>
-          Table(NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj) {}<br>
-  };<br>
-<br>
-  struct MergedTable {<br>
-    std::vector<file_type> Files;<br>
-    llvm::DenseMap<internal_key_type, data_type> Data;<br>
-  };<br>
-<br>
-  typedef llvm::PointerUnion<OnDiskTable*, MergedTable*> Table;<br>
-  typedef llvm::TinyPtrVector<void*> TableVector;<br>
-<br>
-  /// \brief The current set of on-disk and merged tables.<br>
-  /// We manually store the opaque value of the Table because TinyPtrVector<br>
-  /// can't cope with holding a PointerUnion directly.<br>
-  /// There can be at most one MergedTable in this vector, and if present,<br>
-  /// it is the first table.<br>
-  TableVector Tables;<br>
-<br>
-  /// \brief Files corresponding to overridden tables that we've not yet<br>
-  /// discarded.<br>
-  llvm::TinyPtrVector<file_type> PendingOverrides;<br>
-<br>
-  struct AsOnDiskTable {<br>
-    typedef OnDiskTable *result_type;<br>
-    result_type operator()(void *P) const {<br>
-      return Table::getFromOpaqueValue(P).template get<OnDiskTable *>();<br>
-    }<br>
-  };<br>
-  typedef llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable><br>
-      table_iterator;<br>
-  typedef llvm::iterator_range<table_iterator> table_range;<br>
-<br>
-  /// \brief The current set of on-disk tables.<br>
-  table_range tables() {<br>
-    auto Begin = Tables.begin(), End = Tables.end();<br>
-    if (getMergedTable())<br>
-      ++Begin;<br>
-    return llvm::make_range(llvm::map_iterator(Begin, AsOnDiskTable()),<br>
-                            llvm::map_iterator(End, AsOnDiskTable()));<br>
-  }<br>
-<br>
-  MergedTable *getMergedTable() const {<br>
-    // If we already have a merged table, it's the first one.<br>
-    return Tables.empty() ? nullptr : Table::getFromOpaqueValue(*Tables.begin())<br>
-                                          .template dyn_cast<MergedTable*>();<br>
-  }<br>
-<br>
-  /// \brief Delete all our current on-disk tables.<br>
-  void clear() {<br>
-    if (auto *M = getMergedTable())<br>
-      delete M;<br>
-    for (auto *T : tables())<br>
-      delete T;<br>
-  }<br>
-<br>
-  void removeOverriddenTables() {<br>
-    llvm::DenseSet<file_type> Files;<br>
-    Files.insert(PendingOverrides.begin(), PendingOverrides.end());<br>
-    Tables.erase(<br>
-        std::remove_if(tables().begin().getCurrent(), Tables.end(), [&](void *T) -> bool {<br>
-          auto *ODT = Table::getFromOpaqueValue(T).template get<OnDiskTable*>();<br>
-          return Files.count(ODT->File);<br>
-        }), Tables.end());<br>
-    PendingOverrides.clear();<br>
-  }<br>
-<br>
-  void condense() {<br>
-    MergedTable *Merged = getMergedTable();<br>
-    if (!Merged)<br>
-      Merged = new MergedTable;<br>
-<br>
-    // Read in all the tables and merge them together.<br>
-    // FIXME: Be smarter about which tables we merge.<br>
-    for (auto *ODT : tables()) {<br>
-      auto &HT = ODT->Table;<br>
-      Info &InfoObj = HT.getInfoObj();<br>
-<br>
-      for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {<br>
-        auto *LocalPtr = I.getItem();<br>
-<br>
-        // FIXME: Don't rely on the OnDiskHashTable format here.<br>
-        auto L = InfoObj.ReadKeyDataLength(LocalPtr);<br>
-        const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);<br>
-        data_type_builder ValueBuilder(Merged->Data[Key]);<br>
-        InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second,<br>
-                             ValueBuilder);<br>
-      }<br>
-<br>
-      Merged->Files.push_back(ODT->File);<br>
-      delete ODT;<br>
-    }<br>
-<br>
-    Tables.clear();<br>
-    Tables.push_back(Table(Merged).getOpaqueValue());<br>
-  }<br>
-<br>
-  /// The generator is permitted to read our merged table.<br>
-  template<typename ReaderInfo, typename WriterInfo><br>
-  friend class MultiOnDiskHashTableGenerator;<br>
-<br>
-public:<br>
-  MultiOnDiskHashTable() {}<br>
-  MultiOnDiskHashTable(MultiOnDiskHashTable &&O)<br>
-      : Tables(std::move(O.Tables)),<br>
-        PendingOverrides(std::move(O.PendingOverrides)) {<br>
-    O.Tables.clear();<br>
-  }<br>
-  MultiOnDiskHashTable &operator=(MultiOnDiskHashTable &&O) {<br>
-    if (&O == this)<br>
-      return *this;<br>
-    clear();<br>
-    Tables = std::move(O.Tables);<br>
-    O.Tables.clear();<br>
-    PendingOverrides = std::move(O.PendingOverrides);<br>
-    return *this;<br>
-  }<br>
-  ~MultiOnDiskHashTable() { clear(); }<br>
-<br>
-  /// \brief Add the table \p Data loaded from file \p File.<br>
-  void add(file_type File, storage_type Data, Info InfoObj = Info()) {<br>
-    using namespace llvm::support;<br>
-    storage_type Ptr = Data;<br>
-<br>
-    uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr);<br>
-<br>
-    // Read the list of overridden files.<br>
-    uint32_t NumFiles = endian::readNext<uint32_t, little, unaligned>(Ptr);<br>
-    // FIXME: Add a reserve() to TinyPtrVector so that we don't need to make<br>
-    // an additional copy.<br>
-    llvm::SmallVector<file_type, 16> OverriddenFiles;<br>
-    OverriddenFiles.reserve(NumFiles);<br>
-    for (/**/; NumFiles != 0; --NumFiles)<br>
-      OverriddenFiles.push_back(InfoObj.ReadFileRef(Ptr));<br>
-    PendingOverrides.insert(PendingOverrides.end(), OverriddenFiles.begin(),<br>
-                            OverriddenFiles.end());<br>
-<br>
-    // Read the OnDiskChainedHashTable header.<br>
-    storage_type Buckets = Data + BucketOffset;<br>
-    auto NumBucketsAndEntries =<br>
-        OnDiskTable::HashTable::readNumBucketsAndEntries(Buckets);<br>
-<br>
-    // Register the table.<br>
-    Table NewTable = new OnDiskTable(File, NumBucketsAndEntries.first,<br>
-                                     NumBucketsAndEntries.second,<br>
-                                     Buckets, Ptr, Data, std::move(InfoObj));<br>
-    Tables.push_back(NewTable.getOpaqueValue());<br>
-  }<br>
-<br>
-  /// \brief Find and read the lookup results for \p EKey.<br>
-  data_type find(const external_key_type &EKey) {<br>
-    data_type Result;<br>
-<br>
-    if (!PendingOverrides.empty())<br>
-      removeOverriddenTables();<br>
-<br>
-    if (Tables.size() > Info::MaxTables)<br>
-      condense();<br>
-<br>
-    internal_key_type Key = Info::GetInternalKey(EKey);<br>
-    auto KeyHash = Info::ComputeHash(Key);<br>
-<br>
-    if (MergedTable *M = getMergedTable()) {<br>
-      auto It = M->Data.find(Key);<br>
-      if (It != M->Data.end())<br>
-        Result = It->second;<br>
-    }<br>
-<br>
-    data_type_builder ResultBuilder(Result);<br>
-<br>
-    for (auto *ODT : tables()) {<br>
-      auto &HT = ODT->Table;<br>
-      auto It = HT.find_hashed(Key, KeyHash);<br>
-      if (It != HT.end())<br>
-        HT.getInfoObj().ReadDataInto(Key, It.getDataPtr(), It.getDataLen(),<br>
-                                     ResultBuilder);<br>
-    }<br>
-<br>
-    return Result;<br>
-  }<br>
-<br>
-  /// \brief Read all the lookup results into a single value. This only makes<br>
-  /// sense if merging values across keys is meaningful.<br>
-  data_type findAll() {<br>
-    data_type Result;<br>
-    data_type_builder ResultBuilder(Result);<br>
-<br>
-    if (!PendingOverrides.empty())<br>
-      removeOverriddenTables();<br>
-<br>
-    if (MergedTable *M = getMergedTable()) {<br>
-      for (auto &KV : M->Data)<br>
-        Info::MergeDataInto(KV.second, ResultBuilder);<br>
-    }<br>
-<br>
-    for (auto *ODT : tables()) {<br>
-      auto &HT = ODT->Table;<br>
-      Info &InfoObj = HT.getInfoObj();<br>
-      for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {<br>
-        auto *LocalPtr = I.getItem();<br>
-<br>
-        // FIXME: Don't rely on the OnDiskHashTable format here.<br>
-        auto L = InfoObj.ReadKeyDataLength(LocalPtr);<br>
-        const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);<br>
-        InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, ResultBuilder);<br>
-      }<br>
-    }<br>
-<br>
-    return Result;<br>
-  }<br>
-};<br>
-<br>
-/// \brief Writer for the on-disk hash table.<br>
-template<typename ReaderInfo, typename WriterInfo><br>
-class MultiOnDiskHashTableGenerator {<br>
-  typedef MultiOnDiskHashTable<ReaderInfo> BaseTable;<br>
-  typedef llvm::OnDiskChainedHashTableGenerator<WriterInfo> Generator;<br>
-<br>
-  Generator Gen;<br>
-<br>
-public:<br>
-  MultiOnDiskHashTableGenerator() : Gen() {}<br>
-<br>
-  void insert(typename WriterInfo::key_type_ref Key,<br>
-              typename WriterInfo::data_type_ref Data, WriterInfo &Info) {<br>
-    Gen.insert(Key, Data, Info);<br>
-  }<br>
-<br>
-  void emit(llvm::SmallVectorImpl<char> &Out, WriterInfo &Info,<br>
-            const BaseTable *Base) {<br>
-    using namespace llvm::support;<br>
-    llvm::raw_svector_ostream OutStream(Out);<br>
-<br>
-    // Write our header information.<br>
-    {<br>
-      endian::Writer<little> Writer(OutStream);<br>
-<br>
-      // Reserve four bytes for the bucket offset.<br>
-      Writer.write<uint32_t>(0);<br>
-<br>
-      if (auto *Merged = Base ? Base->getMergedTable() : nullptr) {<br>
-        // Write list of overridden files.<br>
-        Writer.write<uint32_t>(Merged->Files.size());<br>
-        for (const auto &F : Merged->Files)<br>
-          Info.EmitFileRef(OutStream, F);<br>
-<br>
-        // Add all merged entries from Base to the generator.<br>
-        for (auto &KV : Merged->Data) {<br>
-          if (!Gen.contains(KV.first, Info))<br>
-            Gen.insert(KV.first, Info.ImportData(KV.second), Info);<br>
-        }<br>
-      } else {<br>
-        Writer.write<uint32_t>(0);<br>
-      }<br>
-    }<br>
-<br>
-    // Write the table itself.<br>
-    uint32_t BucketOffset = Gen.Emit(OutStream, Info);<br>
-<br>
-    // Replace the first four bytes with the bucket offset.<br>
-    endian::write32le(Out.data(), BucketOffset);<br>
-  }<br>
-};<br>
-<br>
-} // end namespace clang::serialization<br>
-} // end namespace clang<br>
-<br>
-<br>
-#endif<br>
<br>
Modified: cfe/trunk/test/Modules/cxx-templates.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)<br>
+++ cfe/trunk/test/Modules/cxx-templates.cpp Tue Sep  1 08:24:39 2015<br>
@@ -28,8 +28,8 @@ void g() {<br>
   f<double>(1.0);<br>
   f<int>();<br>
   f(); // expected-error {{no matching function}}<br>
-  // expected-note@Inputs/cxx-templates-a.h:3 {{couldn't infer template argument}}<br>
-  // expected-note@Inputs/cxx-templates-a.h:4 {{requires 1 argument}}<br>
+  // expected-note@Inputs/cxx-templates-b.h:3 {{couldn't infer template argument}}<br>
+  // expected-note@Inputs/cxx-templates-b.h:4 {{requires single argument}}<br>
<br>
   N::f(0);<br>
   N::f<double>(1.0);<br>
@@ -179,14 +179,10 @@ namespace Std {<br>
<br>
 // CHECK-GLOBAL:      DeclarationName 'f'<br>
 // CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'<br>
-// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'<br>
-// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'<br>
 // CHECK-GLOBAL-NEXT: `-FunctionTemplate {{.*}} 'f'<br>
<br>
 // CHECK-NAMESPACE-N:      DeclarationName 'f'<br>
 // CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'<br>
-// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'<br>
-// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'<br>
 // CHECK-NAMESPACE-N-NEXT: `-FunctionTemplate {{.*}} 'f'<br>
<br>
 // CHECK-DUMP:      ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}>  col:{{.*}} in cxx_templates_common SomeTemplate<br>
<br>
Modified: cfe/trunk/test/Modules/merge-using-decls.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/merge-using-decls.cpp?rev=246546&r1=246545&r2=246546&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/merge-using-decls.cpp?rev=246546&r1=246545&r2=246546&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/merge-using-decls.cpp (original)<br>
+++ cfe/trunk/test/Modules/merge-using-decls.cpp Tue Sep  1 08:24:39 2015<br>
@@ -31,8 +31,6 @@ template int UseAll<YA>();<br>
 template int UseAll<YB>();<br>
 template int UseAll<Y>();<br>
<br>
-// Which of these two sets of diagnostics is chosen is not important. It's OK<br>
-// if this varies with ORDER, but it must be consistent across runs.<br>
 #if ORDER == 1<br>
 // Here, we're instantiating the definition from 'A' and merging the definition<br>
 // from 'B' into it.<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>