diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -108,6 +108,7 @@ return CompletionItemKind::Function; case SK::Variable: case SK::Parameter: + case SK::TemplateParm: return CompletionItemKind::Variable; case SK::Field: return CompletionItemKind::Field; diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -14,6 +14,7 @@ #include "Logger.h" #include "URI.h" #include "clang/Basic/LLVM.h" +#include "clang/Index/IndexSymbol.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -261,6 +262,7 @@ case index::SymbolKind::ConversionFunction: return SymbolKind::Function; case index::SymbolKind::Parameter: + case index::SymbolKind::TemplateParm: return SymbolKind::Variable; case index::SymbolKind::Using: return SymbolKind::Namespace; diff --git a/clang-tools-extra/clangd/Quality.cpp b/clang-tools-extra/clangd/Quality.cpp --- a/clang-tools-extra/clangd/Quality.cpp +++ b/clang-tools-extra/clangd/Quality.cpp @@ -147,6 +147,7 @@ case index::SymbolKind::Field: case index::SymbolKind::EnumConstant: case index::SymbolKind::Parameter: + case index::SymbolKind::TemplateParm: return SymbolQualitySignals::Variable; case index::SymbolKind::Using: case index::SymbolKind::Module: diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -573,6 +573,40 @@ // pattern. HI.Documentation = "comment from primary"; }}, + {// Template Type Parameter + R"cpp( + template void foo(); + )cpp", + [](HoverInfo &HI) { + HI.Name = "T"; + HI.Kind = index::SymbolKind::TemplateParm; + HI.NamespaceScope = ""; + HI.Definition = "typename T = int"; + HI.LocalScope = "foo::"; + }}, + {// TemplateTemplate Type Parameter + R"cpp( + template class [[^T]]> void foo(); + )cpp", + [](HoverInfo &HI) { + HI.Name = "T"; + HI.Kind = index::SymbolKind::TemplateParm; + HI.NamespaceScope = ""; + HI.Definition = "template class T"; + HI.LocalScope = "foo::"; + }}, + {// NonType Template Parameter + R"cpp( + template void foo(); + )cpp", + [](HoverInfo &HI) { + HI.Name = "T"; + HI.Kind = index::SymbolKind::TemplateParm; + HI.NamespaceScope = ""; + HI.Definition = "int T = 5"; + HI.LocalScope = "foo::"; + HI.Type = "int"; + }}, }; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Code); diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -6253,7 +6253,8 @@ CXIdxEntity_CXXDestructor = 23, CXIdxEntity_CXXConversionFunction = 24, CXIdxEntity_CXXTypeAlias = 25, - CXIdxEntity_CXXInterface = 26 + CXIdxEntity_CXXInterface = 26, + CXIdxEntity_CXXTemplateParm = 27 } CXIdxEntityKind; diff --git a/clang/include/clang/Index/IndexSymbol.h b/clang/include/clang/Index/IndexSymbol.h --- a/clang/include/clang/Index/IndexSymbol.h +++ b/clang/include/clang/Index/IndexSymbol.h @@ -54,6 +54,7 @@ Parameter, Using, + TemplateParm, }; enum class SymbolLanguage : uint8_t { diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp --- a/clang/lib/Index/IndexSymbol.cpp +++ b/clang/lib/Index/IndexSymbol.cpp @@ -357,6 +357,11 @@ case Decl::VarTemplate: llvm_unreachable("variables handled before"); break; + case Decl::TemplateTypeParm: + case Decl::TemplateTemplateParm: + case Decl::NonTypeTemplateParm: + Info.Kind = SymbolKind::TemplateParm; + break; // Other decls get the 'unknown' kind. default: break; @@ -517,6 +522,7 @@ case SymbolKind::ConversionFunction: return "conversion-func"; case SymbolKind::Parameter: return "param"; case SymbolKind::Using: return "using"; + case SymbolKind::TemplateParm: return "template-param"; } llvm_unreachable("invalid symbol kind"); } diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -3471,6 +3471,7 @@ case CXIdxEntity_CXXConversionFunction: return "conversion-func"; case CXIdxEntity_CXXTypeAlias: return "type-alias"; case CXIdxEntity_CXXInterface: return "c++-__interface"; + case CXIdxEntity_CXXTemplateParm: return "c++-template-parm"; } assert(0 && "Garbage entity kind"); return 0; diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -1284,6 +1284,7 @@ case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor; case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction; case SymbolKind::Parameter: return CXIdxEntity_Variable; + case SymbolKind::TemplateParm: return CXIdxEntity_CXXTemplateParm; } llvm_unreachable("invalid symbol kind"); } diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp --- a/clang/unittests/Index/IndexTests.cpp +++ b/clang/unittests/Index/IndexTests.cpp @@ -248,9 +248,12 @@ Opts.IndexTemplateParameters = true; Index->Symbols.clear(); tooling::runToolOnCode(std::make_unique(Index, Opts), Code); - EXPECT_THAT(Index->Symbols, - AllOf(Contains(QName("Foo::T")), Contains(QName("Foo::I")), - Contains(QName("Foo::C")), Contains(QName("Foo::NoRef")))); + EXPECT_THAT( + Index->Symbols, + AllOf(Contains(AllOf(QName("Foo::T"), Kind(SymbolKind::TemplateParm))), + Contains(AllOf(QName("Foo::I"), Kind(SymbolKind::TemplateParm))), + Contains(AllOf(QName("Foo::C"), Kind(SymbolKind::TemplateParm))), + Contains(QName("Foo::NoRef")))); } TEST(IndexTest, UsingDecls) {