Author: Mythreya Kuricheti
Date: 2026-01-10T22:02:15Z
New Revision: cd5d07e65cfd92d276bd1b704bcda12952065161

URL: 
https://github.com/llvm/llvm-project/commit/cd5d07e65cfd92d276bd1b704bcda12952065161
DIFF: 
https://github.com/llvm/llvm-project/commit/cd5d07e65cfd92d276bd1b704bcda12952065161.diff

LOG: [clangd] Add designator hints for parenthesis aggregate initialization 
(#170642)

Fixes clangd/clangd#2540

Added: 
    

Modified: 
    clang-tools-extra/clangd/InlayHints.cpp
    clang-tools-extra/clangd/unittests/InlayHintTests.cpp
    clang-tools-extra/docs/ReleaseNotes.rst

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/InlayHints.cpp 
b/clang-tools-extra/clangd/InlayHints.cpp
index 23bd02304a4fd..2290fbd98056d 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -699,6 +699,32 @@ class InlayHintVisitor : public 
RecursiveASTVisitor<InlayHintVisitor> {
     return InstantiatedFunction->getParamDecl(ParamIdx);
   }
 
+  bool VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
+    if (!Cfg.InlayHints.Designators)
+      return true;
+
+    if (const auto *CXXRecord = E->getType()->getAsCXXRecordDecl()) {
+      const auto &InitExprs = E->getUserSpecifiedInitExprs();
+
+      if (InitExprs.size() <= CXXRecord->getNumBases())
+        return true;
+
+      // Inherited members are first, skip hinting them for now.
+      // FIXME: '.base=' or 'base:' hint?
+      const auto &MemberInitExprs =
+          InitExprs.drop_front(CXXRecord->getNumBases());
+
+      // Then the fields in this record
+      for (const auto &[InitExpr, Field] :
+           llvm::zip(MemberInitExprs, CXXRecord->fields())) {
+        addDesignatorHint(InitExpr->getSourceRange(),
+                          "." + Field->getName().str());
+      }
+    }
+
+    return true;
+  }
+
   bool VisitInitListExpr(InitListExpr *Syn) {
     // We receive the syntactic form here (shouldVisitImplicitCode() is false).
     // This is the one we will ultimately attach designators to.

diff  --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp 
b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index feb4404b3d2bf..5552aa178a354 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -1147,20 +1147,6 @@ TEST(ParameterHints, CopyOrMoveConstructor) {
   )cpp");
 }
 
-TEST(ParameterHints, AggregateInit) {
-  // FIXME: This is not implemented yet, but it would be a natural
-  // extension to show member names as hints here.
-  assertParameterHints(R"cpp(
-    struct Point {
-      int x;
-      int y;
-    };
-    void bar() {
-      Point p{41, 42};
-    }
-  )cpp");
-}
-
 TEST(ParameterHints, UserDefinedLiteral) {
   // Do not hint call to user-defined literal operator.
   assertParameterHints(R"cpp(
@@ -1822,6 +1808,63 @@ TEST(DesignatorHints, NoCrash) {
                         ExpectedHint{".b=", "b"});
 }
 
+TEST(DesignatorHints, ParenInit) {
+  assertDesignatorHints(R"cpp(
+    struct S { 
+      int x;
+      int y;
+      int z; 
+    };
+    S s ($x[[1]], $y[[2+2]], $z[[4]]);
+  )cpp",
+                        ExpectedHint{".x=", "x"}, ExpectedHint{".y=", "y"},
+                        ExpectedHint{".z=", "z"});
+}
+
+TEST(DesignatorHints, ParenInitDerived) {
+  assertDesignatorHints(R"cpp(
+    struct S1 {
+      int a;
+      int b;
+    };
+
+    struct S2 : S1 { 
+      int c;
+      int d; 
+    };
+    S2 s2 ({$a[[0]], $b[[0]]}, $c[[0]], $d[[0]]);
+  )cpp",
+                        // ExpectedHint{"S1:", "S1"},
+                        ExpectedHint{".a=", "a"}, ExpectedHint{".b=", "b"},
+                        ExpectedHint{".c=", "c"}, ExpectedHint{".d=", "d"});
+}
+
+TEST(DesignatorHints, ParenInitTemplate) {
+  assertDesignatorHints(R"cpp(
+    template <typename T>
+    struct S1 {
+      int a;
+      int b;
+      T* ptr;
+    };
+
+    struct S2 : S1<S2> {
+      int c;
+      int d;
+      S1<int> mem;
+    };
+
+    int main() {
+      S2 sa ({$a1[[0]], $b1[[0]]}, $c[[0]], $d[[0]], $mem[[S1<int>($a2[[1]], 
$b2[[2]], $ptr[[nullptr]])]]);
+    }
+  )cpp",
+                        ExpectedHint{".a=", "a1"}, ExpectedHint{".b=", "b1"},
+                        ExpectedHint{".c=", "c"}, ExpectedHint{".d=", "d"},
+                        ExpectedHint{".mem=", "mem"}, ExpectedHint{".a=", 
"a2"},
+                        ExpectedHint{".b=", "b2"},
+                        ExpectedHint{".ptr=", "ptr"});
+}
+
 TEST(InlayHints, RestrictRange) {
   Annotations Code(R"cpp(
     auto a = false;

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index d30a7d3549188..7747c5d0e96a7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -96,6 +96,9 @@ Improvements to clangd
 Inlay hints
 ^^^^^^^^^^^
 
+- ``clangd`` now shows designator hints for aggregate initialization of 
structures 
+  with parentheses-list initialization (``CXXParenListInitExpr``) syntax. 
+
 Diagnostics
 ^^^^^^^^^^^
 


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

Reply via email to