nridge updated this revision to Diff 316000. nridge added a comment. Address review comments
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/FindTarget.h 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 | Rel::Underlying}); +} + TEST_F(TargetDeclTest, ObjC) { Flags = {"-xobjective-c"}; Code = R"cpp( Index: clang-tools-extra/clangd/FindTarget.h =================================================================== --- clang-tools-extra/clangd/FindTarget.h +++ clang-tools-extra/clangd/FindTarget.h @@ -194,6 +194,9 @@ S &= Other.S; return *this; } + bool contains(DeclRelationSet Other) const { + return (S & Other.S) == Other.S; + } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet); }; // The above operators can't be looked up if both sides are enums. 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; + llvm::SmallDenseMap<const Decl *, RelSet> Seen; RelSet Flags; template <typename T> void debug(T &Node, RelSet Flags) { @@ -359,6 +360,15 @@ 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 with all flags in Flags. + auto Res = Seen.try_emplace(D); + if (!Res.second && Res.first->second.contains(Flags)) + return; + Res.first->second |= Flags; + 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 | Rel::Underlying}); +} + TEST_F(TargetDeclTest, ObjC) { Flags = {"-xobjective-c"}; Code = R"cpp( Index: clang-tools-extra/clangd/FindTarget.h =================================================================== --- clang-tools-extra/clangd/FindTarget.h +++ clang-tools-extra/clangd/FindTarget.h @@ -194,6 +194,9 @@ S &= Other.S; return *this; } + bool contains(DeclRelationSet Other) const { + return (S & Other.S) == Other.S; + } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet); }; // The above operators can't be looked up if both sides are enums. 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; + llvm::SmallDenseMap<const Decl *, RelSet> Seen; RelSet Flags; template <typename T> void debug(T &Node, RelSet Flags) { @@ -359,6 +360,15 @@ 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 with all flags in Flags. + auto Res = Seen.try_emplace(D); + if (!Res.second && Res.first->second.contains(Flags)) + return; + Res.first->second |= Flags; + 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