From 10e7846abf4e69f03dfb65b36d866c01ece66645 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 2 Oct 2012 21:09:13 +0000 Subject: [PATCH] [libclang] When indexing an AST file, only deserialize the file level declarations of the current primary module. llvm-svn: 165046 --- clang/include/clang/Frontend/ASTUnit.h | 10 +++ clang/include/clang/Serialization/ASTReader.h | 61 ++++++++++++++++++- clang/include/clang/Serialization/Module.h | 1 + clang/lib/Frontend/ASTUnit.cpp | 24 ++++++++ clang/lib/Serialization/ASTReader.cpp | 10 ++- clang/lib/Serialization/ASTWriter.cpp | 2 + clang/lib/Serialization/Module.cpp | 3 +- clang/tools/libclang/Indexing.cpp | 32 +++------- 8 files changed, 117 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 22cc581531f4..454bf512923e 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -613,6 +613,16 @@ public: std::pair getLocalPreprocessingEntities() const; + /// \brief Type for a function iterating over a number of declarations. + /// \returns true to continue iteration and false to abort. + typedef bool (*DeclReceiverFn)(void *context, const Decl *D); + + /// \brief Iterate over local declarations (locally parsed if this is a parsed + /// source file or the loaded declarations of the primary module if this is an + /// AST file). + /// \returns true if the iteration was complete or false if it was aborted. + bool applyOnLocalTopLevelDecls(void *context, DeclReceiverFn Fn); + llvm::MemoryBuffer *getBufferForFile(StringRef Filename, std::string *ErrorStr = 0); diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index b5d1e62a2068..7c5259732dd2 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -860,6 +860,64 @@ private: std::pair getModulePreprocessedEntities(ModuleFile &Mod) const; + class ModuleDeclIterator { + ASTReader *Reader; + ModuleFile *Mod; + const serialization::LocalDeclID *Pos; + + public: + typedef const Decl *value_type; + typedef value_type& reference; + typedef value_type* pointer; + + ModuleDeclIterator() : Reader(0), Mod(0), Pos(0) { } + + ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod, + const serialization::LocalDeclID *Pos) + : Reader(Reader), Mod(Mod), Pos(Pos) { } + + value_type operator*() const { + return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *Pos)); + } + + ModuleDeclIterator &operator++() { + ++Pos; + return *this; + } + + ModuleDeclIterator operator++(int) { + ModuleDeclIterator Prev(*this); + ++Pos; + return Prev; + } + + ModuleDeclIterator &operator--() { + --Pos; + return *this; + } + + ModuleDeclIterator operator--(int) { + ModuleDeclIterator Prev(*this); + --Pos; + return Prev; + } + + friend bool operator==(const ModuleDeclIterator &LHS, + const ModuleDeclIterator &RHS) { + assert(LHS.Reader == RHS.Reader && LHS.Mod == RHS.Mod); + return LHS.Pos == RHS.Pos; + } + + friend bool operator!=(const ModuleDeclIterator &LHS, + const ModuleDeclIterator &RHS) { + assert(LHS.Reader == RHS.Reader && LHS.Mod == RHS.Mod); + return LHS.Pos != RHS.Pos; + } + }; + + std::pair + getModuleFileLevelDecls(ModuleFile &Mod); + void PassInterestingDeclsToConsumer(); void PassInterestingDeclToConsumer(Decl *D); @@ -1081,7 +1139,8 @@ public: /// \brief Map from a local declaration ID within a given module to a /// global declaration ID. - serialization::DeclID getGlobalDeclID(ModuleFile &F, unsigned LocalID) const; + serialization::DeclID getGlobalDeclID(ModuleFile &F, + serialization::LocalDeclID LocalID) const; /// \brief Returns true if global DeclID \p ID originated from module \p M. bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const; diff --git a/clang/include/clang/Serialization/Module.h b/clang/include/clang/Serialization/Module.h index 786ecd33c1d3..e6e7476ba8b5 100644 --- a/clang/include/clang/Serialization/Module.h +++ b/clang/include/clang/Serialization/Module.h @@ -294,6 +294,7 @@ public: /// \brief Array of file-level DeclIDs sorted by file. const serialization::DeclID *FileSortedDecls; + unsigned NumFileSortedDecls; /// \brief Array of redeclaration chain location information within this /// module file, sorted by the first declaration ID. diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 2cf25ebd9ac4..eaad06a36eaa 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -2792,6 +2792,30 @@ ASTUnit::getLocalPreprocessingEntities() const { PreprocessingRecord::iterator()); } +bool ASTUnit::applyOnLocalTopLevelDecls(void *context, DeclReceiverFn Fn) { + if (isMainFileAST()) { + serialization::ModuleFile & + Mod = Reader->getModuleManager().getPrimaryModule(); + ASTReader::ModuleDeclIterator MDI, MDE; + llvm::tie(MDI, MDE) = Reader->getModuleFileLevelDecls(Mod); + for (; MDI != MDE; ++MDI) { + if (!Fn(context, *MDI)) + return false; + } + + return true; + } + + for (ASTUnit::top_level_iterator TL = top_level_begin(), + TLEnd = top_level_end(); + TL != TLEnd; ++TL) { + if (!Fn(context, *TL)) + return false; + } + + return true; +} + void ASTUnit::PreambleData::countLines() const { NumLines = 0; if (empty()) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 6bf6f94fbbaf..3960fa29ce75 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2063,6 +2063,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) { case FILE_SORTED_DECLS: F.FileSortedDecls = (const DeclID *)BlobStart; + F.NumFileSortedDecls = Record[0]; break; case SOURCE_LOCATION_OFFSETS: { @@ -3391,6 +3392,13 @@ ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const { PreprocessingRecord::iterator()); } +std::pair +ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) { + return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls), + ModuleDeclIterator(this, &Mod, + Mod.FileSortedDecls + Mod.NumFileSortedDecls)); +} + PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { PreprocessedEntityID PPID = Index+1; std::pair PPInfo = getModulePreprocessedEntity(Index); @@ -4625,7 +4633,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { } serialization::DeclID -ASTReader::getGlobalDeclID(ModuleFile &F, unsigned LocalID) const { +ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const { if (LocalID < NUM_PREDEF_DECL_IDS) return LocalID; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 7aa68b7bc684..384995722afe 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2251,9 +2251,11 @@ void ASTWriter::WriteFileDeclIDsMap() { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); Record.push_back(FILE_SORTED_DECLS); + Record.push_back(FileSortedIDs.size()); Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs)); } diff --git a/clang/lib/Serialization/Module.cpp b/clang/lib/Serialization/Module.cpp index ff241d3d4105..5fab02b1fb4d 100644 --- a/clang/lib/Serialization/Module.cpp +++ b/clang/lib/Serialization/Module.cpp @@ -35,7 +35,8 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), DeclOffsets(0), BaseDeclID(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), - FileSortedDecls(0), RedeclarationsMap(0), LocalNumRedeclarationsInMap(0), + FileSortedDecls(0), NumFileSortedDecls(0), + RedeclarationsMap(0), LocalNumRedeclarationsInMap(0), ObjCCategoriesMap(0), LocalNumObjCCategoriesInMap(0), LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0) {} diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 8c19aeba2855..598dbce7b650 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -472,30 +472,16 @@ static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { } } +static bool topLevelDeclReceiver(void *context, const Decl *D) { + IndexingContext &IdxCtx = *static_cast(context); + IdxCtx.indexTopLevelDecl(D); + if (IdxCtx.shouldAbort()) + return false; + return true; +} + static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { - // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module - // that it depends on. - - bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls(); - - if (OnlyLocal) { - for (ASTUnit::top_level_iterator TL = Unit.top_level_begin(), - TLEnd = Unit.top_level_end(); - TL != TLEnd; ++TL) { - IdxCtx.indexTopLevelDecl(*TL); - if (IdxCtx.shouldAbort()) - return; - } - - } else { - TranslationUnitDecl *TUDecl = Unit.getASTContext().getTranslationUnitDecl(); - for (TranslationUnitDecl::decl_iterator - I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; ++I) { - IdxCtx.indexTopLevelDecl(*I); - if (IdxCtx.shouldAbort()) - return; - } - } + Unit.applyOnLocalTopLevelDecls(&IdxCtx, topLevelDeclReceiver); } static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {