Skip to content

Commit c300884

Browse files
authored
[clangd] Show alignment for records and fields decls (#67213)
Shows align for records and fields declarations in hover information. Example: ```cpp struct A { char a; short b; }; ``` For this struct hover informations shows: ``` Size: 4 bytes, alignment 2 bytes ``` ![image](https://github.com/llvm/llvm-project/assets/12231048/a130b353-f3f6-4203-b0d7-3d592b7a7855)
1 parent 4f56d47 commit c300884

File tree

3 files changed

+18
-2
lines changed

3 files changed

+18
-2
lines changed

clang-tools-extra/clangd/Hover.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,8 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
10011001
if (auto *RD = llvm::dyn_cast<RecordDecl>(&ND)) {
10021002
if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RD->getTypeForDecl()))
10031003
HI.Size = Size->getQuantity() * 8;
1004+
if (!RD->isDependentType() && RD->isCompleteDefinition())
1005+
HI.Align = Ctx.getTypeAlign(RD->getTypeForDecl());
10041006
return;
10051007
}
10061008

@@ -1009,6 +1011,7 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
10091011
if (Record)
10101012
Record = Record->getDefinition();
10111013
if (Record && !Record->isInvalidDecl() && !Record->isDependentType()) {
1014+
HI.Align = Ctx.getTypeAlign(FD->getType());
10121015
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Record);
10131016
HI.Offset = Layout.getFieldOffset(FD->getFieldIndex());
10141017
if (FD->isBitField())
@@ -1487,6 +1490,8 @@ markup::Document HoverInfo::present() const {
14871490
P.appendText(
14881491
llvm::formatv(" (+{0} padding)", formatSize(*Padding)).str());
14891492
}
1493+
if (Align)
1494+
P.appendText(", alignment " + formatSize(*Align));
14901495
}
14911496

14921497
if (CalleeArgInfo) {

clang-tools-extra/clangd/Hover.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ struct HoverInfo {
9797
std::optional<uint64_t> Offset;
9898
/// Contains the padding following a field within the enclosing class.
9999
std::optional<uint64_t> Padding;
100+
/// Contains the alignment of fields and types where it's interesting.
101+
std::optional<uint64_t> Align;
100102
// Set when symbol is inside function call. Contains information extracted
101103
// from the callee definition about the argument this is passed as.
102104
std::optional<Param> CalleeArgInfo;

clang-tools-extra/clangd/unittests/HoverTests.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ TEST(Hover, Structured) {
9292
HI.Offset = 0;
9393
HI.Size = 8;
9494
HI.Padding = 56;
95+
HI.Align = 8;
9596
HI.AccessSpecifier = "private";
9697
}},
9798
// Union field
@@ -110,6 +111,7 @@ TEST(Hover, Structured) {
110111
HI.Type = "char";
111112
HI.Size = 8;
112113
HI.Padding = 120;
114+
HI.Align = 8;
113115
HI.AccessSpecifier = "public";
114116
}},
115117
// Bitfield
@@ -128,6 +130,7 @@ TEST(Hover, Structured) {
128130
HI.Type = "int";
129131
HI.Offset = 0;
130132
HI.Size = 1;
133+
HI.Align = 32;
131134
HI.AccessSpecifier = "public";
132135
}},
133136
// Local to class method.
@@ -192,6 +195,7 @@ TEST(Hover, Structured) {
192195
HI.Type = "char";
193196
HI.Offset = 0;
194197
HI.Size = 8;
198+
HI.Align = 8;
195199
HI.AccessSpecifier = "public";
196200
}},
197201
// Struct definition shows size.
@@ -204,6 +208,7 @@ TEST(Hover, Structured) {
204208
HI.Kind = index::SymbolKind::Struct;
205209
HI.Definition = "struct X {}";
206210
HI.Size = 8;
211+
HI.Align = 8;
207212
}},
208213
// Variable with template type
209214
{R"cpp(
@@ -1375,6 +1380,7 @@ class Foo final {})cpp";
13751380
HI.Offset = 8;
13761381
HI.Size = 1;
13771382
HI.Padding = 23;
1383+
HI.Align = 8;
13781384
HI.AccessSpecifier = "public";
13791385
}}};
13801386
for (const auto &Case : Cases) {
@@ -1411,6 +1417,7 @@ class Foo final {})cpp";
14111417
EXPECT_EQ(H->Value, Expected.Value);
14121418
EXPECT_EQ(H->Size, Expected.Size);
14131419
EXPECT_EQ(H->Offset, Expected.Offset);
1420+
EXPECT_EQ(H->Align, Expected.Align);
14141421
EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier);
14151422
EXPECT_EQ(H->CalleeArgInfo, Expected.CalleeArgInfo);
14161423
EXPECT_EQ(H->CallPassType, Expected.CallPassType);
@@ -3448,13 +3455,14 @@ template <typename T, typename C = bool> class Foo {})",
34483455
HI.Size = 32;
34493456
HI.Offset = 96;
34503457
HI.Padding = 32;
3458+
HI.Align = 32;
34513459
},
34523460
R"(field foo
34533461
34543462
Type: type (aka can_type)
34553463
Value = value
34563464
Offset: 12 bytes
3457-
Size: 4 bytes (+4 bytes padding)
3465+
Size: 4 bytes (+4 bytes padding), alignment 4 bytes
34583466
34593467
// In test::Bar
34603468
def)",
@@ -3470,13 +3478,14 @@ def)",
34703478
HI.Size = 25;
34713479
HI.Offset = 35;
34723480
HI.Padding = 4;
3481+
HI.Align = 64;
34733482
},
34743483
R"(field foo
34753484
34763485
Type: type (aka can_type)
34773486
Value = value
34783487
Offset: 4 bytes and 3 bits
3479-
Size: 25 bits (+4 bits padding)
3488+
Size: 25 bits (+4 bits padding), alignment 8 bytes
34803489
34813490
// In test::Bar
34823491
def)",

0 commit comments

Comments
 (0)