diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -580,6 +580,11 @@ {D->getAliasedNamespace()}}); } + void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *TD) { + // {Class,Function,Var,TypeAlias}TemplateDecls are visited as part of the + // NamedDecl below, we skip them here to not visit them twice. + } + void VisitNamedDecl(const NamedDecl *ND) { // FIXME: decide on how to surface destructors when we need them. if (llvm::isa(ND)) diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -733,18 +733,17 @@ {R"cpp( namespace foo { template - class $1^$2^Bar { - ~$3^Bar(); - void $4^f($5^Bar); + class $1^Bar { + ~$2^Bar(); + void $3^f($4^Bar); }; } )cpp", "0: targets = {foo::Bar::T}, decl\n" "1: targets = {foo::Bar}, decl\n" - "2: targets = {foo::Bar}, decl\n" - "3: targets = {foo::Bar}\n" - "4: targets = {foo::Bar::f}, decl\n" - "5: targets = {foo::Bar}\n"}, + "2: targets = {foo::Bar}\n" + "3: targets = {foo::Bar::f}, decl\n" + "4: targets = {foo::Bar}\n"}, // MemberExpr should know their using declaration. {R"cpp( struct X { void func(int); }; @@ -1044,7 +1043,47 @@ } )cpp", "0: targets = {Test}\n" - "1: targets = {a}, decl\n"}}; + "1: targets = {a}, decl\n"}, + // Templates + {R"cpp( + namespace foo { + template + class $1^Bar {}; + } + )cpp", + "0: targets = {foo::Bar::T}, decl\n" + "1: targets = {foo::Bar}, decl\n"}, + // Templates + {R"cpp( + namespace foo { + template + void $1^func(); + } + )cpp", + "0: targets = {T}, decl\n" + "1: targets = {foo::func}, decl\n"}, + // Templates + {R"cpp( + namespace foo { + template + $1^T $2^x; + } + )cpp", + "0: targets = {foo::T}, decl\n" + "1: targets = {foo::T}\n" + "2: targets = {foo::x}, decl\n"}, + // Templates + {R"cpp( + template class vector {}; + namespace foo { + template + using $1^V = $2^vector<$3^T>; + } + )cpp", + "0: targets = {foo::T}, decl\n" + "1: targets = {foo::V}, decl\n" + "2: targets = {vector}\n" + "3: targets = {foo::T}\n"}}; for (const auto &C : Cases) { llvm::StringRef ExpectedCode = C.first;