https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/212094
>From bc4e97068596c8d9e057cf8abce5059d180e2e53 Mon Sep 17 00:00:00 2001 From: Nathan Ridge <[email protected]> Date: Sun, 26 Jul 2026 02:44:54 -0400 Subject: [PATCH] [clangd] Respect ArgumentLists for struct templates Also fix a bug in index::getSymbolKind where the returned symbol kind would be Class for a struct template. Fixes https://github.com/clangd/clangd/issues/2616 --- clang-tools-extra/clangd/CodeComplete.cpp | 1 + .../clangd/unittests/CodeCompleteTests.cpp | 30 ++++++++++++++++++- clang/lib/Index/IndexSymbol.cpp | 8 +++-- clang/test/Index/index-refs.cpp | 2 +- .../Index/index-template-specialization.cpp | 6 ++-- 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 5f70dfe0dfd71..80091d3a48b33 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -643,6 +643,7 @@ struct CodeCompletionBuilder { // 'CompletionItemKind::Interface' matches template type aliases. if (Completion.Kind == CompletionItemKind::Interface || Completion.Kind == CompletionItemKind::Class || + Completion.Kind == CompletionItemKind::Struct || Completion.Kind == CompletionItemKind::Variable) { if (Snippet->front() != '<') return *Snippet; // Not an arg snippet? diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5fad022cfe57b..4c1cab7b11e60 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -841,7 +841,7 @@ TEST(CompletionTest, Kinds) { EXPECT_THAT( Results.Completions, UnorderedElementsAre( - AllOf(named("complete_class"), kind(CompletionItemKind::Class)), + AllOf(named("complete_class"), kind(CompletionItemKind::Struct)), AllOf(named("complete_function"), kind(CompletionItemKind::Function)), AllOf(named("complete_type_alias"), kind(CompletionItemKind::Interface)), @@ -2996,6 +2996,8 @@ TEST(CompletionTest, ArgumentListsPolicy) { template <class T> class foo_class{}; template <class T> + struct foo_struct{}; + template <class T> using foo_alias = T**; template <class T> T foo_var = T{}; @@ -3004,8 +3006,34 @@ TEST(CompletionTest, ArgumentListsPolicy) { EXPECT_THAT( Results.Completions, UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix("<$0>")), + AllOf(named("foo_struct"), snippetSuffix("<$0>")), + AllOf(named("foo_alias"), snippetSuffix("<$0>")), + AllOf(named("foo_var"), snippetSuffix("<$0>")))); + } + { + const char *Header = R"cpp( + template <class T> + class foo_class{}; + template <class T> + struct foo_struct{}; + template <class T> + using foo_alias = T**; + template <class T> + T foo_var = T{}; + )cpp"; + auto Index = TestTU::withHeaderCode(Header).index(); + Opts.Index = Index.get(); + auto Results = completions( + R"cpp( + void f() { foo_^ })cpp", + {}, Opts); + EXPECT_THAT( + Results.Completions, + UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix("<$0>")), + AllOf(named("foo_struct"), snippetSuffix("<$0>")), AllOf(named("foo_alias"), snippetSuffix("<$0>")), AllOf(named("foo_var"), snippetSuffix("<$0>")))); + Opts.Index = nullptr; } { auto Results = completions( diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp index 9b7fee421bdfe..5131b321dedb2 100644 --- a/clang/lib/Index/IndexSymbol.cpp +++ b/clang/lib/Index/IndexSymbol.cpp @@ -302,11 +302,15 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Lang = SymbolLanguage::CXX; break; } - case Decl::ClassTemplate: - Info.Kind = SymbolKind::Class; + case Decl::ClassTemplate: { + const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(D); + Info.Kind = CTD->getTemplatedDecl()->getTagKind() == TagTypeKind::Struct + ? SymbolKind::Struct + : SymbolKind::Class; Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; Info.Lang = SymbolLanguage::CXX; break; + } case Decl::FunctionTemplate: Info.Kind = SymbolKind::Function; Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; diff --git a/clang/test/Index/index-refs.cpp b/clang/test/Index/index-refs.cpp index 22eb7532ffad6..edd9049c79d07 100644 --- a/clang/test/Index/index-refs.cpp +++ b/clang/test/Index/index-refs.cpp @@ -105,7 +105,7 @@ int ginitlist[] = {EnumVal}; // CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 44:7 // CHECK-NEXT: [indexEntityReference]: kind: typedef | name: Foo | {{.*}} | loc: 44:11 -// CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8 +// CHECK: [indexDeclaration]: kind: struct-template | name: TS | {{.*}} | loc: 47:8 // CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8 // CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] /* when indexing implicit instantiations diff --git a/clang/test/Index/index-template-specialization.cpp b/clang/test/Index/index-template-specialization.cpp index d50da0f2d63d8..fcc6f3821923c 100644 --- a/clang/test/Index/index-template-specialization.cpp +++ b/clang/test/Index/index-template-specialization.cpp @@ -24,6 +24,6 @@ struct D : B<T> {}; // CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: Foo | USR: c:@ST>1#T@Foo // CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: f | USR: c:@ST>1#T@Foo@F@f#t0.0# -// CHECK: [indexDeclaration]: kind: c++-class-template | name: D -// CHECK-NEXT: <base>: kind: c++-class-template | name: B -// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: B +// CHECK: [indexDeclaration]: kind: struct-template | name: D +// CHECK-NEXT: <base>: kind: struct-template | name: B +// CHECK-NEXT: [indexEntityReference]: kind: struct-template | name: B _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
