]> granicus.if.org Git - clang/commitdiff
Reverting r246497 (which requires also reverting r246524 and r246521 to avoid merge...
authorAaron Ballman <aaron@aaronballman.com>
Tue, 1 Sep 2015 13:24:39 +0000 (13:24 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Tue, 1 Sep 2015 13:24:39 +0000 (13:24 +0000)
llvm\tools\clang\lib\serialization\MultiOnDiskHashTable.h(117):
error C2065: 'Files': undeclared identifier

http://bb.pgr.jp/builders/ninja-clang-i686-msc18-R/builds/2917

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@246546 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
include/clang/Serialization/Module.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTReaderInternals.h
lib/Serialization/ASTWriter.cpp
lib/Serialization/ASTWriterDecl.cpp
lib/Serialization/Module.cpp
lib/Serialization/MultiOnDiskHashTable.h [deleted file]
test/Modules/cxx-templates.cpp
test/Modules/merge-using-decls.cpp

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