Index: clangd/ClangdUnit.h =================================================================== --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -44,12 +44,10 @@ // Stores Preamble and associated data. struct PreambleData { - PreambleData(PrecompiledPreamble Preamble, - std::vector TopLevelDeclIDs, - std::vector Diags, std::vector Inclusions); + PreambleData(PrecompiledPreamble Preamble, std::vector Diags, + std::vector Inclusions); PrecompiledPreamble Preamble; - std::vector TopLevelDeclIDs; std::vector Diags; // Processes like code completions and go-to-definitions will need #include // information, and their compile action skips preamble range. @@ -80,6 +78,9 @@ ~ParsedAST(); + /// Note that the returned ast will not contain decls from the preamble that + /// were not deserialized during parsing. Clients should expect only decls + /// from the main file to be in the AST. ASTContext &getASTContext(); const ASTContext &getASTContext() const; @@ -87,10 +88,9 @@ std::shared_ptr getPreprocessorPtr(); const Preprocessor &getPreprocessor() const; - /// This function returns all top-level decls, including those that come - /// from Preamble. Decls, coming from Preamble, have to be deserialized, so - /// this call might be expensive. - ArrayRef getTopLevelDecls(); + /// This function returns top-level decls present in the main file of the AST. + /// The result does not include the decls that come from the preamble. + ArrayRef getLocalTopLevelDecls(); const std::vector &getDiagnostics() const; @@ -103,11 +103,8 @@ ParsedAST(std::shared_ptr Preamble, std::unique_ptr Clang, std::unique_ptr Action, - std::vector TopLevelDecls, std::vector Diags, - std::vector Inclusions); - -private: - void ensurePreambleDeclsDeserialized(); + std::vector LocalTopLevelDecls, + std::vector Diags, std::vector Inclusions); // In-memory preambles must outlive the AST, it is important that this member // goes before Clang and Action. @@ -122,8 +119,9 @@ // Data, stored after parsing. std::vector Diags; - std::vector TopLevelDecls; - bool PreambleDeclsDeserialized; + // Top-level decls inside the current file. Not that this does not include + // top-level decls from the preamble. + std::vector LocalTopLevelDecls; std::vector Inclusions; }; Index: clangd/ClangdUnit.cpp =================================================================== --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -90,22 +90,8 @@ CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback) : File(File), ParsedCallback(ParsedCallback) {} - std::vector takeTopLevelDeclIDs() { - return std::move(TopLevelDeclIDs); - } - std::vector takeInclusions() { return std::move(Inclusions); } - void AfterPCHEmitted(ASTWriter &Writer) override { - TopLevelDeclIDs.reserve(TopLevelDecls.size()); - for (Decl *D : TopLevelDecls) { - // Invalid top-level decls may not have been serialized. - if (D->isInvalidDecl()) - continue; - TopLevelDeclIDs.push_back(Writer.getDeclID(D)); - } - } - void AfterExecute(CompilerInstance &CI) override { if (!ParsedCallback) return; @@ -113,14 +99,6 @@ ParsedCallback(File, CI.getASTContext(), CI.getPreprocessorPtr()); } - void HandleTopLevelDecl(DeclGroupRef DG) override { - for (Decl *D : DG) { - if (isa(D)) - continue; - TopLevelDecls.push_back(D); - } - } - void BeforeExecute(CompilerInstance &CI) override { SourceMgr = &CI.getSourceManager(); } @@ -135,8 +113,6 @@ private: PathRef File; PreambleParsedCallback ParsedCallback; - std::vector TopLevelDecls; - std::vector TopLevelDeclIDs; std::vector Inclusions; SourceManager *SourceMgr = nullptr; }; @@ -204,28 +180,6 @@ std::move(Inclusions)); } -void ParsedAST::ensurePreambleDeclsDeserialized() { - if (PreambleDeclsDeserialized || !Preamble) - return; - - std::vector Resolved; - Resolved.reserve(Preamble->TopLevelDeclIDs.size()); - - ExternalASTSource &Source = *getASTContext().getExternalSource(); - for (serialization::DeclID TopLevelDecl : Preamble->TopLevelDeclIDs) { - // Resolve the declaration ID to an actual declaration, possibly - // deserializing the declaration in the process. - if (Decl *D = Source.GetExternalDecl(TopLevelDecl)) - Resolved.push_back(D); - } - - TopLevelDecls.reserve(TopLevelDecls.size() + - Preamble->TopLevelDeclIDs.size()); - TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end()); - - PreambleDeclsDeserialized = true; -} - ParsedAST::ParsedAST(ParsedAST &&Other) = default; ParsedAST &ParsedAST::operator=(ParsedAST &&Other) = default; @@ -252,9 +206,8 @@ return Clang->getPreprocessor(); } -ArrayRef ParsedAST::getTopLevelDecls() { - ensurePreambleDeclsDeserialized(); - return TopLevelDecls; +ArrayRef ParsedAST::getLocalTopLevelDecls() { + return LocalTopLevelDecls; } const std::vector &ParsedAST::getDiagnostics() const { return Diags; } @@ -264,7 +217,7 @@ // FIXME(ibiryukov): we do not account for the dynamically allocated part of // Message and Fixes inside each diagnostic. return AST.getASTAllocatedMemory() + AST.getSideTableAllocatedMemory() + - ::getUsedBytes(TopLevelDecls) + ::getUsedBytes(Diags); + ::getUsedBytes(LocalTopLevelDecls) + ::getUsedBytes(Diags); } const std::vector &ParsedAST::getInclusions() const { @@ -272,21 +225,19 @@ } PreambleData::PreambleData(PrecompiledPreamble Preamble, - std::vector TopLevelDeclIDs, std::vector Diags, std::vector Inclusions) - : Preamble(std::move(Preamble)), - TopLevelDeclIDs(std::move(TopLevelDeclIDs)), Diags(std::move(Diags)), + : Preamble(std::move(Preamble)), Diags(std::move(Diags)), Inclusions(std::move(Inclusions)) {} ParsedAST::ParsedAST(std::shared_ptr Preamble, std::unique_ptr Clang, std::unique_ptr Action, - std::vector TopLevelDecls, + std::vector LocalTopLevelDecls, std::vector Diags, std::vector Inclusions) : Preamble(std::move(Preamble)), Clang(std::move(Clang)), Action(std::move(Action)), Diags(std::move(Diags)), - TopLevelDecls(std::move(TopLevelDecls)), PreambleDeclsDeserialized(false), + LocalTopLevelDecls(std::move(LocalTopLevelDecls)), Inclusions(std::move(Inclusions)) { assert(this->Clang); assert(this->Action); @@ -431,9 +382,8 @@ " for file " + Twine(FileName)); return std::make_shared( - std::move(*BuiltPreamble), - SerializedDeclsCollector.takeTopLevelDeclIDs(), - PreambleDiagnostics.take(), SerializedDeclsCollector.takeInclusions()); + std::move(*BuiltPreamble), PreambleDiagnostics.take(), + SerializedDeclsCollector.takeInclusions()); } else { log("Could not build a preamble for file " + Twine(FileName)); return nullptr; Index: clangd/XRefs.cpp =================================================================== --- clangd/XRefs.cpp +++ clangd/XRefs.cpp @@ -168,7 +168,7 @@ IndexOpts.SystemSymbolFilter = index::IndexingOptions::SystemSymbolFilterKind::All; IndexOpts.IndexFunctionLocals = true; - indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(), + indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(), DeclMacrosFinder, IndexOpts); return {DeclMacrosFinder.takeDecls(), DeclMacrosFinder.takeMacroInfos()}; @@ -418,7 +418,7 @@ IndexOpts.SystemSymbolFilter = index::IndexingOptions::SystemSymbolFilterKind::All; IndexOpts.IndexFunctionLocals = true; - indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(), + indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(), DocHighlightsFinder, IndexOpts); return DocHighlightsFinder.takeHighlights(); Index: unittests/clangd/TestTU.cpp =================================================================== --- unittests/clangd/TestTU.cpp +++ unittests/clangd/TestTU.cpp @@ -1,5 +1,4 @@ -//===--- TestTU.cpp - Scratch source files for testing ------------*- -//C++-*-===// +//===--- TestTU.cpp - Scratch source files for testing --------------------===// // // The LLVM Compiler Infrastructure // @@ -73,22 +72,24 @@ } const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) { - const NamedDecl *Result = nullptr; - for (const Decl *D : AST.getTopLevelDecls()) { - auto *ND = dyn_cast(D); - if (!ND || ND->getNameAsString() != QName) - continue; - if (Result) { - ADD_FAILURE() << "Multiple Decls named " << QName; - assert(false && "QName is not unique"); - } - Result = ND; - } - if (!Result) { - ADD_FAILURE() << "No Decl named " << QName << " in AST"; - assert(false && "No Decl with QName"); + llvm::SmallVector Components; + QName.split(Components, "::"); + + auto &Ctx = AST.getASTContext(); + auto LookupDecl = [&Ctx](const DeclContext &Scope, + llvm::StringRef Name) -> const NamedDecl & { + auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(Name))); + assert(!LookupRes.empty() && "Lookup failed"); + assert(LookupRes.size() == 1 && "Lookup returned multiple results"); + return *LookupRes.front(); + }; + + const DeclContext *Scope = Ctx.getTranslationUnitDecl(); + for (auto NameIt = Components.begin(), End = Components.end() - 1; + NameIt != End; ++NameIt) { + Scope = &cast(LookupDecl(*Scope, *NameIt)); } - return *Result; + return LookupDecl(*Scope, Components.back()); } } // namespace clangd