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,38 +197,12 @@ struct TargetFinder { using RelSet = DeclRelationSet; using Rel = DeclRelation; + +private: + llvm::SmallDenseMap InsertionOrder; 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; - } - template void debug(T &Node, RelSet Flags) { dlog("visit [{0}] {1}", Flags, nodeToString(ast_type_traits::DynTypedNode::create(Node))); @@ -207,10 +211,24 @@ 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, Flags); + if (It.second) + InsertionOrder[D] = InsertionOrder.size(); + else + It.first->second |= Flags; } public: + llvm::SmallVector, 1> takeDecls() const { + using ValTy = std::pair; + llvm::SmallVector Result{Decls.begin(), Decls.end()}; + llvm::sort(Result, [this](const ValTy &LHS, const ValTy &RHS) { + return InsertionOrder.lookup(LHS.first) < + InsertionOrder.lookup(RHS.first); + }); + return Result; + } + void add(const Decl *Dcl, RelSet Flags) { const NamedDecl *D = llvm::dyn_cast(Dcl); if (!D) @@ -485,7 +503,7 @@ else if (const CXXCtorInitializer *CCI = N.get()) Finder.add(CCI, Flags); - return {Finder.Decls.begin(), Finder.Decls.end()}; + return Finder.takeDecls(); } llvm::SmallVector