hokein created this revision. hokein added a reviewer: sammccall. Herald added subscribers: usaxena95, kadircet, arphaman. Herald added a project: All. hokein requested review of this revision. Herald added subscribers: MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
Add supports in FindTarget and IncludeCleaner. This would improve AST-based features on a tempalte which is found via a using declaration. For example, go-to-def on `vect^or<int> v;` gives us the location of `using std::vector`, which was not previously. Base on https://reviews.llvm.org/D123127 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D123212 Files: clang-tools-extra/clangd/FindTarget.cpp clang-tools-extra/clangd/IncludeCleaner.cpp clang-tools-extra/clangd/unittests/FindTargetTests.cpp clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -78,9 +78,17 @@ "using namespace ns;", }, { + // Refs from UsingTypeLoc and implicit constructor! "struct ^A {}; using B = A; using ^C = B;", "C a;", }, + {"namespace ns { template<typename T> class A {}; } using ns::^A;", + "A<int>* a;"}, + {"namespace ns { template<typename T> class A {}; } using ns::^A;", + "template <template <typename> class T> class X {}; X<A> x;"}, + {"namespace ns { template<typename T> struct ^A { ^A(T); }; } using " + "ns::^A;", + "A x(123);"}, { "typedef bool ^Y; template <typename T> struct ^X {};", "X<Y> x;", @@ -226,6 +234,7 @@ TU.Code = T.MainCode; Annotations Header(T.HeaderCode); TU.HeaderCode = Header.code().str(); + TU.ExtraArgs.push_back("-std=c++17"); auto AST = TU.build(); std::vector<Position> Points; Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -229,6 +229,44 @@ )cpp"; EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::waldo", Rel::Alias}, {"void waldo()"}); + + Code = R"cpp( + namespace ns { + template<typename T> class S {}; + } + + using ns::S; + + template<typename T> + using A = [[S]]<T>; + )cpp"; + EXPECT_DECLS("TemplateSpecializationTypeLoc", {"using ns::S", Rel::Alias}, + {"template <typename T> class S"}); + + Code = R"cpp( + namespace ns { + template<typename T> class S {}; + } + + using ns::S; + template <template <typename> class T> class X {}; + using B = X<[[S]]>; + )cpp"; + EXPECT_DECLS("TemplateArgumentLoc", {"using ns::S", Rel::Alias}, + {"template <typename T> class S"}); + + Code = R"cpp( + namespace ns { + template<typename T> class S { public: S(T); }; + } + + using ns::S; + [[S]] s(123); + )cpp"; + Flags.push_back("-std=c++17"); // For CTAD feature. + EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc", + {"using ns::S", Rel::Alias}, {"template <typename T> class S"}, + {"class S", Rel::TemplatePattern}); } TEST_F(TargetDeclTest, BaseSpecifier) { Index: clang-tools-extra/clangd/IncludeCleaner.cpp =================================================================== --- clang-tools-extra/clangd/IncludeCleaner.cpp +++ clang-tools-extra/clangd/IncludeCleaner.cpp @@ -73,11 +73,23 @@ } bool VisitTemplateSpecializationType(TemplateSpecializationType *TST) { + if (const auto *UTN = TST->getTemplateName().getAsUsingTemplateName()) { + add(UTN->getFoundDecl()); + return true; + } add(TST->getTemplateName().getAsTemplateDecl()); // Primary template. add(TST->getAsCXXRecordDecl()); // Specialization return true; } + // There is no VisitTemplateName in RAV, thus we override the Traverse version + // to handle the UsingTemplateName case. + bool TraverseTemplateName(TemplateName TN) { + if (const auto *UTN = TN.getAsUsingTemplateName()) + add(UTN->getFoundDecl()); + return Base::TraverseTemplateName(TN); + } + bool VisitUsingType(UsingType *UT) { add(UT->getFoundDecl()); return true; Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -384,11 +384,14 @@ } void VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *DTST) { + if (const auto *UTN = DTST->getTemplateName().getAsUsingTemplateName()) + Outer.add(UTN->getFoundDecl(), Flags); + // FIXME: This is a workaround for https://llvm.org/PR42914, // which is causing DTST->getDeducedType() to be empty. We // fall back to the template pattern and miss the instantiation // even when it's known in principle. Once that bug is fixed, - // this method can be removed (the existing handling in + // the following code can be removed (the existing handling in // VisitDeducedType() is sufficient). if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); @@ -440,6 +443,9 @@ // class template specializations have a (specialized) CXXRecordDecl. else if (const CXXRecordDecl *RD = TST->getAsCXXRecordDecl()) Outer.add(RD, Flags); // add(Decl) will despecialize if needed. + else if (const auto *UTN = + TST->getTemplateName().getAsUsingTemplateName()) + Outer.add(UTN->getFoundDecl(), Flags); else { // fallback: the (un-specialized) declaration from primary template. if (auto *TD = TST->getTemplateName().getAsTemplateDecl()) @@ -508,6 +514,9 @@ Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) { report(TD, Flags); } + if (const auto *UTN = + Arg.getAsTemplateOrTemplatePattern().getAsUsingTemplateName()) + add(UTN->getFoundDecl(), Flags); } } };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits