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

via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 10 09:57:44 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Kevin Kremer (Xoltus)

<details>
<summary>Changes</summary>

Hi team, I've written a small patch as a small quality of life improvement for my development and figured it may be worth sharing. Please let me know what you think:

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.

```
struct Foo
{
    char a;
    int b;
    char c;
};
```
results in
![Screenshot 2024-11-10 at 9 50 52 AM](https://github.com/user-attachments/assets/163d1582-4de0-4673-9024-8f04465f221a)

I've also added additional tests to HoverTests.cpp.

---
Full diff: https://github.com/llvm/llvm-project/pull/115665.diff


2 Files Affected:

- (modified) clang-tools-extra/clangd/Hover.cpp (+27) 
- (modified) clang-tools-extra/clangd/unittests/HoverTests.cpp (+62) 


``````````diff
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 {

``````````

</details>


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


More information about the cfe-commits mailing list