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