@@ -631,7 +631,50 @@ def Packed : DiagGroup<"packed", [PackedNonPod]>;
631631def PaddedBitField : DiagGroup<"padded-bitfield">;
632632def Padded : DiagGroup<"padded", [PaddedBitField]>;
633633def UnalignedAccess : DiagGroup<"unaligned-access">;
634- def MSBitfieldCompatibility : DiagGroup<"ms-bitfield-packing-compatibility">;
634+ def MSBitfieldCompatibility : DiagGroup<"ms-bitfield-compatibility"> {
635+ code Documentation = [{
636+ Under the MSVC ABI adjacemt bit-fields are not packed if the underlying type
637+ has a different storage size. This warning indicates that a pair of adjacent
638+ bit-fields may not pack in the same way due to this behavioural difference.
639+
640+ This can occur when mixing different types explicitly:
641+
642+ .. code-block:: c++
643+
644+ struct S {
645+ uint16_t field1 : 1;
646+ uint32_t field2 : 1;
647+ };
648+
649+ or more subtly through enums
650+
651+ .. code-block:: c++
652+
653+ enum Enum1 { /* ... */ };
654+ enum class Enum2 : unsigned char { /* ... */ };
655+ struct S {
656+ Enum1 field1 : 1;
657+ Enum2 field2 : 1;
658+ };
659+
660+ In each of these cases under the MSVC ABI the second bit-field will not be
661+ packed with the preceding bit-field, and instead will be aligned as if the
662+ fields were each separately defined integer fields of their respective storage
663+ size. For binary compatibility this is obviously and observably incompatible,
664+ however where bit-fields are being used solely for memory use reduction this
665+ incomplete packing may silently increase the size of objects vs what is
666+ expected.
667+
668+ This issue can be addressed by ensuring the storage type of each bit-field is
669+ the same, either by explicitly using the same integer type, or in the case of
670+ enum types declaring the enum types with the same storage size. For enum types
671+ where you cannot specify the underlying type, the options are to either switch
672+ to int sized storage for all specifiers or to resort to declaring the
673+ bit-fields with explicit integer storage types and cast in and out of the field.
674+ If such a solution is required the `preferred_type` attribute can be used to
675+ convey the actual field type to debuggers and other tooling.
676+ }];
677+ }
635678
636679def PessimizingMove : DiagGroup<"pessimizing-move">;
637680def ReturnStdMove : DiagGroup<"return-std-move">;
0 commit comments