nridge updated this revision to Diff 315689. nridge marked an inline comment as done. nridge added a comment.
Use map lookup instead of iteration Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D94382/new/ https://reviews.llvm.org/D94382 Files: clang-tools-extra/clangd/FindTarget.cpp clang-tools-extra/clangd/unittests/FindTargetTests.cpp Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -787,6 +787,47 @@ "template <typename> struct B"); } +TEST_F(TargetDeclTest, TypedefCascade) { + Code = R"cpp( + struct C { + using type = int; + }; + struct B { + using type = C::type; + }; + struct A { + using type = B::type; + }; + A::[[type]] waldo; + )cpp"; + EXPECT_DECLS("TypedefTypeLoc", + {"using type = int", Rel::Alias | Rel::Underlying}, + {"using type = C::type", Rel::Alias | Rel::Underlying}, + {"using type = B::type", Rel::Alias}); +} + +TEST_F(TargetDeclTest, RecursiveTemplate) { + Flags.push_back("-std=c++20"); // the test case uses concepts + + Code = R"cpp( + template <typename T> + concept Leaf = false; + + template <typename Tree> + struct descend_left { + using type = typename descend_left<typename Tree::left>::[[type]]; + }; + + template <Leaf Tree> + struct descend_left<Tree> { + using type = typename Tree::value; + }; + )cpp"; + EXPECT_DECLS("DependentNameTypeLoc", + {"using type = typename descend_left<typename Tree::left>::type", + Rel::Alias}); +} + TEST_F(TargetDeclTest, ObjC) { Flags = {"-xobjective-c"}; Code = R"cpp( Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -330,6 +330,7 @@ llvm::SmallDenseMap<const NamedDecl *, std::pair<RelSet, /*InsertionOrder*/ size_t>> Decls; + const Decl *CurrentlyProcessing = nullptr; RelSet Flags; template <typename T> void debug(T &Node, RelSet Flags) { @@ -354,11 +355,23 @@ return Result; } + bool seenDecl(const NamedDecl *D) const { + return CurrentlyProcessing == D || Decls.count(D) != 0; + } + void add(const Decl *Dcl, RelSet Flags) { const NamedDecl *D = llvm::dyn_cast_or_null<NamedDecl>(Dcl); if (!D) return; debug(*D, Flags); + + // Avoid recursion (which can arise in the presence of heuristic + // resolution of dependent names) by exiting early if we have + // already seen this decl. + if (seenDecl(D)) + return; + CurrentlyProcessing = D; + if (const UsingDirectiveDecl *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D)) D = UDD->getNominatedNamespaceAsWritten();
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -787,6 +787,47 @@ "template <typename> struct B"); } +TEST_F(TargetDeclTest, TypedefCascade) { + Code = R"cpp( + struct C { + using type = int; + }; + struct B { + using type = C::type; + }; + struct A { + using type = B::type; + }; + A::[[type]] waldo; + )cpp"; + EXPECT_DECLS("TypedefTypeLoc", + {"using type = int", Rel::Alias | Rel::Underlying}, + {"using type = C::type", Rel::Alias | Rel::Underlying}, + {"using type = B::type", Rel::Alias}); +} + +TEST_F(TargetDeclTest, RecursiveTemplate) { + Flags.push_back("-std=c++20"); // the test case uses concepts + + Code = R"cpp( + template <typename T> + concept Leaf = false; + + template <typename Tree> + struct descend_left { + using type = typename descend_left<typename Tree::left>::[[type]]; + }; + + template <Leaf Tree> + struct descend_left<Tree> { + using type = typename Tree::value; + }; + )cpp"; + EXPECT_DECLS("DependentNameTypeLoc", + {"using type = typename descend_left<typename Tree::left>::type", + Rel::Alias}); +} + TEST_F(TargetDeclTest, ObjC) { Flags = {"-xobjective-c"}; Code = R"cpp( Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -330,6 +330,7 @@ llvm::SmallDenseMap<const NamedDecl *, std::pair<RelSet, /*InsertionOrder*/ size_t>> Decls; + const Decl *CurrentlyProcessing = nullptr; RelSet Flags; template <typename T> void debug(T &Node, RelSet Flags) { @@ -354,11 +355,23 @@ return Result; } + bool seenDecl(const NamedDecl *D) const { + return CurrentlyProcessing == D || Decls.count(D) != 0; + } + void add(const Decl *Dcl, RelSet Flags) { const NamedDecl *D = llvm::dyn_cast_or_null<NamedDecl>(Dcl); if (!D) return; debug(*D, Flags); + + // Avoid recursion (which can arise in the presence of heuristic + // resolution of dependent names) by exiting early if we have + // already seen this decl. + if (seenDecl(D)) + return; + CurrentlyProcessing = D; + if (const UsingDirectiveDecl *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D)) D = UDD->getNominatedNamespaceAsWritten();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits