Author: Elio Date: 2026-10-09T12:05:53+01:00 New Revision: f3c93acd6ecef3324c39af67a8a563b3a8dc6020
URL: https://github.com/llvm/llvm-project/commit/f3c93acd6ecef3324c39af67a8a563b3a8dc6020 DIFF: https://github.com/llvm/llvm-project/commit/f3c93acd6ecef3324c39af67a8a563b3a8dc6020.diff LOG: [Clang] Fix oversized bit-field layout on big-endian targets (#225494) Fixes #225361. This patch fixes two issues related to bit-fields: - **Big-endian CodeGen:** Clang incorrectly places the value bits of oversized bit-fields after the padding bits, contrary to the Itanium C++ ABI (§2.4). Fix the layout so that value bits precede padding bits. - **`__builtin_clear_padding` (LE and BE):** Correct the occupied-bit calculation for bit-fields, including `bool` and `_BitInt`, by using `min(declared width, type size)`. This preserves bits that should not be treated as padding. Added: clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp Modified: clang/lib/AST/ASTContext.cpp clang/lib/CodeGen/CGRecordLayoutBuilder.cpp clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 58a761f11925c0..d2774b03151b2c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -15972,13 +15972,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. + // Oversized bit-fields (declared width larger than the field type) occupy + // only the type's width. The extra declared bits are padding and follow + // the occupied bits (Itanium C++ ABI §2.4, II.1(b)). + // In case where the bitfield can only have values with a range smaller than + // the one declared, e.g. bool a : 5 or _BitInt(5) b : 6, the remaining bits + // within the bitfield are for sign or zero extension. These are considered + // occupied as well. const uint64_t OccupiedSizeInBits = - std::min(DeclaredSizeInBits, - static_cast<uint64_t>(Ctx.getIntWidth(Field->getType()))); + std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType())); if (Ctx.getTargetInfo().isLittleEndian()) { OccuppiedIntervals.push_back( @@ -15996,14 +15998,8 @@ 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. - const uint64_t Start = - StartBitOffset + DeclaredSizeInBits - OccupiedSizeInBits; + // Occupied bits are allocated first, and any padding follows them. + const uint64_t Start = StartBitOffset; const uint64_t End = Start + OccupiedSizeInBits; const uint64_t CharWidth = Ctx.getCharWidth(); diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 6e7df1395350c8..0a5fd222b7d80b 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -223,6 +223,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/big-endian-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp new file mode 100644 index 00000000000000..da51f12b553ab9 --- /dev/null +++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -emit-llvm -fdump-record-layouts-simple -o %t.be.ll %s | FileCheck %s --check-prefix=LAYOUT +// RUN: FileCheck %s --check-prefix=IR <%t.be.ll +// RUN: %clang_cc1 -triple s390x-linux-gnu -emit-llvm -fdump-record-layouts-simple -o %t.s390x.ll %s | FileCheck %s --check-prefix=LAYOUT +// RUN: FileCheck %s --check-prefix=IR <%t.s390x.ll +// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -fdump-record-layouts-simple -o %t.ppc64.ll %s | FileCheck %s --check-prefix=LAYOUT +// RUN: FileCheck %s --check-prefix=IR <%t.ppc64.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. +// Big endian places 0xAB at the higher bits of the 16-bit storage type, although in memory it resides +// at the low byte because of the reversed byte order. A load therefore +// shifts the storage type (i16) right by 8. A store shifts the new value left by 8 +// and keeps the lower bits. + +#pragma clang diagnostic ignored "-Wbitfield-width" + +struct S { + unsigned char value : 16; +}; + +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: ]> + +// First byte is 0xAB. The padding byte is not the value. +// IR: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2 +S global = {0xAB}; + +// `bool : 16 = true` is 00000001 in the first byte. The value bit is the +// low bit of that byte; the second byte is padding. +// IR: @bglobal = global { i8, i8 } { i8 1, i8 undef }, align 2 +struct B { + bool value : 16; +}; +B bglobal = {true}; + +// IR-LABEL: define {{.*}} @_Z3getPK1S( +// IR: [[P:%.*]] = load ptr, ptr %p.addr +// IR: [[LOAD:%.*]] = load i16, ptr [[P]] +// IR-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8 +// IR-NEXT: trunc i16 [[SHL]] to i8 +unsigned char get(const S *p) { + return p->value; +} + +// The value goes in the high byte. The low byte is padding and is preserved. +// IR-LABEL: define {{.*}} @_Z3setP1Sh( +// IR: [[V:%.*]] = load i8, ptr %v.addr +// IR: [[PTR:%.*]] = load ptr, ptr %p.addr +// IR: [[EXT:%.*]] = zext i8 [[V]] to i16 +// IR: [[OLD:%.*]] = load i16, ptr [[PTR]] +// IR-NEXT: [[MASKED:%.*]] = and i16 [[EXT]], 255 +// IR-NEXT: [[SHIFTED:%.*]] = shl i16 [[MASKED]], 8 +// IR-NEXT: [[KEPT:%.*]] = and i16 [[OLD]], 255 +// IR-NEXT: [[MERGED:%.*]] = or i16 [[KEPT]], [[SHIFTED]] +// IR-NEXT: store i16 [[MERGED]], ptr [[PTR]] +void set(S *p, unsigned char v) { + p->value = v; +} + +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: ]> + +// IR-LABEL: define {{.*}} @_Z3getPK1B( +// IR: [[BP:%.*]] = load ptr, ptr %p.addr +// IR: [[BLOAD:%.*]] = load i16, ptr [[BP]] +// IR-NEXT: [[BSHL:%.*]] = lshr i16 [[BLOAD]], 8 +// IR-NEXT: trunc i16 [[BSHL]] to i1 +bool get(const B *p) { + return p->value; +} + +// IR-LABEL: define {{.*}} @_Z3setP1Bb( +// IR: [[BEXT:%.*]] = zext i1 {{.*}} to i16 +// IR: [[BOLD:%.*]] = load i16, ptr %{{.*}} +// IR-NEXT: [[BSHIFT:%.*]] = shl i16 [[BEXT]], 8 +// IR-NEXT: [[BKEPT:%.*]] = and i16 [[BOLD]], 255 +// IR-NEXT: [[BMERGED:%.*]] = or i16 [[BKEPT]], [[BSHIFT]] +// IR-NEXT: store i16 [[BMERGED]], ptr %{{.*}} +void set(B *p, bool v) { + p->value = v; +} diff --git a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp index 7de1b0bb59fc5f..8b495d4336ea97 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,65 @@ 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. +// `bool : 16` occupies the whole first byte on both endians, like GCC. Only +// the second byte is padding. +struct BitfieldOversizedBool { + bool value : 16; +}; + +// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedBool( +// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// ITANIUM64-LE-NEXT: [[ENTRY:.*:]] +// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8 +// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8 +// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1 +// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1 +// ITANIUM64-LE-NEXT: ret void +// +// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedBool( +// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1 +// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1 +// ARM-LE-NEXT: ret void +// +// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedBool( +// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// 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 1 +// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1 +// ARM-BE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedBool( +// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// 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 1 +// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1 +// AARCH64-BE-NEXT: ret void +// +extern "C" void testBitfieldOversizedBool(BitfieldOversizedBool *s) { + __builtin_clear_padding(s); +} + +// Eight value bits occupy the first byte. The rest of the allocation is padding. struct BitfieldOversizedBeyondBoundary { unsigned char value : 17; }; @@ -4928,18 +4881,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 +4895,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( @@ -4984,16 +4925,12 @@ struct BitfieldOversizedValueTypes { // ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 // ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 // ITANIUM64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2 -// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1 +// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 7 // ITANIUM64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2 // ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2 // ITANIUM64-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2 // ITANIUM64-LE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -16 // ITANIUM64-LE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2 -// ITANIUM64-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 -// ITANIUM64-LE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1 -// ITANIUM64-LE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 31 -// ITANIUM64-LE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1 // ITANIUM64-LE-NEXT: ret void // // ARM-LE-LABEL: define dso_local void @testBitfieldOversizedValueTypes( @@ -5004,16 +4941,12 @@ struct BitfieldOversizedValueTypes { // ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 // ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 // ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2 -// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1 +// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 7 // ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2 // ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2 // ARM-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2 // ARM-LE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -16 // ARM-LE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2 -// ARM-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 -// ARM-LE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1 -// ARM-LE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 31 -// ARM-LE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1 // ARM-LE-NEXT: ret void // // ARM-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes( @@ -5026,18 +4959,10 @@ struct BitfieldOversizedValueTypes { // ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2 // ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -32 // ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2 -// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2 // ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2 -// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63 +// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 15 // 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: ret void // // AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes( @@ -5050,18 +4975,10 @@ struct BitfieldOversizedValueTypes { // AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2 // AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -32 // AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2 -// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2 // AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2 -// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63 +// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 15 // 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: ret void // extern "C" void testBitfieldOversizedValueTypes( @@ -5069,6 +4986,82 @@ extern "C" void testBitfieldOversizedValueTypes( __builtin_clear_padding(s); } +// Within a single byte, padding follows the occupied bits: it is in the high +// bits on little endian and in the low bits on big endian. The _BitInt(5) +// field is kept up to the storage size of _BitInt(5), i.e. all 6 bits. +struct BitfieldOversizedSubByte { + _BitInt(5) precise : 6; + bool flag : 6; +}; + +// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedSubByte( +// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// ITANIUM64-LE-NEXT: [[ENTRY:.*:]] +// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8 +// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8 +// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1 +// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63 +// ITANIUM64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1 +// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1 +// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 +// ITANIUM64-LE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63 +// ITANIUM64-LE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1 +// ITANIUM64-LE-NEXT: ret void +// +// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedSubByte( +// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1 +// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63 +// ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1 +// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1 +// ARM-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 +// ARM-LE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63 +// ARM-LE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1 +// ARM-LE-NEXT: ret void +// +// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedSubByte( +// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// 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 1 +// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -4 +// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1 +// 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]], -4 +// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1 +// ARM-BE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedSubByte( +// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// 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 1 +// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -4 +// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1 +// 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]], -4 +// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1 +// AARCH64-BE-NEXT: ret void +// +extern "C" void testBitfieldOversizedSubByte(BitfieldOversizedSubByte *s) { + __builtin_clear_padding(s); +} + #pragma clang diagnostic pop #endif _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
