https://github.com/HighCommander4 created 
https://github.com/llvm/llvm-project/pull/212094

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

>From 89e5445d1d572213a3f36bb7bda3362325a436b6 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 +++--
 3 files changed, 36 insertions(+), 3 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;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to