[clang-tools-extra] [clangd] Add padding to struct hover information (PR #115665)

Kevin Kremer via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 10 20:03:45 PST 2024


https://github.com/Xoltus updated https://github.com/llvm/llvm-project/pull/115665

>From 3b64d9d82047159fbd7cb4662d1b666c4431be9c Mon Sep 17 00:00:00 2001
From: Kevin Kremer <github at kevin-kremer.com>
Date: Sun, 10 Nov 2024 16:00:00 +0000
Subject: [PATCH 1/2] [clangd] Add padding to struct hover information

HI.Padding is already available for a struct's member
variables but the struct itself is not displaying how
much padding has been added to it.

This commit sums up all padding within a struct and adds
it to a struct's hover information.
---
 clang-tools-extra/clangd/Hover.cpp            | 27 ++++++++
 .../clangd/unittests/HoverTests.cpp           | 62 +++++++++++++++++++
 2 files changed, 89 insertions(+)

diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 298fa79e3fd0ba..9ef32a777d73fe 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -1006,6 +1006,33 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
       HI.Size = Size->getQuantity() * 8;
     if (!RD->isDependentType() && RD->isCompleteDefinition())
       HI.Align = Ctx.getTypeAlign(RD->getTypeForDecl());
+    if (HI.Size && !RD->field_empty()) {
+      HI.Padding = 0;
+      const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
+      auto NumFields = std::distance(RD->field_begin(), RD->field_end());
+      auto FieldIt = RD->field_begin();
+      for (; --NumFields; ++FieldIt) {
+        unsigned Offset = Layout.getFieldOffset(FieldIt->getFieldIndex());
+        unsigned NextOffset =
+            Layout.getFieldOffset(FieldIt->getFieldIndex() + 1);
+        if (auto Size = Ctx.getTypeSizeInCharsIfKnown(FieldIt->getType())) {
+          unsigned EndOfField = Offset + Size->getQuantity() * 8;
+          if (NextOffset > EndOfField)
+            HI.Padding = *HI.Padding + NextOffset - EndOfField;
+        } else {
+          HI.Padding.reset();
+          break;
+        }
+      }
+      // We've processed all but the last field. If we still have valid
+      // HI.Padding, finish the calculation
+      auto Size = Ctx.getTypeSizeInCharsIfKnown(FieldIt->getType());
+      if (HI.Padding && Size) {
+        unsigned Offset = Layout.getFieldOffset(FieldIt->getFieldIndex());
+        HI.Padding = *HI.Padding + *HI.Size - Offset - Size->getQuantity() * 8;
+      }
+    }
+
     return;
   }
 
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 69f6df46c87ce0..96fb4d8f317328 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -73,6 +73,68 @@ TEST(Hover, Structured) {
          HI.Type = "void ()";
          HI.Parameters.emplace();
        }},
+      {R"cpp(
+            struct [[F^oo]] {
+              char a;
+              long long b;
+            };
+          )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "Foo";
+         HI.Kind = index::SymbolKind::Struct;
+         HI.Definition = "struct Foo {}";
+         HI.Size = 128;
+         HI.Padding = 56;
+         HI.Align = 64;
+       }},
+      {R"cpp(
+            struct [[F^oo]] {
+              int b;
+              char a;
+            };
+          )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "Foo";
+         HI.Kind = index::SymbolKind::Struct;
+         HI.Definition = "struct Foo {}";
+         HI.Size = 64;
+         HI.Padding = 24;
+         HI.Align = 32;
+       }},
+      {R"cpp(
+            struct [[F^oo]] {
+              double a;
+              char b;
+              double c;
+            };
+          )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "Foo";
+         HI.Kind = index::SymbolKind::Struct;
+         HI.Definition = "struct Foo {}";
+         HI.Size = 192;
+         HI.Padding = 46;
+         HI.Align = 64;
+       }},      {R"cpp(
+            struct [[F^oo]] {
+              double a;
+              char b;
+              double c;
+              char d;
+            };
+          )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "Foo";
+         HI.Kind = index::SymbolKind::Struct;
+         HI.Definition = "struct Foo {}";
+         HI.Size = 256;
+         HI.Padding = 112;
+         HI.Align = 64;
+       }},
       // Field
       {R"cpp(
           namespace ns1 { namespace ns2 {

>From 126fb9bf3e5bef3026bee37c4147ba36857bdeb8 Mon Sep 17 00:00:00 2001
From: Kevin Kremer <github at kevin-kremer.com>
Date: Mon, 11 Nov 2024 04:01:15 +0000
Subject: [PATCH 2/2] fix formatting

---
 clang-tools-extra/clangd/unittests/HoverTests.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 96fb4d8f317328..269b1f2faf5059 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -118,7 +118,8 @@ TEST(Hover, Structured) {
          HI.Size = 192;
          HI.Padding = 46;
          HI.Align = 64;
-       }},      {R"cpp(
+       }},
+      {R"cpp(
             struct [[F^oo]] {
               double a;
               char b;



More information about the cfe-commits mailing list