From 100dbd15624c1ac8d1210e7748462e20fed9a9d9 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sun, 19 Jul 2020 02:26:49 -0400 Subject: [PATCH] [clangd] Handle deduction guides in TargetFinder and ExplicitReferenceCollector Summary: Fixes https://github.com/clangd/clangd/issues/463. Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D84122 --- clang-tools-extra/clangd/FindTarget.cpp | 11 ++++ .../clangd/unittests/FindTargetTests.cpp | 62 +++++++++++++++++----- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 627f40c8543..c2887f3306f 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -302,6 +302,8 @@ public: // Record the underlying decl instead, if allowed. D = USD->getTargetDecl(); Flags |= Rel::Underlying; // continue with the underlying decl. + } else if (const auto *DG = dyn_cast(D)) { + D = DG->getDeducedTemplate(); } if (const Decl *Pat = getTemplatePattern(D)) { @@ -659,6 +661,15 @@ llvm::SmallVector refInDecl(const Decl *D) { /*IsDecl=*/true, {ND}}); } + + void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *DG) { + // The class template name in a deduction guide targets the class + // template. + Refs.push_back(ReferenceLoc{DG->getQualifierLoc(), + DG->getNameInfo().getLoc(), + /*IsDecl=*/false, + {DG->getDeducedTemplate()}}); + } }; Visitor V; diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index bf5cc62411b..fa8f4935b1d 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -376,6 +376,8 @@ TEST_F(TargetDeclTest, ClassTemplate) { {"template<> class Foo", Rel::TemplateInstantiation}, {"template class Foo", Rel::TemplatePattern}); + Flags.push_back("-std=c++17"); // for CTAD tests + Code = R"cpp( // Class template argument deduction template @@ -386,9 +388,20 @@ TEST_F(TargetDeclTest, ClassTemplate) { [[Test]] a(5); } )cpp"; - Flags.push_back("-std=c++17"); EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc", {"struct Test", Rel::TemplatePattern}); + + Code = R"cpp( + // Deduction guide + template + struct Test { + template + Test(I, I); + }; + template + [[Test]](I, I) -> Test; + )cpp"; + EXPECT_DECLS("CXXDeductionGuideDecl", {"template struct Test"}); } TEST_F(TargetDeclTest, Concept) { @@ -792,8 +805,8 @@ TEST_F(FindExplicitReferencesTest, All) { goto $1^ten; } )cpp", - "0: targets = {ten}, decl\n" - "1: targets = {ten}\n"}, + "0: targets = {ten}, decl\n" + "1: targets = {ten}\n"}, // Simple templates. {R"cpp( template struct vector { using value_type = T; }; @@ -1295,7 +1308,7 @@ TEST_F(FindExplicitReferencesTest, All) { "6: targets = {bar}, decl\n" "7: targets = {foo()::Bar::Foo}\n" "8: targets = {foo()::Baz::Field}\n"}, - {R"cpp( + {R"cpp( template void crash(T); template @@ -1305,10 +1318,9 @@ TEST_F(FindExplicitReferencesTest, All) { )cpp", "0: targets = {crash}\n" "1: targets = {}\n" - "2: targets = {T}\n" - }, - // unknown template name should not crash. - {R"cpp( + "2: targets = {T}\n"}, + // unknown template name should not crash. + {R"cpp( template