diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 7edf2704c857..62fd01266154 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -433,10 +433,7 @@ namespace clang { /// declarations. TU_UPDATE_LEXICAL = 22, - /// \brief Record code for the array describing the locations (in the - /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by - /// the first known ID. - LOCAL_REDECLARATIONS_MAP = 23, + // ID 23 used to be for a list of local redeclarations. /// \brief Record code for declarations that Sema keeps references of. SEMA_DECL_REFS = 24, @@ -514,13 +511,8 @@ namespace clang { /// imported by the AST file. IMPORTED_MODULES = 43, - // ID 40 used to be a table of merged canonical declarations. - - /// \brief Record code for the array of redeclaration chains. - /// - /// This array can only be interpreted properly using the local - /// redeclarations map. - LOCAL_REDECLARATIONS = 45, + // ID 44 used to be a table of merged canonical declarations. + // ID 45 used to be a list of declaration IDs of local redeclarations. /// \brief Record code for the array of Objective-C categories (including /// extensions). @@ -948,6 +940,9 @@ namespace clang { /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. const unsigned int NUM_PREDEF_DECL_IDS = 12; + + /// \brief Record code for a list of local redeclarations of a declaration. + const unsigned int LOCAL_REDECLARATIONS = 50; /// \brief Record codes for each kind of declaration. /// diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index ae2d54b77583..dca2032655f9 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -933,12 +933,9 @@ private: std::deque InterestingDecls; /// \brief The list of redeclaration chains that still need to be - /// reconstructed. - /// - /// Each element is the canonical declaration of the chain. - /// Elements in this vector should be unique; use - /// PendingDeclChainsKnown to ensure uniqueness. - SmallVector PendingDeclChains; + /// reconstructed, and the local offset to the corresponding list + /// of redeclarations. + SmallVector, 16> PendingDeclChains; /// \brief The list of canonical declarations whose redeclaration chains /// need to be marked as incomplete once we're done deserializing things. @@ -1165,7 +1162,7 @@ private: RecordLocation DeclCursorForID(serialization::DeclID ID, unsigned &RawLocation); void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D); - void loadPendingDeclChain(Decl *D); + void loadPendingDeclChain(Decl *D, uint64_t LocalOffset); void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D, unsigned PreviousGeneration = 0); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 5eeaee9a1590..3711e155f633 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -547,7 +547,6 @@ private: void WriteFPPragmaOptions(const FPOptions &Opts); void WriteOpenCLExtensions(Sema &SemaRef); void WriteObjCCategories(); - void WriteRedeclarations(); void WriteLateParsedTemplates(Sema &SemaRef); void WriteOptimizePragmaOptions(Sema &SemaRef); diff --git a/clang/include/clang/Serialization/Module.h b/clang/include/clang/Serialization/Module.h index ee10f9b7e4de..93067031ae8e 100644 --- a/clang/include/clang/Serialization/Module.h +++ b/clang/include/clang/Serialization/Module.h @@ -427,17 +427,6 @@ public: const serialization::DeclID *FileSortedDecls; unsigned NumFileSortedDecls; - /// \brief Array of redeclaration chain location information within this - /// module file, sorted by the first declaration ID. - const serialization::LocalRedeclarationsInfo *RedeclarationsMap; - - /// \brief The number of redeclaration info entries in RedeclarationsMap. - unsigned LocalNumRedeclarationsInMap; - - /// \brief The redeclaration chains for declarations local to this - /// module file. - SmallVector RedeclarationChains; - /// \brief Array of category list location information within this /// module file, sorted by the definition ID. const serialization::ObjCCategoriesInfo *ObjCCategoriesMap; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index bcc7e7cf48fb..9899eaf6989b 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3100,22 +3100,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } - case LOCAL_REDECLARATIONS: { - F.RedeclarationChains.swap(Record); - break; - } - - case LOCAL_REDECLARATIONS_MAP: { - if (F.LocalNumRedeclarationsInMap != 0) { - Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file"); - return Failure; - } - - F.LocalNumRedeclarationsInMap = Record[0]; - F.RedeclarationsMap = (const LocalRedeclarationsInfo *)Blob.data(); - break; - } - case MACRO_OFFSET: { if (F.LocalNumMacros != 0) { Error("duplicate MACRO_OFFSET record in AST file"); @@ -8124,7 +8108,7 @@ void ASTReader::finishPendingActions() { // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) - loadPendingDeclChain(PendingDeclChains[I]); + loadPendingDeclChain(PendingDeclChains[I].first, PendingDeclChains[I].second); PendingDeclChains.clear(); // Make the most recent of the top-level declarations visible. diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index f4f39a8506ba..00785aa1d054 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2156,6 +2156,8 @@ ASTDeclReader::VisitRedeclarable(Redeclarable *D) { bool IsKeyDecl = ThisDeclID == FirstDeclID; bool IsFirstLocalDecl = false; + uint64_t RedeclOffset = 0; + // 0 indicates that this declaration was the only declaration of its entity, // and is used for space optimization. if (FirstDeclID == 0) { @@ -2175,6 +2177,8 @@ ASTDeclReader::VisitRedeclarable(Redeclarable *D) { // declaration. for (unsigned I = 0; I != N - 1; ++I) MergeWith = ReadDecl(Record, Idx/*, MergeWith*/); + + RedeclOffset = Record[Idx++]; } else { // This declaration was not the first local declaration. Read the first // local declaration now, to trigger the import of other redeclarations. @@ -2198,7 +2202,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable *D) { // above; this ensures that the redeclaration chain is built in the correct // order. if (IsFirstLocalDecl) - Reader.PendingDeclChains.push_back(DAsT); + Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset)); return RedeclarableResult(FirstDeclID, MergeWith, IsKeyDecl); } @@ -3393,43 +3397,40 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { } } -void ASTReader::loadPendingDeclChain(Decl *FirstLocal) { - ModuleFile &M = *getOwningModuleFile(FirstLocal); - DeclID LocalID = - mapGlobalIDToModuleFileGlobalID(M, FirstLocal->getGlobalID()); - assert(LocalID && "looking for redecl chain in wrong module file"); - - // Perform a binary search to find the local redeclarations for this - // declaration (if any). - // FIXME: Just store an offset with the first declaration. - const LocalRedeclarationsInfo Compare = {LocalID, 0}; - const LocalRedeclarationsInfo *Result = std::lower_bound( - M.RedeclarationsMap, - M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare); - - // Pull out the list of redeclarations. - SmallVector Chain; - if (Result != M.RedeclarationsMap + M.LocalNumRedeclarationsInMap && - Result->FirstID == LocalID) { - unsigned Offset = Result->Offset; - unsigned N = M.RedeclarationChains[Offset++]; - for (unsigned I = 0; I != N; ++I) - Chain.push_back(GetLocalDecl(M, M.RedeclarationChains[Offset++])); - } - Chain.push_back(FirstLocal); - - // Hook up the chain. - // - // FIXME: We have three different dispatches on decl kind here; maybe - // we should instead generate one loop per kind and dispatch up-front? +void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { + // Attach FirstLocal to the end of the decl chain. Decl *CanonDecl = FirstLocal->getCanonicalDecl(); - Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl); - if (!MostRecent) - MostRecent = CanonDecl; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - auto *D = Chain[N - I - 1]; - if (D == CanonDecl) - continue; + if (FirstLocal != CanonDecl) { + Decl *PrevMostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl); + ASTDeclReader::attachPreviousDecl( + *this, FirstLocal, PrevMostRecent ? PrevMostRecent : CanonDecl, + CanonDecl); + } + + if (!LocalOffset) { + ASTDeclReader::attachLatestDecl(CanonDecl, FirstLocal); + return; + } + + // Load the list of other redeclarations from this module file. + ModuleFile *M = getOwningModuleFile(FirstLocal); + assert(M && "imported decl from no module file"); + + llvm::BitstreamCursor &Cursor = M->DeclsCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(LocalOffset); + + RecordData Record; + unsigned Code = Cursor.ReadCode(); + unsigned RecCode = Cursor.readRecord(Code, Record); + (void)RecCode; + assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!"); + + // FIXME: We have several different dispatches on decl kind here; maybe + // we should instead generate one loop per kind and dispatch up-front? + Decl *MostRecent = FirstLocal; + for (unsigned I = 0, N = Record.size(); I != N; ++I) { + auto *D = GetLocalDecl(*M, Record[N - I - 1]); ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl); MostRecent = D; } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ae326b2068b7..d7803d166eea 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -911,7 +911,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(PPD_ENTITIES_OFFSETS); RECORD(REFERENCED_SELECTOR_POOL); RECORD(TU_UPDATE_LEXICAL); - RECORD(LOCAL_REDECLARATIONS_MAP); RECORD(SEMA_DECL_REFS); RECORD(WEAK_UNDECLARED_IDENTIFIERS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS); @@ -933,7 +932,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(OBJC_CATEGORIES_MAP); RECORD(FILE_SORTED_DECLS); RECORD(IMPORTED_MODULES); - RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); RECORD(MACRO_OFFSET); RECORD(LATE_PARSED_TEMPLATE); @@ -997,6 +995,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_ATOMIC); RECORD(TYPE_DECAYED); RECORD(TYPE_ADJUSTED); + RECORD(LOCAL_REDECLARATIONS); RECORD(DECL_TYPEDEF); RECORD(DECL_TYPEALIAS); RECORD(DECL_ENUM); @@ -3794,76 +3793,6 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } -void ASTWriter::WriteRedeclarations() { - RecordData LocalRedeclChains; - SmallVector LocalRedeclsMap; - - for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) { - const Decl *FirstLocal = Redeclarations[I]; - assert(!FirstLocal->isFromASTFile() && - (!FirstLocal->getPreviousDecl() || - FirstLocal->getPreviousDecl()->isFromASTFile() || - getDeclID(FirstLocal->getPreviousDecl()) < NUM_PREDEF_DECL_IDS) && - "not the first local declaration"); - assert(getDeclID(FirstLocal) >= NUM_PREDEF_DECL_IDS && - "should not have predefined decl as first decl"); - - unsigned Offset = LocalRedeclChains.size(); - unsigned Size = 0; - LocalRedeclChains.push_back(0); // Placeholder for the size. - - // Collect the set of local redeclarations of this declaration, from newest - // to oldest. - for (const Decl *Prev = FirstLocal->getMostRecentDecl(); Prev != FirstLocal; - Prev = Prev->getPreviousDecl()) { - if (!Prev->isFromASTFile()) { - AddDeclRef(Prev, LocalRedeclChains); - ++Size; - } - } - - // If we only have a single local declaration, there is no point in storing - // a redeclaration chain. - if (LocalRedeclChains.size() == 1) - continue; - - LocalRedeclChains[Offset] = Size; - - // Add the mapping from the first ID from the AST to the set of local - // declarations. - LocalRedeclarationsInfo Info = { getDeclID(FirstLocal), Offset }; - LocalRedeclsMap.push_back(Info); - - assert(N == Redeclarations.size() && - "Deserialized a declaration we shouldn't have"); - } - - if (LocalRedeclChains.empty()) - return; - - // Sort the local redeclarations map by the first declaration ID, - // since the reader will be performing binary searches on this information. - llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end()); - - // Emit the local redeclarations map. - using namespace llvm; - llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned AbbrevID = Stream.EmitAbbrev(Abbrev); - - RecordData Record; - Record.push_back(LOCAL_REDECLARATIONS_MAP); - Record.push_back(LocalRedeclsMap.size()); - Stream.EmitRecordWithBlob(AbbrevID, Record, - reinterpret_cast(LocalRedeclsMap.data()), - LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo)); - - // Emit the redeclaration chains. - Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains); -} - void ASTWriter::WriteObjCCategories() { SmallVector CategoriesMap; RecordData Categories; @@ -4589,7 +4518,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } WriteDeclReplacementsBlock(); - WriteRedeclarations(); WriteObjCCategories(); if(!WritingModule) WriteOptimizePragmaOptions(SemaRef); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 712eae186ca6..3f8ddf1292e2 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1565,8 +1565,6 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable *D) { // first local declaration in the chain. const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT); if (DAsT == FirstLocal) { - Writer.Redeclarations.push_back(DAsT); - // Emit a list of all imported first declarations so that we can be sure // that all redeclarations visible to this module are before D in the // redecl chain. @@ -1576,6 +1574,23 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable *D) { AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false); // This is the number of imported first declarations + 1. Record[I] = Record.size() - I; + + // Collect the set of local redeclarations of this declaration, from + // newest to oldest. + RecordData LocalRedecls; + for (const Decl *Prev = FirstLocal->getMostRecentDecl(); + Prev != FirstLocal; Prev = Prev->getPreviousDecl()) + if (!Prev->isFromASTFile()) + Writer.AddDeclRef(Prev, LocalRedecls); + + // If we have any redecls, write them now as a separate record preceding + // the declaration itself. + if (LocalRedecls.empty()) + Record.push_back(0); + else { + Record.push_back(Writer.Stream.GetCurrentBitNo()); + Writer.Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedecls); + } } else { Record.push_back(0); Writer.AddDeclRef(FirstLocal, Record); @@ -2114,6 +2129,13 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); } + // Build a record for this declaration + Record.clear(); + W.Code = (serialization::DeclCode)0; + W.AbbrevToUse = 0; + W.Visit(D); + if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); + if (isReplacingADecl) { // We're replacing a decl in a previous file. ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(), @@ -2130,19 +2152,12 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { DeclOffsets[Index].setLocation(Loc); DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo(); } - + SourceManager &SM = Context.getSourceManager(); if (Loc.isValid() && SM.isLocalSourceLocation(Loc)) associateDeclWithFile(D, ID); } - // Build and emit a record for this declaration - Record.clear(); - W.Code = (serialization::DeclCode)0; - W.AbbrevToUse = 0; - W.Visit(D); - if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); - if (!W.Code) llvm::report_fatal_error(StringRef("unexpected declaration kind '") + D->getDeclKindName() + "'"); diff --git a/clang/lib/Serialization/Module.cpp b/clang/lib/Serialization/Module.cpp index 3b237d5529c6..9111fc40a027 100644 --- a/clang/lib/Serialization/Module.cpp +++ b/clang/lib/Serialization/Module.cpp @@ -40,7 +40,6 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr), LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr), FileSortedDecls(nullptr), NumFileSortedDecls(0), - RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0), ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0), LocalNumTypes(0), TypeOffsets(nullptr), BaseTypeIndex(0) {}