[clang] Allow packing fields into tail padding of record fields (PR #122197)

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 16 13:02:10 PDT 2025


================
@@ -389,14 +389,28 @@ void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) {
       // Empty fields have no storage.
       ++Field;
     } else {
-      // Use base subobject layout for the potentially-overlapping field,
-      // as it is done in RecordLayoutBuilder
-      Members.push_back(MemberInfo(
-          bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
-          Field->isPotentiallyOverlapping()
-              ? getStorageType(Field->getType()->getAsCXXRecordDecl())
-              : getStorageType(*Field),
-          *Field));
+      CharUnits CurOffset = bitsToCharUnits(getFieldBitOffset(*Field));
+      llvm::Type *StorageType = getStorageType(*Field);
+
+      // Detect cases when the next field needs to be packed into tail padding
+      // of a record field. This is typically caused by [[no_unique_address]],
+      // but we try to infer when that is the case rather than checking for the
+      // attribute explicitly because the attribute is typically not present in
+      // debug info. Use the base subobject LLVM struct type in these cases,
+      // which will be less than data size bytes.
+      if (const CXXRecordDecl *FieldRD =
+              Field->getType()->getAsCXXRecordDecl()) {
+        CharUnits NextOffset = Layout.getNonVirtualSize();
+        auto NextField = std::next(Field);
----------------
rnk wrote:

That is annoying. I think the whole purpose of building the `Members` vector is to sort the subobjects by offset to avoid dealing with special cases where field offsets are non-ascending, so perhaps I should be computing the LLVM storage types in a second pass altogether.

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


More information about the cfe-commits mailing list