diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -35,6 +35,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include +#include namespace clang { namespace clangd { @@ -134,6 +135,35 @@ return FirstArg.getAsType().getTypePtrOrNull(); } +const NamedDecl *getTemplatePattern(const NamedDecl *D) { + if (const CXXRecordDecl *CRD = dyn_cast(D)) { + return CRD->getTemplateInstantiationPattern(); + } else if (const FunctionDecl *FD = dyn_cast(D)) { + return FD->getTemplateInstantiationPattern(); + } else if (auto *VD = dyn_cast(D)) { + // Hmm: getTIP returns its arg if it's not an instantiation?! + VarDecl *T = VD->getTemplateInstantiationPattern(); + return (T == D) ? nullptr : T; + } else if (const auto *ED = dyn_cast(D)) { + return ED->getInstantiatedFromMemberEnum(); + } else if (isa(D) || isa(D)) { + if (const auto *Parent = llvm::dyn_cast(D->getDeclContext())) + if (const DeclContext *ParentPat = + dyn_cast_or_null(getTemplatePattern(Parent))) + for (const NamedDecl *BaseND : ParentPat->lookup(D->getDeclName())) + if (!BaseND->isImplicit() && BaseND->getKind() == D->getKind()) + return BaseND; + } else if (const auto *ECD = dyn_cast(D)) { + if (const auto *ED = dyn_cast(ECD->getDeclContext())) { + if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { + for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) + return BaseECD; + } + } + } + return nullptr; +} + // TargetFinder locates the entities that an AST node refers to. // // Typically this is (possibly) one declaration and (possibly) one type, but @@ -167,37 +197,12 @@ struct TargetFinder { using RelSet = DeclRelationSet; using Rel = DeclRelation; - llvm::SmallDenseMap Decls; - RelSet Flags; - static const NamedDecl *getTemplatePattern(const NamedDecl *D) { - if (const CXXRecordDecl *CRD = dyn_cast(D)) { - return CRD->getTemplateInstantiationPattern(); - } else if (const FunctionDecl *FD = dyn_cast(D)) { - return FD->getTemplateInstantiationPattern(); - } else if (auto *VD = dyn_cast(D)) { - // Hmm: getTIP returns its arg if it's not an instantiation?! - VarDecl *T = VD->getTemplateInstantiationPattern(); - return (T == D) ? nullptr : T; - } else if (const auto *ED = dyn_cast(D)) { - return ED->getInstantiatedFromMemberEnum(); - } else if (isa(D) || isa(D)) { - if (const auto *Parent = llvm::dyn_cast(D->getDeclContext())) - if (const DeclContext *ParentPat = - dyn_cast_or_null(getTemplatePattern(Parent))) - for (const NamedDecl *BaseND : ParentPat->lookup(D->getDeclName())) - if (!BaseND->isImplicit() && BaseND->getKind() == D->getKind()) - return BaseND; - } else if (const auto *ECD = dyn_cast(D)) { - if (const auto *ED = dyn_cast(ECD->getDeclContext())) { - if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { - for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) - return BaseECD; - } - } - } - return nullptr; - } +private: + llvm::SmallDenseMap> + Decls; + RelSet Flags; template void debug(T &Node, RelSet Flags) { dlog("visit [{0}] {1}", Flags, @@ -207,10 +212,22 @@ void report(const NamedDecl *D, RelSet Flags) { dlog("--> [{0}] {1}", Flags, nodeToString(ast_type_traits::DynTypedNode::create(*D))); - Decls[D] |= Flags; + auto It = Decls.try_emplace(D, std::make_pair(Flags, Decls.size())); + // If already exists, update the flags. + if (!It.second) + It.first->second.first |= Flags; } public: + llvm::SmallVector, 1> takeDecls() const { + using ValTy = std::pair; + llvm::SmallVector Result; + Result.resize(Decls.size()); + for (const auto &Elem : Decls) + Result[Elem.second.second] = {Elem.first, Elem.second.first}; + return Result; + } + void add(const Decl *Dcl, RelSet Flags) { const NamedDecl *D = llvm::dyn_cast(Dcl); if (!D) @@ -485,7 +502,7 @@ else if (const CXXCtorInitializer *CCI = N.get()) Finder.add(CCI, Flags); - return {Finder.Decls.begin(), Finder.Decls.end()}; + return Finder.takeDecls(); } llvm::SmallVector