[clangd] Remove accessors for top-level decls from preamble
Summary: They cause lots of deserialization and are not actually used. The ParsedAST accessor that previously returned those was renamed from getTopLevelDecls to getLocalTopLevelDecls in order to avoid confusion. This change should considerably improve the speed of findDefinition and other features that try to find AST nodes, corresponding to the locations in the source code. Reviewers: ioeric, sammccall Reviewed By: sammccall Subscribers: klimek, mehdi_amini, MaskRay, jkorous, cfe-commits Differential Revision: https://reviews.llvm.org/D47331 llvm-svn: 333371
This commit is contained in:
parent
981a35d81e
commit
da0256f2c8
|
@ -90,22 +90,8 @@ public:
|
|||
CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
|
||||
: File(File), ParsedCallback(ParsedCallback) {}
|
||||
|
||||
std::vector<serialization::DeclID> takeTopLevelDeclIDs() {
|
||||
return std::move(TopLevelDeclIDs);
|
||||
}
|
||||
|
||||
std::vector<Inclusion> 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 @@ public:
|
|||
ParsedCallback(File, CI.getASTContext(), CI.getPreprocessorPtr());
|
||||
}
|
||||
|
||||
void HandleTopLevelDecl(DeclGroupRef DG) override {
|
||||
for (Decl *D : DG) {
|
||||
if (isa<ObjCMethodDecl>(D))
|
||||
continue;
|
||||
TopLevelDecls.push_back(D);
|
||||
}
|
||||
}
|
||||
|
||||
void BeforeExecute(CompilerInstance &CI) override {
|
||||
SourceMgr = &CI.getSourceManager();
|
||||
}
|
||||
|
@ -135,8 +113,6 @@ public:
|
|||
private:
|
||||
PathRef File;
|
||||
PreambleParsedCallback ParsedCallback;
|
||||
std::vector<Decl *> TopLevelDecls;
|
||||
std::vector<serialization::DeclID> TopLevelDeclIDs;
|
||||
std::vector<Inclusion> Inclusions;
|
||||
SourceManager *SourceMgr = nullptr;
|
||||
};
|
||||
|
@ -204,28 +180,6 @@ ParsedAST::Build(std::unique_ptr<clang::CompilerInvocation> CI,
|
|||
std::move(Inclusions));
|
||||
}
|
||||
|
||||
void ParsedAST::ensurePreambleDeclsDeserialized() {
|
||||
if (PreambleDeclsDeserialized || !Preamble)
|
||||
return;
|
||||
|
||||
std::vector<const Decl *> 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 @@ const Preprocessor &ParsedAST::getPreprocessor() const {
|
|||
return Clang->getPreprocessor();
|
||||
}
|
||||
|
||||
ArrayRef<const Decl *> ParsedAST::getTopLevelDecls() {
|
||||
ensurePreambleDeclsDeserialized();
|
||||
return TopLevelDecls;
|
||||
ArrayRef<const Decl *> ParsedAST::getLocalTopLevelDecls() {
|
||||
return LocalTopLevelDecls;
|
||||
}
|
||||
|
||||
const std::vector<Diag> &ParsedAST::getDiagnostics() const { return Diags; }
|
||||
|
@ -264,7 +217,7 @@ std::size_t ParsedAST::getUsedBytes() const {
|
|||
// 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<Inclusion> &ParsedAST::getInclusions() const {
|
||||
|
@ -272,21 +225,19 @@ const std::vector<Inclusion> &ParsedAST::getInclusions() const {
|
|||
}
|
||||
|
||||
PreambleData::PreambleData(PrecompiledPreamble Preamble,
|
||||
std::vector<serialization::DeclID> TopLevelDeclIDs,
|
||||
std::vector<Diag> Diags,
|
||||
std::vector<Inclusion> 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<const PreambleData> Preamble,
|
||||
std::unique_ptr<CompilerInstance> Clang,
|
||||
std::unique_ptr<FrontendAction> Action,
|
||||
std::vector<const Decl *> TopLevelDecls,
|
||||
std::vector<const Decl *> LocalTopLevelDecls,
|
||||
std::vector<Diag> Diags, std::vector<Inclusion> 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 @@ CppFile::rebuildPreamble(CompilerInvocation &CI,
|
|||
" for file " + Twine(FileName));
|
||||
|
||||
return std::make_shared<PreambleData>(
|
||||
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;
|
||||
|
|
|
@ -44,12 +44,10 @@ namespace clangd {
|
|||
|
||||
// Stores Preamble and associated data.
|
||||
struct PreambleData {
|
||||
PreambleData(PrecompiledPreamble Preamble,
|
||||
std::vector<serialization::DeclID> TopLevelDeclIDs,
|
||||
std::vector<Diag> Diags, std::vector<Inclusion> Inclusions);
|
||||
PreambleData(PrecompiledPreamble Preamble, std::vector<Diag> Diags,
|
||||
std::vector<Inclusion> Inclusions);
|
||||
|
||||
PrecompiledPreamble Preamble;
|
||||
std::vector<serialization::DeclID> TopLevelDeclIDs;
|
||||
std::vector<Diag> Diags;
|
||||
// Processes like code completions and go-to-definitions will need #include
|
||||
// information, and their compile action skips preamble range.
|
||||
|
@ -80,6 +78,9 @@ public:
|
|||
|
||||
~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 @@ public:
|
|||
std::shared_ptr<Preprocessor> 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<const Decl *> 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<const Decl *> getLocalTopLevelDecls();
|
||||
|
||||
const std::vector<Diag> &getDiagnostics() const;
|
||||
|
||||
|
@ -103,11 +103,8 @@ private:
|
|||
ParsedAST(std::shared_ptr<const PreambleData> Preamble,
|
||||
std::unique_ptr<CompilerInstance> Clang,
|
||||
std::unique_ptr<FrontendAction> Action,
|
||||
std::vector<const Decl *> TopLevelDecls, std::vector<Diag> Diags,
|
||||
std::vector<Inclusion> Inclusions);
|
||||
|
||||
private:
|
||||
void ensurePreambleDeclsDeserialized();
|
||||
std::vector<const Decl *> LocalTopLevelDecls,
|
||||
std::vector<Diag> Diags, std::vector<Inclusion> Inclusions);
|
||||
|
||||
// In-memory preambles must outlive the AST, it is important that this member
|
||||
// goes before Clang and Action.
|
||||
|
@ -122,8 +119,9 @@ private:
|
|||
|
||||
// Data, stored after parsing.
|
||||
std::vector<Diag> Diags;
|
||||
std::vector<const Decl *> TopLevelDecls;
|
||||
bool PreambleDeclsDeserialized;
|
||||
// Top-level decls inside the current file. Not that this does not include
|
||||
// top-level decls from the preamble.
|
||||
std::vector<const Decl *> LocalTopLevelDecls;
|
||||
std::vector<Inclusion> Inclusions;
|
||||
};
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ IdentifiedSymbol getSymbolAtPosition(ParsedAST &AST, SourceLocation Pos) {
|
|||
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 @@ std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
|
|||
IndexOpts.SystemSymbolFilter =
|
||||
index::IndexingOptions::SystemSymbolFilterKind::All;
|
||||
IndexOpts.IndexFunctionLocals = true;
|
||||
indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
|
||||
indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
|
||||
DocHighlightsFinder, IndexOpts);
|
||||
|
||||
return DocHighlightsFinder.takeHighlights();
|
||||
|
|
|
@ -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 Symbol &findSymbol(const SymbolSlab &Slab, llvm::StringRef QName) {
|
|||
}
|
||||
|
||||
const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) {
|
||||
const NamedDecl *Result = nullptr;
|
||||
for (const Decl *D : AST.getTopLevelDecls()) {
|
||||
auto *ND = dyn_cast<NamedDecl>(D);
|
||||
if (!ND || ND->getNameAsString() != QName)
|
||||
continue;
|
||||
if (Result) {
|
||||
ADD_FAILURE() << "Multiple Decls named " << QName;
|
||||
assert(false && "QName is not unique");
|
||||
}
|
||||
Result = ND;
|
||||
llvm::SmallVector<llvm::StringRef, 4> 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<DeclContext>(LookupDecl(*Scope, *NameIt));
|
||||
}
|
||||
if (!Result) {
|
||||
ADD_FAILURE() << "No Decl named " << QName << " in AST";
|
||||
assert(false && "No Decl with QName");
|
||||
}
|
||||
return *Result;
|
||||
return LookupDecl(*Scope, Components.back());
|
||||
}
|
||||
|
||||
} // namespace clangd
|
||||
|
|
Loading…
Reference in New Issue