https://github.com/ojhunt updated https://github.com/llvm/llvm-project/pull/117428
>From 3e25d7ef2e223942298078dace8979905956d05c Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Fri, 22 Nov 2024 17:53:24 +0100 Subject: [PATCH 1/4] Add an off-by-default warning to complain about MSVC bitfield padding --- clang/include/clang/Basic/DiagnosticGroups.td | 1 + .../clang/Basic/DiagnosticSemaKinds.td | 6 + clang/lib/Sema/SemaDecl.cpp | 27 ++- .../SemaCXX/ms_struct-bitfield-padding.cpp | 180 ++++++++++++++++++ 4 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaCXX/ms_struct-bitfield-padding.cpp diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index df9bf94b5d0398..57bdda4b8f8b47 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -631,6 +631,7 @@ def Packed : DiagGroup<"packed", [PackedNonPod]>; def PaddedBitField : DiagGroup<"padded-bitfield">; def Padded : DiagGroup<"padded", [PaddedBitField]>; def UnalignedAccess : DiagGroup<"unaligned-access">; +def MSBitfieldCompatibility : DiagGroup<"ms-bitfield-packing-compatibility">; def PessimizingMove : DiagGroup<"pessimizing-move">; def ReturnStdMove : DiagGroup<"return-std-move">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index eb05a6a77978af..aa13e3438d3739 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6418,6 +6418,12 @@ def warn_signed_bitfield_enum_conversion : Warning< InGroup<BitFieldEnumConversion>, DefaultIgnore; def note_change_bitfield_sign : Note< "consider making the bitfield type %select{unsigned|signed}0">; +def warn_ms_bitfield_mismatched_storage_packing : Warning< + "bit-field %0 of type %1 has a different storage size (%2 vs %3 bytes) than the " + "preceding bit-field and may not be packed under MSVC ABI">, + InGroup<MSBitfieldCompatibility>, DefaultIgnore; +def note_ms_bitfield_mismatched_storage_size_previous : Note< + "preceding bit-field %0 declared here with type %1">; def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 74b0e5ad23bd48..18aeca3b34f659 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19001,9 +19001,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Verify that all the fields are okay. SmallVector<FieldDecl*, 32> RecFields; - + std::optional<const FieldDecl *> PreviousField; for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); - i != end; ++i) { + i != end; PreviousField = cast<FieldDecl>(*i), ++i) { FieldDecl *FD = cast<FieldDecl>(*i); // Get the type for the field. @@ -19213,6 +19213,29 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (Record && FD->getType().isVolatileQualified()) Record->setHasVolatileMember(true); + auto IsNonDependentBitField = [](const FieldDecl *FD) { + if (!FD->isBitField()) + return false; + if (FD->getType()->isDependentType()) + return false; + return true; + }; + + if (Record && PreviousField && IsNonDependentBitField(FD) && + IsNonDependentBitField(*PreviousField)) { + unsigned FDStorageSize = + Context.getTypeSizeInChars(FD->getType()).getQuantity(); + unsigned PreviousFieldStorageSize = + Context.getTypeSizeInChars((*PreviousField)->getType()).getQuantity(); + if (FDStorageSize != PreviousFieldStorageSize) { + Diag(FD->getLocation(), + diag::warn_ms_bitfield_mismatched_storage_packing) + << FD << FD->getType() << FDStorageSize << PreviousFieldStorageSize; + Diag((*PreviousField)->getLocation(), + diag::note_ms_bitfield_mismatched_storage_size_previous) + << *PreviousField << (*PreviousField)->getType(); + } + } // Keep track of the number of named members. if (FD->getIdentifier()) ++NumNamedMembers; diff --git a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp new file mode 100644 index 00000000000000..001086de5bbd10 --- /dev/null +++ b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp @@ -0,0 +1,180 @@ + +// RUN: %clang_cc1 -fsyntax-only -Wms-bitfield-packing-compatibility -verify -triple armv8 -std=c++23 %s +// RUN: %clang_cc1 -fsyntax-only -DMS_BITFIELDS -mms-bitfields -verify=msbitfields -triple armv8-apple-macos10.15 -std=c++23 %s + +// msbitfields-no-diagnostics + +enum Enum1 { Enum1_A, Enum1_B }; +enum Enum2 { Enum2_A, Enum2_B }; + +enum class EnumU32_1 : unsigned { A, B }; +enum class EnumU32_2 : unsigned { A, B }; +enum class EnumU64 : unsigned long long { A, B }; +enum class EnumI32 : int { A, B }; +enum class EnumU8 : unsigned char { A, B }; +enum class EnumI8 : char { A, B }; +enum class EnumU16 : unsigned short { A, B }; +enum class EnumI16 : short { A, B }; + +struct A { + unsigned int a : 15; + unsigned int b : 15; +}; +static_assert(sizeof(A) == 4); + +struct B { + unsigned int a : 15; + int b : 15; +}; +static_assert(sizeof(B) == 4); + +struct C { + unsigned int a : 15; + int b : 15; +}; +static_assert(sizeof(C) == 4); + +struct D { + Enum1 a : 15; + Enum1 b : 15; +}; +static_assert(sizeof(D) == 4); + +struct E { + Enum1 a : 15; + Enum2 b : 15; +}; +static_assert(sizeof(E) == 4); + +struct F { + EnumU32_1 a : 15; + EnumU32_2 b : 15; +}; +static_assert(sizeof(F) == 4); + +struct G { + EnumU32_1 a : 15; + EnumU64 b : 15; + // expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size (8 vs 4 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}} +}; + +#ifdef MS_BITFIELDS + static_assert(sizeof(G) == 16); +#else + static_assert(sizeof(G) == 8); +#endif + +struct H { + EnumU32_1 a : 10; + EnumI32 b : 10; + EnumU32_1 c : 10; +}; +static_assert(sizeof(H) == 4); + +struct I { + EnumU8 a : 3; + EnumI8 b : 5; + EnumU32_1 c : 10; + // expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size (4 vs 1 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'b' declared here with type 'EnumI8'}} +}; +#ifdef MS_BITFIELDS +static_assert(sizeof(I) == 8); +#else +static_assert(sizeof(I) == 4); +#endif + +struct J { + EnumU8 : 0; + EnumU8 b : 4; +}; +static_assert(sizeof(J) == 1); + +struct K { + EnumU8 a : 4; + EnumU8 : 0; +}; +static_assert(sizeof(K) == 1); + +struct L { + EnumU32_1 a : 10; + EnumU32_2 b : 10; + EnumU32_1 c : 10; +}; + +static_assert(sizeof(L) == 4); + +struct M { + EnumU32_1 a : 10; + EnumI32 b : 10; + EnumU32_1 c : 10; +}; + +static_assert(sizeof(M) == 4); + +struct N { + EnumU32_1 a : 10; + EnumU64 b : 10; + // expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size (8 vs 4 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}} + EnumU32_1 c : 10; + // expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size (4 vs 8 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-5 {{preceding bit-field 'b' declared here with type 'EnumU64'}} +}; + +#ifdef MS_BITFIELDS +static_assert(sizeof(N) == 24); +#else +static_assert(sizeof(N) == 8); +#endif + +struct O { + EnumU16 a : 10; + EnumU32_1 b : 10; + // expected-warning@-1 {{bit-field 'b' of type 'EnumU32_1' has a different storage size (4 vs 2 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU16'}} +}; +#ifdef MS_BITFIELDS +static_assert(sizeof(O) == 8); +#else +static_assert(sizeof(O) == 4); +#endif + +struct P { + EnumU32_1 a : 10; + EnumU16 b : 10; + // expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size (2 vs 4 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}} +}; +#ifdef MS_BITFIELDS +static_assert(sizeof(P) == 8); +#else +static_assert(sizeof(P) == 4); +#endif + +struct Q { + EnumU8 a : 6; + EnumU16 b : 6; + // expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size (2 vs 1 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU8'}} +}; +#ifdef MS_BITFIELDS +static_assert(sizeof(Q) == 4); +#else +static_assert(sizeof(Q) == 2); +#endif + +struct R { + EnumU16 a : 9; + EnumU16 b : 9; + EnumU8 c : 6; + // expected-warning@-1 {{bit-field 'c' of type 'EnumU8' has a different storage size (1 vs 2 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-note@-3 {{preceding bit-field 'b' declared here with type 'EnumU16'}} +}; + +#ifdef MS_BITFIELDS +static_assert(sizeof(R) == 6); +#else +static_assert(sizeof(R) == 4); +#endif >From 11447fea7197a0902c0b1c23071b35de3b782f13 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Sat, 30 Nov 2024 19:36:33 -0800 Subject: [PATCH 2/4] Address feedback --- .../clang/Basic/DiagnosticSemaKinds.td | 5 ++-- clang/lib/Sema/SemaDecl.cpp | 24 ++++++++----------- .../SemaCXX/ms_struct-bitfield-padding.cpp | 16 ++++++------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 98ed070e398a50..ce4f68bbb8bfc0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6423,8 +6423,9 @@ def warn_signed_bitfield_enum_conversion : Warning< def note_change_bitfield_sign : Note< "consider making the bit-field type %select{unsigned|signed}0">; def warn_ms_bitfield_mismatched_storage_packing : Warning< - "bit-field %0 of type %1 has a different storage size (%2 vs %3 bytes) than the " - "preceding bit-field and may not be packed under MSVC ABI">, + "bit-field %0 of type %1 has a different storage size than the " + "preceding bit-field (%2 vs %3 bytes) and will not be packed under " + "the MSVC ABI">, InGroup<MSBitfieldCompatibility>, DefaultIgnore; def note_ms_bitfield_mismatched_storage_size_previous : Note< "preceding bit-field %0 declared here with type %1">; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 123e061404add0..a71c31b0a5ae36 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19016,7 +19016,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Verify that all the fields are okay. SmallVector<FieldDecl*, 32> RecFields; - std::optional<const FieldDecl *> PreviousField; + const FieldDecl *PreviousField = nullptr; for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); i != end; PreviousField = cast<FieldDecl>(*i), ++i) { FieldDecl *FD = cast<FieldDecl>(*i); @@ -19229,26 +19229,22 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (Record && FD->getType().isVolatileQualified()) Record->setHasVolatileMember(true); auto IsNonDependentBitField = [](const FieldDecl *FD) { - if (!FD->isBitField()) - return false; - if (FD->getType()->isDependentType()) - return false; - return true; + return FD->isBitField() && !FD->getType()->isDependentType(); }; if (Record && PreviousField && IsNonDependentBitField(FD) && - IsNonDependentBitField(*PreviousField)) { - unsigned FDStorageSize = - Context.getTypeSizeInChars(FD->getType()).getQuantity(); - unsigned PreviousFieldStorageSize = - Context.getTypeSizeInChars((*PreviousField)->getType()).getQuantity(); + IsNonDependentBitField(PreviousField)) { + CharUnits FDStorageSize = Context.getTypeSizeInChars(FD->getType()); + CharUnits PreviousFieldStorageSize = + Context.getTypeSizeInChars(PreviousField->getType()); if (FDStorageSize != PreviousFieldStorageSize) { Diag(FD->getLocation(), diag::warn_ms_bitfield_mismatched_storage_packing) - << FD << FD->getType() << FDStorageSize << PreviousFieldStorageSize; - Diag((*PreviousField)->getLocation(), + << FD << FD->getType() << FDStorageSize.getQuantity() + << PreviousFieldStorageSize.getQuantity(); + Diag(PreviousField->getLocation(), diag::note_ms_bitfield_mismatched_storage_size_previous) - << *PreviousField << (*PreviousField)->getType(); + << PreviousField << PreviousField->getType(); } } // Keep track of the number of named members. diff --git a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp index 001086de5bbd10..11a786d47dd0ac 100644 --- a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp +++ b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp @@ -55,7 +55,7 @@ static_assert(sizeof(F) == 4); struct G { EnumU32_1 a : 15; EnumU64 b : 15; - // expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size (8 vs 4 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size than the preceding bit-field (8 vs 4 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}} }; @@ -76,7 +76,7 @@ struct I { EnumU8 a : 3; EnumI8 b : 5; EnumU32_1 c : 10; - // expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size (4 vs 1 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size than the preceding bit-field (4 vs 1 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'b' declared here with type 'EnumI8'}} }; #ifdef MS_BITFIELDS @@ -116,10 +116,10 @@ static_assert(sizeof(M) == 4); struct N { EnumU32_1 a : 10; EnumU64 b : 10; - // expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size (8 vs 4 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size than the preceding bit-field (8 vs 4 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}} EnumU32_1 c : 10; - // expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size (4 vs 8 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size than the preceding bit-field (4 vs 8 bytes) and will not be packed under the MSVC ABI}} // expected-note@-5 {{preceding bit-field 'b' declared here with type 'EnumU64'}} }; @@ -132,7 +132,7 @@ static_assert(sizeof(N) == 8); struct O { EnumU16 a : 10; EnumU32_1 b : 10; - // expected-warning@-1 {{bit-field 'b' of type 'EnumU32_1' has a different storage size (4 vs 2 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'b' of type 'EnumU32_1' has a different storage size than the preceding bit-field (4 vs 2 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU16'}} }; #ifdef MS_BITFIELDS @@ -144,7 +144,7 @@ static_assert(sizeof(O) == 4); struct P { EnumU32_1 a : 10; EnumU16 b : 10; - // expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size (2 vs 4 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size than the preceding bit-field (2 vs 4 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}} }; #ifdef MS_BITFIELDS @@ -156,7 +156,7 @@ static_assert(sizeof(P) == 4); struct Q { EnumU8 a : 6; EnumU16 b : 6; - // expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size (2 vs 1 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size than the preceding bit-field (2 vs 1 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU8'}} }; #ifdef MS_BITFIELDS @@ -169,7 +169,7 @@ struct R { EnumU16 a : 9; EnumU16 b : 9; EnumU8 c : 6; - // expected-warning@-1 {{bit-field 'c' of type 'EnumU8' has a different storage size (1 vs 2 bytes) than the preceding bit-field and may not be packed under MSVC ABI}} + // expected-warning@-1 {{bit-field 'c' of type 'EnumU8' has a different storage size than the preceding bit-field (1 vs 2 bytes) and will not be packed under the MSVC ABI}} // expected-note@-3 {{preceding bit-field 'b' declared here with type 'EnumU16'}} }; >From a18c032c7b7b57be64d0f60aa7768b078adae992 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Sun, 1 Dec 2024 23:23:47 -0800 Subject: [PATCH 3/4] Documentation and renaming --- clang/include/clang/Basic/DiagnosticGroups.td | 45 ++++++++++++++++++- .../SemaCXX/ms_struct-bitfield-padding.cpp | 2 +- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 69fae8c650ec9c..7e679169302fbd 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -631,7 +631,50 @@ def Packed : DiagGroup<"packed", [PackedNonPod]>; def PaddedBitField : DiagGroup<"padded-bitfield">; def Padded : DiagGroup<"padded", [PaddedBitField]>; def UnalignedAccess : DiagGroup<"unaligned-access">; -def MSBitfieldCompatibility : DiagGroup<"ms-bitfield-packing-compatibility">; +def MSBitfieldCompatibility : DiagGroup<"ms-bitfield-compatibility"> { + code Documentation = [{ + Under the MSVC ABI adjacemt bit-fields are not packed if the underlying type + has a different storage size. This warning indicates that a pair of adjacent + bit-fields may not pack in the same way due to this behavioural difference. + + This can occur when mixing different types explicitly: + + .. code-block:: c++ + + struct S { + uint16_t field1 : 1; + uint32_t field2 : 1; + }; + + or more subtly through enums + + .. code-block:: c++ + + enum Enum1 { /* ... */ }; + enum class Enum2 : unsigned char { /* ... */ }; + struct S { + Enum1 field1 : 1; + Enum2 field2 : 1; + }; + + In each of these cases under the MSVC ABI the second bit-field will not be + packed with the preceding bit-field, and instead will be aligned as if the + fields were each separately defined integer fields of their respective storage + size. For binary compatibility this is obviously and observably incompatible, + however where bit-fields are being used solely for memory use reduction this + incomplete packing may silently increase the size of objects vs what is + expected. + + This issue can be addressed by ensuring the storage type of each bit-field is + the same, either by explicitly using the same integer type, or in the case of + enum types declaring the enum types with the same storage size. For enum types + where you cannot specify the underlying type, the options are to either switch + to int sized storage for all specifiers or to resort to declaring the + bit-fields with explicit integer storage types and cast in and out of the field. + If such a solution is required the `preferred_type` attribute can be used to + convey the actual field type to debuggers and other tooling. + }]; +} def PessimizingMove : DiagGroup<"pessimizing-move">; def ReturnStdMove : DiagGroup<"return-std-move">; diff --git a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp index 11a786d47dd0ac..fd1eb30bfe3769 100644 --- a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp +++ b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wms-bitfield-packing-compatibility -verify -triple armv8 -std=c++23 %s +// RUN: %clang_cc1 -fsyntax-only -Wms-bitfield-compatibility -verify -triple armv8 -std=c++23 %s // RUN: %clang_cc1 -fsyntax-only -DMS_BITFIELDS -mms-bitfields -verify=msbitfields -triple armv8-apple-macos10.15 -std=c++23 %s // msbitfields-no-diagnostics >From 75a46fe44b70f565bbe7f1ac0ee1ddf1bb0c171e Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Sun, 1 Dec 2024 23:30:16 -0800 Subject: [PATCH 4/4] Add release note --- clang/docs/ReleaseNotes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e44aefa90ab386..5605656c3df485 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -629,6 +629,9 @@ Improvements to Clang's diagnostics - Clang now diagnoses dangling references for C++20's parenthesized aggregate initialization (#101957). +- A new off-by-default warning ``-Wms-bitfield-compatibility`` has been added to alert to cases where bit-field + packing may differ under the MS struct ABI (#GH117428). + Improvements to Clang's time-trace ---------------------------------- _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits