diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 8b5790fc9c66..889605e34d38 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -343,14 +343,29 @@ private: const serialization::DeclID *LexicalDecls; unsigned NumLexicalDecls; }; + // In a full chain, there could be multiple updates to every decl context, + // so this is a vector. However, typically a chain is only two elements long, + // with only one file containing updates, so there will be only one update + // per decl context. typedef llvm::SmallVector DeclContextInfos; typedef llvm::DenseMap - DeclContextOffsetsMap; + DeclContextOffsetsMap; + // Updates for visible decls can occur for other contexts than just the + // TU, and when we read those update records, the actual context will not + // be available yet (unless it's the TU), so have this pending map using the + // ID as a key. It will be realized when the context is actually loaded. + typedef llvm::SmallVector DeclContextVisibleUpdates; + typedef llvm::DenseMap + DeclContextVisibleUpdatesPending; /// \brief Offsets of the lexical and visible declarations for each /// DeclContext. DeclContextOffsetsMap DeclContextOffsets; + /// \brief Updates to the visible declarations of declaration contexts that + /// haven't been loaded yet. + DeclContextVisibleUpdatesPending PendingVisibleUpdates; + typedef llvm::DenseMap FirstLatestDeclIDMap; /// \brief Map of first declarations from a chained PCH that point to the diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 2a5a9ac1d959..8167a0f5faff 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -412,43 +412,6 @@ void PCHValidator::ReadCounter(unsigned Value) { // AST reader implementation //===----------------------------------------------------------------------===// -ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context, - const char *isysroot, bool DisableValidation) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), - Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation), - NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), - TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), - NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), - NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0), - TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0), - TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), - TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) { - RelocatablePCH = false; -} - -ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot, - bool DisableValidation) - : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), - Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), - isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0), - NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0), - NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), - TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), - NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), - NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), - NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), - NumCurrentElementsDeserializing(0) { - RelocatablePCH = false; -} - -ASTReader::~ASTReader() { - for (unsigned i = 0, e = Chain.size(); i != e; ++i) - delete Chain[e - i - 1]; -} - void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) { DeserializationListener = Listener; @@ -1770,6 +1733,22 @@ ASTReader::ReadASTBlock(PerFileData &F) { break; } + case UPDATE_VISIBLE: { + serialization::DeclID ID = Record[0]; + void *Table = ASTDeclContextNameLookupTable::Create( + (const unsigned char *)BlobStart + Record[1], + (const unsigned char *)BlobStart, + ASTDeclContextNameLookupTrait(*this)); + if (ID == 1) { // Is it the TU? + DeclContextInfo Info = { + Table, /* No lexical inforamtion */ 0, 0 + }; + DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info); + } else + PendingVisibleUpdates[ID].push_back(Table); + break; + } + case REDECLS_UPDATE_LATEST: { assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs"); for (unsigned i = 0, e = Record.size(); i < e; i += 2) { @@ -3130,7 +3109,7 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() { if (!DeclsLoaded[0]) { - ReadDeclRecord(0, 0); + ReadDeclRecord(0, 1); if (DeserializationListener) DeserializationListener->DeclRead(1, DeclsLoaded[0]); } @@ -4084,6 +4063,63 @@ void ASTReader::FinishedDeserializing() { --NumCurrentElementsDeserializing; } +ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context, + const char *isysroot, bool DisableValidation) + : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), + SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), + Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), + Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation), + NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), + TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), + NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), + NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0), + TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0), + TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), + TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) { + RelocatablePCH = false; +} + +ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr, + Diagnostic &Diags, const char *isysroot, + bool DisableValidation) + : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), + Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), + isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0), + NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0), + NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), + TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), + NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), + NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), + NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), + NumCurrentElementsDeserializing(0) { + RelocatablePCH = false; +} + +ASTReader::~ASTReader() { + for (unsigned i = 0, e = Chain.size(); i != e; ++i) + delete Chain[e - i - 1]; + // Delete all visible decl lookup tables + for (DeclContextOffsetsMap::iterator I = DeclContextOffsets.begin(), + E = DeclContextOffsets.end(); + I != E; ++I) { + for (DeclContextInfos::iterator J = I->second.begin(), F = I->second.end(); + J != F; ++J) { + if (J->NameLookupTableData) + delete static_cast( + J->NameLookupTableData); + } + } + for (DeclContextVisibleUpdatesPending::iterator + I = PendingVisibleUpdates.begin(), + E = PendingVisibleUpdates.end(); + I != E; ++I) { + for (DeclContextVisibleUpdates::iterator J = I->second.begin(), + F = I->second.end(); + J != F; ++J) + delete static_cast(*J); + } +} + ASTReader::PerFileData::PerFileData() : StatCache(0), LocalNumSLocEntries(0), LocalNumTypes(0), TypeOffsets(0), LocalNumDecls(0), DeclOffsets(0), LocalNumIdentifiers(0), diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0ee8c83183a8..d2fb408e56c9 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1402,10 +1402,26 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { if (ReadDeclContextStorage(DeclsCursor, Offsets, Info)) return 0; DeclContextInfos &Infos = DeclContextOffsets[DC]; - // Reading the TU will happen after reading its update blocks, so we need - // to make sure we insert in front. For all other contexts, the vector - // is empty here anyway, so there's no loss in efficiency. + // Reading the TU will happen after reading its lexical update blocks, + // so we need to make sure we insert in front. For all other contexts, + // the vector is empty here anyway, so there's no loss in efficiency. Infos.insert(Infos.begin(), Info); + + // Now add the pending visible updates for this decl context, if it has + // any. + DeclContextVisibleUpdatesPending::iterator I = + PendingVisibleUpdates.find(ID); + if (I != PendingVisibleUpdates.end()) { + DeclContextVisibleUpdates &U = I->second; + Info.LexicalDecls = 0; + Info.NumLexicalDecls = 0; + for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); + UI != UE; ++UI) { + Info.NameLookupTableData = *UI; + Infos.push_back(Info); + } + PendingVisibleUpdates.erase(I); + } } } assert(Idx == Record.size());