Author: Kadir Cetinkaya Date: 2020-01-16T14:47:28+01:00 New Revision: d54d71b67e602674a255e299a22fe31dee1f3619
URL: https://github.com/llvm/llvm-project/commit/d54d71b67e602674a255e299a22fe31dee1f3619 DIFF: https://github.com/llvm/llvm-project/commit/d54d71b67e602674a255e299a22fe31dee1f3619.diff LOG: [clangd] Make output order of allTargetDecls deterministic Summary: Makes use of insertion order to stabilize output for multiple decls. Fixes https://bugs.llvm.org/show_bug.cgi?id=44564 Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, usaxena95, cfe-commits, aemerson Tags: #clang Differential Revision: https://reviews.llvm.org/D72826 Added: Modified: clang-tools-extra/clangd/FindTarget.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index d8ce0b69283f..82a2e8c27d56 100644 --- 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 <utility> +#include <vector> namespace clang { namespace clangd { @@ -134,6 +135,35 @@ const Type *getPointeeType(const Type *T) { return FirstArg.getAsType().getTypePtrOrNull(); } +const NamedDecl *getTemplatePattern(const NamedDecl *D) { + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { + return CRD->getTemplateInstantiationPattern(); + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + return FD->getTemplateInstantiationPattern(); + } else if (auto *VD = dyn_cast<VarDecl>(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<EnumDecl>(D)) { + return ED->getInstantiatedFromMemberEnum(); + } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) { + if (const auto *Parent = llvm::dyn_cast<NamedDecl>(D->getDeclContext())) + if (const DeclContext *ParentPat = + dyn_cast_or_null<DeclContext>(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<EnumConstantDecl>(D)) { + if (const auto *ED = dyn_cast<EnumDecl>(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 @@ const Type *getPointeeType(const Type *T) { struct TargetFinder { using RelSet = DeclRelationSet; using Rel = DeclRelation; - llvm::SmallDenseMap<const NamedDecl *, RelSet> Decls; - RelSet Flags; - static const NamedDecl *getTemplatePattern(const NamedDecl *D) { - if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { - return CRD->getTemplateInstantiationPattern(); - } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - return FD->getTemplateInstantiationPattern(); - } else if (auto *VD = dyn_cast<VarDecl>(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<EnumDecl>(D)) { - return ED->getInstantiatedFromMemberEnum(); - } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) { - if (const auto *Parent = llvm::dyn_cast<NamedDecl>(D->getDeclContext())) - if (const DeclContext *ParentPat = - dyn_cast_or_null<DeclContext>(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<EnumConstantDecl>(D)) { - if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) { - if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { - for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) - return BaseECD; - } - } - } - return nullptr; - } +private: + llvm::SmallDenseMap<const NamedDecl *, + std::pair<RelSet, /*InsertionOrder*/ size_t>> + Decls; + RelSet Flags; template <typename T> void debug(T &Node, RelSet Flags) { dlog("visit [{0}] {1}", Flags, @@ -207,10 +212,22 @@ struct TargetFinder { 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<std::pair<const NamedDecl *, RelSet>, 1> takeDecls() const { + using ValTy = std::pair<const NamedDecl *, RelSet>; + llvm::SmallVector<ValTy, 1> 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<NamedDecl>(Dcl); if (!D) @@ -485,7 +502,7 @@ allTargetDecls(const ast_type_traits::DynTypedNode &N) { else if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) Finder.add(CCI, Flags); - return {Finder.Decls.begin(), Finder.Decls.end()}; + return Finder.takeDecls(); } llvm::SmallVector<const NamedDecl *, 1> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits