[clang] bd5883c - [clang] Fix record alignment lost via external layout on Arm64 (#212362)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 27 15:55:28 PDT 2026


Author: Daniel Paoliello
Date: 2026-07-27T15:55:23-07:00
New Revision: bd5883c35f43b01ab96bbdba1bc14a81f78694ea

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

LOG: [clang] Fix record alignment lost via external layout on Arm64 (#212362)

An external layout source (such as LLDB reading DWARF) supplies a
record's final alignment directly, since `alignas` / `__declspec(align)`
attributes are not recoverable from debug info. `finalizeLayout`
captured `NonRequiredAlignment` before applying the external alignment,
so an externally laid out record published a stale, too-small value.

On Arm64 this field is used to fold a base's alignment into the derived
record, so a derived class picked up the stale value instead of the
base's actual alignment. This regressed
`lldb/test/API/lang/cpp/alignas_base_class` when #210461 was merged,
where `alignof(Derived)` evaluated to 1 instead of 8. Other targets were
unaffected as they do not read this field.

Treat all of an externally supplied alignment as non-required, as there
is no way to tell how much of it was imposed by an alignment attribute.

Added: 
    clang/test/CodeGenCXX/Inputs/override-layout-aligned-base.layout
    clang/test/CodeGenCXX/override-layout-aligned-base.cpp

Modified: 
    clang/lib/AST/RecordLayoutBuilder.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 61df17451be5d..c27572bc7f50d 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -3307,8 +3307,13 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
 
   if (UseExternalLayout) {
     Size = Context.toCharUnitsFromBits(External.Size);
-    if (External.Align)
+    if (External.Align) {
       Alignment = Context.toCharUnitsFromBits(External.Align);
+      // An external layout provides the record's final alignment, with no way
+      // to tell how much of it was imposed via alignas / __declspec(align), so
+      // treat all of it as non-required alignment.
+      NonRequiredAlignment = Alignment;
+    }
     return;
   }
   unsigned CharBitNum = Context.getTargetInfo().getCharWidth();

diff  --git a/clang/test/CodeGenCXX/Inputs/override-layout-aligned-base.layout b/clang/test/CodeGenCXX/Inputs/override-layout-aligned-base.layout
new file mode 100644
index 0000000000000..7828b17ea1769
--- /dev/null
+++ b/clang/test/CodeGenCXX/Inputs/override-layout-aligned-base.layout
@@ -0,0 +1,8 @@
+
+*** Dumping AST Record Layout
+Type: struct AlignedBase
+
+Layout: <ASTRecordLayout
+  Size:64
+  Alignment:64
+  FieldOffsets: []>

diff  --git a/clang/test/CodeGenCXX/override-layout-aligned-base.cpp b/clang/test/CodeGenCXX/override-layout-aligned-base.cpp
new file mode 100644
index 0000000000000..387e8bfc414b2
--- /dev/null
+++ b/clang/test/CodeGenCXX/override-layout-aligned-base.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple aarch64-windows-msvc -w -fdump-record-layouts-simple \
+// RUN:            -foverride-record-layout=%S/Inputs/override-layout-aligned-base.layout %s \
+// RUN:   | FileCheck %s
+// RUN: %clang_cc1 -triple arm64ec-windows-msvc -w -fdump-record-layouts-simple \
+// RUN:            -foverride-record-layout=%S/Inputs/override-layout-aligned-base.layout %s \
+// RUN:   | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -w -fdump-record-layouts-simple \
+// RUN:            -foverride-record-layout=%S/Inputs/override-layout-aligned-base.layout %s \
+// RUN:   | FileCheck %s
+
+// An external layout source (such as LLDB reading DWARF) supplies a record's
+// alignment directly; the over-alignment is not recoverable from an alignas
+// attribute because no such attribute exists in the AST.  A derived class must
+// still pick up the externally supplied alignment of its base.
+
+// CHECK: Type: struct AlignedBase
+// CHECK:   Size:64
+// CHECK:   Alignment:64
+struct AlignedBase {
+};
+
+// CHECK: Type: struct Derived
+// CHECK:   Alignment:64
+struct Derived : AlignedBase {
+};
+
+void use_structs() {
+  Derived d;
+}


        


More information about the cfe-commits mailing list