[clang] [Clang] Fix oversized bit-field layout on big-endian targets (PR #225494)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 22 20:11:27 PDT 2026
https://github.com/xiongzile updated https://github.com/llvm/llvm-project/pull/225494
>From aa4b747ea45d05e37ec6f8d30b3f0dd1821c7d39 Mon Sep 17 00:00:00 2001
From: Elio <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 03:10:13 +0800
Subject: [PATCH 1/3] [Clang][CodeGen] Fix oversized bit-field placement on
big-endian
CodeGen treated the full declared width of an oversized bit-field as
value bits. On big-endian targets that stored the value at the low end
of the storage unit, so `unsigned char value : 16` initialized to 0xAB
landed in memory as 00 AB and was loaded from the second byte. Clamp
the value width to the declared type before the big-endian offset
adjustment, matching CGBitFieldInfo::MakeInfo.
---
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 5 ++
.../aarch64-be-oversized-bitfield.cpp | 47 +++++++++++++++++++
2 files changed, 52 insertions(+)
create mode 100644 clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index d98d7c0c96dc3d..56199dc18b7943 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -243,6 +243,11 @@ void CGRecordLowering::setBitFieldInfo(
Info.StorageOffset = StartOffset;
if (Info.Size > Info.StorageSize)
Info.Size = Info.StorageSize;
+ // CGBitFieldInfo::MakeInfo does the same clamp
+ llvm::Type *FieldType = Types.ConvertTypeForMem(FD->getType());
+ unsigned FieldTypeSize = DataLayout.getTypeAllocSizeInBits(FieldType);
+ if (Info.Size > FieldTypeSize)
+ Info.Size = FieldTypeSize;
// Reverse the bit offsets for big endian machines. Because we represent
// a bitfield as a single large integer load, we can imagine the bits
// counting from the most-significant-bit instead of the
diff --git a/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp b/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
new file mode 100644
index 00000000000000..8dc72c55f984dd
--- /dev/null
+++ b/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.be.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
+// RUN: FileCheck %s --check-prefix=BE <%t.be.ll
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.le.ll %s | FileCheck %s --check-prefix=LAYOUT-LE
+// RUN: FileCheck %s --check-prefix=LE <%t.le.ll
+
+// An oversized bit-field has a declared width larger than its type. Only the
+// type width is a value; the rest is padding, and the value bits come first.
+// On AArch64 big endian that places 0xAB in the high byte of the 16-bit
+// container (memory AB 00). A load therefore shifts the container right by 8.
+// Little endian keeps the value in the low byte (memory AB 00 as well, as the
+// integer 0x00AB).
+
+#pragma clang diagnostic ignored "-Wbitfield-width"
+
+struct S {
+ unsigned char value : 16;
+};
+
+// LAYOUT-BE: BitFields:[
+// LAYOUT-BE-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
+// LAYOUT-BE-NEXT: ]>
+// LAYOUT-LE: BitFields:[
+// LAYOUT-LE-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
+// LAYOUT-LE-NEXT: ]>
+
+// First byte is 0xAB. The padding byte is not the value.
+// BE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
+// LE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
+extern "C" S global = {0xAB};
+
+// BE-LABEL: define {{.*}} @get(
+// BE: [[P:%.*]] = load ptr, ptr %p.addr
+// BE: [[LOAD:%.*]] = load i16, ptr [[P]]
+// BE-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8
+// BE-NEXT: trunc i16 [[SHL]] to i8
+//
+// LE-LABEL: define {{.*}} @get(
+// LE: [[P:%.*]] = load ptr, ptr %p.addr
+// LE: [[LOAD:%.*]] = load i16, ptr [[P]]
+// LE-NOT: lshr
+// LE: [[CLEAR:%.*]] = and i16 [[LOAD]], 255
+// LE-NEXT: trunc i16 [[CLEAR]] to i8
+extern "C" unsigned char get(const S *p) {
+ return p->value;
+}
>From 7c0868223ac0cdb79ee75007c2b13f0977ace40f Mon Sep 17 00:00:00 2001
From: Elio <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 03:10:14 +0800
Subject: [PATCH 2/3] [Clang] Adjust padding calculation for corrected
oversized bit-fields
__builtin_clear_padding located occupied bits using the old big-endian
layout, which placed padding before the value of an oversized
bit-field. After the CodeGen fix, value bits come first. Size the value
container to the field type and keep only the low-order occupied bits
inside it, so clear_padding no longer zeroes the value.
---
clang/lib/AST/ASTContext.cpp | 27 +-
.../builtin-clear-padding-codegen.cpp | 395 ++++++------------
2 files changed, 152 insertions(+), 270 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index e74423ca8c8a1b..f2d7ebcbd3c5ed 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15917,13 +15917,15 @@ struct PaddingCalculator {
const uint64_t DeclaredSizeInBits = Field->getBitWidthValue();
- // Handle over-sized bitfields:
- // unsigned char a : 12;
- // In this case, DeclaredSizeInBits is 12, but the actually occupied bit
- // size is 8, while the remaining 4 bits are padding.
- const uint64_t OccupiedSizeInBits =
- std::min(DeclaredSizeInBits,
- static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
+ // Oversized bit-fields (declared width larger than the field type) keep
+ // only the type's width as the value container. The extra declared bits
+ // are padding and follow that container (Itanium C++ ABI 2.4).
+ // getIntWidth may be narrower still (bool, _BitInt); those occupied bits
+ // are the low-order bits of the value container.
+ const uint64_t ValueFieldBits =
+ std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType()));
+ const uint64_t OccupiedSizeInBits = std::min(
+ ValueFieldBits, static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
@@ -15941,14 +15943,11 @@ struct PaddingCalculator {
// the partially occupied bytes in either end, if present, their bit
// intervals need to be adjusted so that they count from the MSB instead.
//
- // FIXME: For over-sized bitfields in BE, Clang allocates padding bits
- // before the occupied bits. This violates the ABI rules, which say that
- // padding should be allocated after, regardless of endianness (Itanium C++
- // ABI ยง2.4, II.1(b)). The current code accommodates for Clang's current
- // behaviour though, and bumps Start forward to skip the leading padding
- // bits.
+ // Within the value container, occupied bits are its low-order bits, which
+ // are allocated last. Padding from an oversized declared width follows
+ // the container.
const uint64_t Start =
- StartBitOffset + DeclaredSizeInBits - OccupiedSizeInBits;
+ StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
const uint64_t End = Start + OccupiedSizeInBits;
const uint64_t CharWidth = Ctx.getCharWidth();
diff --git a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
index 7de1b0bb59fc5f..599a8ba03c30df 100644
--- a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
+++ b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
@@ -1782,32 +1782,20 @@ struct OversizedBitfield {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testOversizedBitfield(
@@ -1816,32 +1804,20 @@ struct OversizedBitfield {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
@@ -1898,32 +1874,20 @@ extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
@@ -1932,32 +1896,20 @@ extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testOversizedBitfieldVolatileStruct(
@@ -2021,32 +1973,20 @@ struct VolatileOversizedBitfield {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testVolatileOversizedBitfield(
@@ -2055,32 +1995,20 @@ struct VolatileOversizedBitfield {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testVolatileOversizedBitfield(
@@ -2138,32 +2066,20 @@ extern "C" void testVolatileOversizedBitfield(
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
@@ -2172,32 +2088,20 @@ extern "C" void testVolatileOversizedBitfield(
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testVolatileOversizedBitfieldVolatileStruct(
@@ -4838,8 +4742,8 @@ extern "C" void testPackedBooleanVectorWithFullyPaddingBytes(bool33 *v) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wbitfield-width"
-// Match Clang's existing oversized-field representation. On big endian the
-// occupied byte is byte 1, so clearing padding must leave that byte intact.
+// Value bits occupy the first byte on both endians. The second byte is
+// padding and must be cleared.
struct BitfieldOversizedAligned {
unsigned char value : 16;
};
@@ -4870,8 +4774,8 @@ struct BitfieldOversizedAligned {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedAligned(
@@ -4880,16 +4784,15 @@ struct BitfieldOversizedAligned {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedAligned(BitfieldOversizedAligned *s) {
__builtin_clear_padding(s);
}
-// The occupied bits cross a byte boundary after more than one byte of leading
-// padding on big endian. The declared width also exceeds the allocation type.
+// Eight value bits occupy the first byte. The rest of the allocation is padding.
struct BitfieldOversizedBeyondBoundary {
unsigned char value : 17;
};
@@ -4928,18 +4831,12 @@ struct BitfieldOversizedBeyondBoundary {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 1
-// ARM-BE-NEXT: [[TMP4:%.*]] = and i8 [[TMP3]], 127
-// ARM-BE-NEXT: store i8 [[TMP4]], ptr [[TMP2]], align 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -128
-// ARM-BE-NEXT: store i8 [[TMP7]], ptr [[TMP5]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
@@ -4948,18 +4845,12 @@ struct BitfieldOversizedBeyondBoundary {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 1
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = and i8 [[TMP3]], 127
-// AARCH64-BE-NEXT: store i8 [[TMP4]], ptr [[TMP2]], align 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -128
-// AARCH64-BE-NEXT: store i8 [[TMP7]], ptr [[TMP5]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedBeyondBoundary(
@@ -5030,14 +4921,10 @@ struct BitfieldOversizedValueTypes {
// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 15
-// ARM-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1
-// ARM-BE-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 2
-// ARM-BE-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], -15
-// ARM-BE-NEXT: store i8 [[TMP12]], ptr [[TMP10]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 2
+// ARM-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 1
+// ARM-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 2
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes(
@@ -5054,14 +4941,10 @@ struct BitfieldOversizedValueTypes {
// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 15
-// AARCH64-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 2
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], -15
-// AARCH64-BE-NEXT: store i8 [[TMP12]], ptr [[TMP10]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 2
+// AARCH64-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 1
+// AARCH64-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 2
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedValueTypes(
>From a57f09dfe74547b919b2423d5e93db1803a020b8 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 11:09:43 +0800
Subject: [PATCH 3/3] clang-format
---
clang/lib/AST/ASTContext.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f2d7ebcbd3c5ed..c6554fc58f1985 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15924,8 +15924,9 @@ struct PaddingCalculator {
// are the low-order bits of the value container.
const uint64_t ValueFieldBits =
std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType()));
- const uint64_t OccupiedSizeInBits = std::min(
- ValueFieldBits, static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
+ const uint64_t OccupiedSizeInBits =
+ std::min(ValueFieldBits,
+ static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
@@ -15946,8 +15947,7 @@ struct PaddingCalculator {
// Within the value container, occupied bits are its low-order bits, which
// are allocated last. Padding from an oversized declared width follows
// the container.
- const uint64_t Start =
- StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
+ const uint64_t Start = StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
const uint64_t End = Start + OccupiedSizeInBits;
const uint64_t CharWidth = Ctx.getCharWidth();
More information about the cfe-commits
mailing list