Author: Oliver Hunt
Date: 2025-04-20T14:16:51-07:00
New Revision: 3ac1aa4c88d4fe40166209cad616f4ae867c20a2

URL: 
https://github.com/llvm/llvm-project/commit/3ac1aa4c88d4fe40166209cad616f4ae867c20a2
DIFF: 
https://github.com/llvm/llvm-project/commit/3ac1aa4c88d4fe40166209cad616f4ae867c20a2.diff

LOG: [Clang] Consider preferred_type in bitfield warnings (#116760) (#116785)

Very simply extends the bitfield sema checks for assignment to fields
with a preferred type specified to consider the preferred type if the
decl storage type is not explicitly an enum type.

This does mean that if the preferred and explicit types have different
storage requirements we may not warn in all possible cases, but that's a
scenario for which the warnings are much more complex and confusing.

Added: 
    clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaChecking.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 25302764778d1..7417fdd71a392 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -395,6 +395,14 @@ Improvements to Clang's diagnostics
   constructors to initialize their non-modifiable members. The diagnostic is
   not new; being controlled via a warning group is what's new. Fixes #GH41104
 
+- Improved bit-field diagnostics to consider the type specified by the
+  ``preferred_type`` attribute. These diagnostics are controlled by the flags
+  ``-Wpreferred-type-bitfield-enum-conversion`` and
+  ``-Wpreferred-type-bitfield-width``. These warnings are on by default as they
+  they're only triggered if the authors are already making the choice to use
+  ``preferred_type`` attribute.
+
+
 Improvements to Clang's time-trace
 ----------------------------------
 

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index b234d60fee8fc..b29fe40b05c6f 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -49,6 +49,9 @@ def SingleBitBitFieldConstantConversion :
   DiagGroup<"single-bit-bitfield-constant-conversion">;
 def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion",
                                            
[SingleBitBitFieldConstantConversion]>;
+def PreferredTypeBitFieldEnumConversion
+    : DiagGroup<"preferred-type-bitfield-enum-conversion">;
+def PreferredTypeBitFieldWidth : DiagGroup<"preferred-type-bitfield-width">;
 def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
 def BitFieldWidth : DiagGroup<"bitfield-width">;
 def CompoundTokenSplitByMacro : DiagGroup<"compound-token-split-by-macro">;

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8b8d3d7f6903b..45b6e1dc29980 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6492,8 +6492,25 @@ def warn_signed_bitfield_enum_conversion : Warning<
   "signed bit-field %0 needs an extra bit to represent the largest positive "
   "enumerators of %1">,
   InGroup<BitFieldEnumConversion>, DefaultIgnore;
+def warn_preferred_type_bitfield_too_small_for_enum
+    : Warning<"bit-field %0 is not wide enough to store all enumerators of "
+              "preferred type %1">,
+      InGroup<PreferredTypeBitFieldEnumConversion>;
+def warn_preferred_type_unsigned_bitfield_assigned_signed_enum
+    : Warning<"assigning value of preferred signed enum type %1 to unsigned "
+              "bit-field %0; "
+              "negative enumerators of enum %1 will be converted to positive "
+              "values">,
+      InGroup<PreferredTypeBitFieldEnumConversion>;
+def warn_preferred_type_signed_bitfield_enum_conversion
+    : Warning<"signed bit-field %0 needs an extra bit to represent the largest 
"
+              "positive "
+              "enumerators of preferred type %1">,
+      InGroup<PreferredTypeBitFieldEnumConversion>;
 def note_change_bitfield_sign : Note<
   "consider making the bit-field type %select{unsigned|signed}0">;
+def note_bitfield_preferred_type
+    : Note<"preferred type for bit-field %0 specified here">;
 
 def warn_missing_braces : Warning<
   "suggest braces around initialization of subobject">,

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c48e009fd7242..b2b26a2c39cf2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11293,9 +11293,16 @@ static bool AnalyzeBitFieldAssignment(Sema &S, 
FieldDecl *Bitfield, Expr *Init,
     // The RHS is not constant.  If the RHS has an enum type, make sure the
     // bitfield is wide enough to hold all the values of the enum without
     // truncation.
-    if (const auto *EnumTy = OriginalInit->getType()->getAs<EnumType>()) {
+    const auto *EnumTy = OriginalInit->getType()->getAs<EnumType>();
+    const PreferredTypeAttr *PTAttr = nullptr;
+    if (!EnumTy) {
+      PTAttr = Bitfield->getAttr<PreferredTypeAttr>();
+      if (PTAttr)
+        EnumTy = PTAttr->getType()->getAs<EnumType>();
+    }
+    if (EnumTy) {
       EnumDecl *ED = EnumTy->getDecl();
-      bool SignedBitfield = BitfieldType->isSignedIntegerType();
+      bool SignedBitfield = BitfieldType->isSignedIntegerOrEnumerationType();
 
       // Enum types are implicitly signed on Windows, so check if there are any
       // negative enumerators to see if the enum was intended to be signed or
@@ -11309,12 +11316,18 @@ static bool AnalyzeBitFieldAssignment(Sema &S, 
FieldDecl *Bitfield, Expr *Init,
       // on Windows where unfixed enums always use an underlying type of 'int'.
       unsigned DiagID = 0;
       if (SignedEnum && !SignedBitfield) {
-        DiagID = diag::warn_unsigned_bitfield_assigned_signed_enum;
+        DiagID =
+            PTAttr == nullptr
+                ? diag::warn_unsigned_bitfield_assigned_signed_enum
+                : diag::
+                      
warn_preferred_type_unsigned_bitfield_assigned_signed_enum;
       } else if (SignedBitfield && !SignedEnum &&
                  ED->getNumPositiveBits() == FieldWidth) {
-        DiagID = diag::warn_signed_bitfield_enum_conversion;
+        DiagID =
+            PTAttr == nullptr
+                ? diag::warn_signed_bitfield_enum_conversion
+                : diag::warn_preferred_type_signed_bitfield_enum_conversion;
       }
-
       if (DiagID) {
         S.Diag(InitLoc, DiagID) << Bitfield << ED;
         TypeSourceInfo *TSI = Bitfield->getTypeSourceInfo();
@@ -11322,6 +11335,9 @@ static bool AnalyzeBitFieldAssignment(Sema &S, 
FieldDecl *Bitfield, Expr *Init,
             TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange();
         S.Diag(Bitfield->getTypeSpecStartLoc(), 
diag::note_change_bitfield_sign)
             << SignedEnum << TypeRange;
+        if (PTAttr)
+          S.Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
+              << ED;
       }
 
       // Compute the required bitwidth. If the enum has negative values, we 
need
@@ -11334,10 +11350,16 @@ static bool AnalyzeBitFieldAssignment(Sema &S, 
FieldDecl *Bitfield, Expr *Init,
       // Check the bitwidth.
       if (BitsNeeded > FieldWidth) {
         Expr *WidthExpr = Bitfield->getBitWidth();
-        S.Diag(InitLoc, diag::warn_bitfield_too_small_for_enum)
-            << Bitfield << ED;
+        auto DiagID =
+            PTAttr == nullptr
+                ? diag::warn_bitfield_too_small_for_enum
+                : diag::warn_preferred_type_bitfield_too_small_for_enum;
+        S.Diag(InitLoc, DiagID) << Bitfield << ED;
         S.Diag(WidthExpr->getExprLoc(), diag::note_widen_bitfield)
             << BitsNeeded << ED << WidthExpr->getSourceRange();
+        if (PTAttr)
+          S.Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
+              << ED;
       }
     }
 

diff  --git a/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp 
b/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp
new file mode 100644
index 0000000000000..5eaa3eb2d85e3
--- /dev/null
+++ b/clang/test/SemaCXX/bitfield-preferred-type-sizing.cpp
@@ -0,0 +1,411 @@
+// RUN: %clang_cc1 %s      -std=c++23 -triple=x86_64-apple-darwin10 
-fsyntax-only -verify=expected,bitfieldwarnings,cpp -Wno-unused-value 
-Wno-unused-but-set-variable -Wbitfield-width -Wbitfield-enum-conversion
+// RUN: %clang_cc1 %s      -std=c++23 -triple=x86_64-apple-darwin10 
-fsyntax-only -verify=expected,cpp -Wno-unused-value 
-Wno-unused-but-set-variable
+
+// RUN: %clang_cc1 %s -x c -std=c23   -triple=x86_64-apple-darwin10 
-fsyntax-only -verify=expected,c -Wno-unused-value -Wno-unused-but-set-variable
+// RUN: %clang_cc1 %s -x c -std=c23   -triple=x86_64-apple-darwin10 
-fsyntax-only -verify=expected,bitfieldwarnings,c -Wno-unused-value 
-Wno-unused-but-set-variable -Wbitfield-width -Wbitfield-enum-conversion
+
+
+typedef enum A {
+  A_a,
+  A_b,
+  A_c,
+  A_d
+} A;
+
+#ifdef __cplusplus
+#define DEFINE_ENUM(_Name, _Type, ...) enum class _Name : _Type { __VA_ARGS__ 
} ;
+#define ENUM_CLASS_REF(_Name, _Enum) _Name::_Enum
+#else
+#define DEFINE_ENUM(_Name, _Type, ...) typedef enum _Name : _Type { 
__VA_ARGS__ } _Name;
+#define ENUM_CLASS_REF(_Name, _Enum) _Enum
+#endif
+
+DEFINE_ENUM(B, int, B_a, B_b, B_c, B_d );
+DEFINE_ENUM(C, unsigned, C_a, C_b, C_c, C_d );
+DEFINE_ENUM(D, unsigned, D_a, D_b);
+
+// Not using templates here so we can more easily distinguish the responsible
+// party for each warning
+
+typedef struct S_A {
+  A field1 : 1; // #S_A_field1
+  A field2 : 2; // #S_A_field2
+  A field3 : 8; // #S_A_field3
+  __attribute__((preferred_type(A))) // #preferred_S_A_field4
+  unsigned field4 : 1; // #S_A_field4
+  __attribute__((preferred_type(A)))
+  unsigned field5 : 2; // #S_A_field5
+  __attribute__((preferred_type(A)))
+  unsigned field6 : 8; // #S_A_field6
+  __attribute__((preferred_type(A))) // #preferred_S_A_field7
+  int field7 : 1; // #S_A_field7
+  __attribute__((preferred_type(A))) // #preferred_S_A_field8
+  int field8 : 2; // #S_A_field8
+  __attribute__((preferred_type(A)))
+  int field9 : 8; // #S_A_field9
+  __attribute__((preferred_type(A)))
+  D field10 : 1; // #S_A_field10
+  __attribute__((preferred_type(A))) // #preferred_S_A_field11
+  D field11 : 2; // #S_A_field11
+  __attribute__((preferred_type(A)))
+  D field12 : 8; // #S_A_field12
+} S_A;
+
+typedef struct S_B {
+  B field1 : 1; // #S_B_field1
+  B field2 : 2; // #S_B_field2
+  B field3 : 8; // #S_B_field3
+  __attribute__((preferred_type(B))) // #preferred_S_B_field4
+  unsigned field4 : 1; // #S_B_field4
+  __attribute__((preferred_type(B)))
+  unsigned field5 : 2; // #S_B_field5
+  __attribute__((preferred_type(B)))
+  unsigned field6 : 8; // #S_B_field6
+  __attribute__((preferred_type(B))) // #preferred_S_B_field7
+  int field7 : 1; // #S_B_field7
+  __attribute__((preferred_type(B))) // #preferred_S_B_field8
+  int field8 : 2; // #S_B_field8
+  __attribute__((preferred_type(B)))
+  int field9 : 8; // #S_B_field9
+  __attribute__((preferred_type(B)))
+  D field10 : 1; // #S_B_field10
+  __attribute__((preferred_type(B))) // #preferred_S_B_field11
+  D field11 : 2; // #S_B_field11
+  __attribute__((preferred_type(B)))
+  D field12 : 8; // #S_B_field12
+} S_B;
+
+typedef struct S_C {
+  C field1 : 1; // #S_C_field1
+  C field2 : 2; // #S_C_field2
+  C field3 : 8; // #S_C_field3
+  __attribute__((preferred_type(C))) // #preferred_S_C_field4
+  unsigned field4 : 1; // #S_C_field4
+  __attribute__((preferred_type(C)))
+  unsigned field5 : 2; // #S_C_field5
+  __attribute__((preferred_type(C)))
+  unsigned field6 : 8; // #S_C_field6
+  __attribute__((preferred_type(C))) // #preferred_S_C_field7
+  int field7 : 1; // #S_C_field7
+  __attribute__((preferred_type(C))) // #preferred_S_C_field8
+  int field8 : 2; // #S_C_field8
+  __attribute__((preferred_type(C)))
+  int field9 : 8; // #S_C_field9
+  __attribute__((preferred_type(C)))
+  D field10 : 1; // #S_C_field10
+  __attribute__((preferred_type(C))) // #preferred_S_C_field11
+  D field11 : 2; // #S_C_field11
+  __attribute__((preferred_type(C)))
+  D field12 : 8; // #S_C_field12
+} S_C;
+
+void read_enumA(S_A *s) {
+  A x;
+  x = s->field1;
+  x = s->field2;
+  x = s->field3;
+  x = (A)s->field4;
+  x = (A)s->field5;
+  x = (A)s->field6;
+  x = (A)s->field7;
+  x = (A)s->field8;
+  x = (A)s->field9;
+  x = (A)s->field10;
+  x = (A)s->field11;
+  x = (A)s->field12;
+}
+
+void read_enumB(S_B *s) {
+  B x;
+  x = s->field1;
+  x = s->field2;
+  x = s->field3;
+  x = (B)s->field4;
+  x = (B)s->field5;
+  x = (B)s->field6;
+  x = (B)s->field7;
+  x = (B)s->field8;
+  x = (B)s->field9;
+  x = (B)s->field10;
+  x = (B)s->field11;
+  x = (B)s->field12;
+}
+
+void read_enumC(S_C *s) {
+  C x;
+  x = s->field1;
+  x = s->field2;
+  x = s->field3;
+  x = (C)s->field4;
+  x = (C)s->field5;
+  x = (C)s->field6;
+  x = (C)s->field7;
+  x = (C)s->field8;
+  x = (C)s->field9;
+  x = (C)s->field10;
+  x = (C)s->field11;
+  x = (C)s->field12;
+}
+
+void write_enumA(S_A *s, A x) {
+  s->field1 = x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to 
store all enumerators of 'A'}}
+  // bitfieldwarnings-note@#S_A_field1 {{widen this field to 2 bits to store 
all values of 'A'}}
+  s->field2 = x;
+  s->field3 = x;
+  s->field4 = x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field4' is not wide enough to 
store all enumerators of 'A'}}
+  // bitfieldwarnings-note@#S_A_field4 {{widen this field to 2 bits to store 
all values of 'A'}}
+  s->field5 = x;
+  s->field6 = x;
+  s->field7 = x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field7' is not wide enough to 
store all enumerators of 'A'}}
+  // bitfieldwarnings-note@#S_A_field7 {{widen this field to 2 bits to store 
all values of 'A'}}
+  s->field8 = x;
+  // bitfieldwarnings-warning@-1 {{signed bit-field 'field8' needs an extra 
bit to represent the largest positive enumerators of 'A'}}
+  // bitfieldwarnings-note@#S_A_field8 {{consider making the bit-field type 
unsigned}}
+  s->field9 = x;
+  s->field10 = (D)x;
+  s->field11 = (D)x;
+  s->field12 = (D)x;
+}
+
+void write_enumB(S_B *s, B x) {
+  s->field1 = x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to 
store all enumerators of 'B'}}
+  // bitfieldwarnings-note@#S_B_field1 {{widen this field to 2 bits to store 
all values of 'B'}}
+  s->field2 = x;
+  // bitfieldwarnings-warning@-1 {{signed bit-field 'field2' needs an extra 
bit to represent the largest positive enumerators of 'B'}}
+  // bitfieldwarnings-note@#S_B_field2 {{consider making the bit-field type 
unsigned}}
+  s->field3 = x;
+  s->field4 = (unsigned)x;
+  // expected-warning@-1 {{bit-field 'field4' is not wide enough to store all 
enumerators of preferred type 'B'}}
+  // expected-note@#S_B_field4 {{widen this field to 2 bits to store all 
values of 'B'}}
+  // expected-note@#preferred_S_B_field4 {{preferred type for bit-field 'B' 
specified here}}
+  s->field5 = (unsigned)x;
+  s->field6 = (unsigned)x;
+  s->field7 = (int)x;
+  // expected-warning@-1 {{bit-field 'field7' is not wide enough to store all 
enumerators of preferred type 'B'}}
+  // expected-note@#S_B_field7 {{widen this field to 2 bits to store all 
values of 'B'}}
+  // expected-note@#preferred_S_B_field7 {{preferred type for bit-field 'B' 
specified here}}
+  s->field8 = (int)x;
+  // expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to 
represent the largest positive enumerators of preferred type 'B'}}
+  // expected-note@#S_B_field8 {{consider making the bit-field type unsigned}}
+  // expected-note@#preferred_S_B_field8 {{preferred type for bit-field 'B' 
specified here}}
+  s->field9 = (int)x;
+  s->field10 = (D)x;
+  s->field11 = (D)x;
+  s->field12 = (D)x;
+}
+
+void write_enumC(S_C *s, C x) {
+  s->field1 = x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to 
store all enumerators of 'C'}}
+  // bitfieldwarnings-note@#S_C_field1 {{widen this field to 2 bits to store 
all values of 'C'}}
+  s->field2 = x;
+  s->field3 = x;
+  s->field4 = (unsigned)x;
+  // expected-warning@-1 {{bit-field 'field4' is not wide enough to store all 
enumerators of preferred type 'C'}}
+  // expected-note@#S_C_field4 {{widen this field to 2 bits to store all 
values of 'C'}}
+  // expected-note@#preferred_S_C_field4 {{preferred type for bit-field 'C' 
specified here}}
+  s->field5 = (unsigned)x;
+  s->field6 = (unsigned)x;
+  s->field7 = (int)x;
+  // expected-warning@-1 {{bit-field 'field7' is not wide enough to store all 
enumerators of preferred type 'C'}}
+  // expected-note@#S_C_field7 {{widen this field to 2 bits to store all 
values of 'C'}}
+  // expected-note@#preferred_S_C_field7 {{preferred type for bit-field 'C' 
specified here}}
+  s->field8 = (int)x;
+  // expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to 
represent the largest positive enumerators of preferred type 'C'}}
+  // expected-note@#S_C_field8 {{consider making the bit-field type unsigned}}
+  // expected-note@#preferred_S_C_field8 {{preferred type for bit-field 'C' 
specified here}}
+  s->field9 = (int)x;
+  s->field10 = (D)x;
+  s->field11 = (D)x;
+  s->field12 = (D)x;
+}
+
+void write_enum_intA(struct S_A *s, int x) {
+  s->field1 = (A)x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to 
store all enumerators of 'A'}}
+  // bitfieldwarnings-note@#S_A_field1 {{widen this field to 2 bits to store 
all values of 'A'}}
+  s->field2 = (A)x;
+  s->field3 = (A)x;
+  s->field4 = x;
+  // expected-warning@-1 {{bit-field 'field4' is not wide enough to store all 
enumerators of preferred type 'A'}}
+  // expected-note@#S_A_field4 {{widen this field to 2 bits to store all 
values of 'A'}}
+  // expected-note@#preferred_S_A_field4 {{preferred type for bit-field 'A' 
specified here}}
+  s->field5 = x;
+  s->field6 = x;
+  s->field7 = x;
+  // expected-warning@-1 {{bit-field 'field7' is not wide enough to store all 
enumerators of preferred type 'A'}}
+  // expected-note@#S_A_field7 {{widen this field to 2 bits to store all 
values of 'A'}}
+  // expected-note@#preferred_S_A_field7 {{preferred type for bit-field 'A' 
specified here}}
+  s->field8 = x;
+  // expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to 
represent the largest positive enumerators of preferred type 'A'}}
+  // expected-note@#S_A_field8 {{consider making the bit-field type unsigned}}
+  // expected-note@#preferred_S_A_field8 {{preferred type for bit-field 'A' 
specified here}}
+  s->field9 = x;
+  s->field10 = (D)x;
+  s->field11 = (D)x;
+  s->field12 = (D)x;
+}
+
+void write_enum_intB(struct S_B *s, int x) {
+  s->field1 = (B)x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to 
store all enumerators of 'B'}}
+  // bitfieldwarnings-note@#S_B_field1 {{widen this field to 2 bits to store 
all values of 'B'}}
+  s->field2 = (B)x;
+  // bitfieldwarnings-warning@-1 {{signed bit-field 'field2' needs an extra 
bit to represent the largest positive enumerators of 'B'}}
+  // bitfieldwarnings-note@#S_B_field2 {{consider making the bit-field type 
unsigned}}
+  s->field3 = (B)x;
+  s->field4 = x;
+  // expected-warning@-1 {{bit-field 'field4' is not wide enough to store all 
enumerators of preferred type 'B'}}
+  // expected-note@#S_B_field4 {{widen this field to 2 bits to store all 
values of 'B'}}
+  // expected-note@#preferred_S_B_field4 {{preferred type for bit-field 'B' 
specified here}}
+  s->field5 = x;
+  s->field6 = x;
+  s->field7 = x;
+  // expected-warning@-1 {{bit-field 'field7' is not wide enough to store all 
enumerators of preferred type 'B'}}
+  // expected-note@#S_B_field7 {{widen this field to 2 bits to store all 
values of 'B'}}
+  // expected-note@#preferred_S_B_field7 {{preferred type for bit-field 'B' 
specified here}}
+  s->field8 = x;
+  // expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to 
represent the largest positive enumerators of preferred type 'B'}}
+  // expected-note@#S_B_field8 {{consider making the bit-field type unsigned}}
+  // expected-note@#preferred_S_B_field8 {{preferred type for bit-field 'B' 
specified here}}
+  s->field9 = x;
+  s->field10 = (D)x;
+  s->field11 = (D)x;
+  s->field12 = (D)x;
+}
+
+void write_enum_intC(struct S_C *s, int x) {
+  s->field1 = (C)x;
+  // bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to 
store all enumerators of 'C'}}
+  // bitfieldwarnings-note@#S_C_field1 {{widen this field to 2 bits to store 
all values of 'C'}}
+  s->field2 = (C)x;
+  s->field3 = (C)x;
+  s->field4 = x;
+  // expected-warning@-1 {{bit-field 'field4' is not wide enough to store all 
enumerators of preferred type 'C'}}
+  // expected-note@#S_C_field4 {{widen this field to 2 bits to store all 
values of 'C'}}
+  // expected-note@#preferred_S_C_field4 {{preferred type for bit-field 'C' 
specified here}}
+  s->field5 = x;
+  s->field6 = x;
+  s->field7 = x;
+  // expected-warning@-1 {{bit-field 'field7' is not wide enough to store all 
enumerators of preferred type 'C'}}
+  // expected-note@#S_C_field7 {{widen this field to 2 bits to store all 
values of 'C'}}
+  // expected-note@#preferred_S_C_field7 {{preferred type for bit-field 'C' 
specified here}}
+  s->field8 = x;
+  // expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to 
represent the largest positive enumerators of preferred type 'C'}}
+  // expected-note@#S_C_field8 {{consider making the bit-field type unsigned}}
+  // expected-note@#preferred_S_C_field8 {{preferred type for bit-field 'C' 
specified here}}
+  s->field9 = x;
+  s->field10 = (D)x;
+  s->field11 = (D)x;
+  s->field12 = (D)x;
+}
+
+void write_low_constantA(S_A *s) {
+  s->field1 = A_a;
+  s->field2 = A_a;
+  s->field3 = A_a;
+  s->field4 = A_a;
+  s->field5 = A_a;
+  s->field6 = A_a;
+  s->field7 = A_a;
+  s->field8 = A_a;
+  s->field9 = A_a;
+  s->field10 = (D)A_a;
+  s->field11 = (D)A_a;
+  s->field12 = (D)A_a;
+};
+
+void write_low_constantB(S_B *s) {
+  s->field1 = ENUM_CLASS_REF(B, B_a);
+  s->field2 = ENUM_CLASS_REF(B, B_a);
+  s->field3 = ENUM_CLASS_REF(B, B_a);
+  s->field4 = (unsigned)ENUM_CLASS_REF(B, B_a);
+  s->field5 = (unsigned)ENUM_CLASS_REF(B, B_a);
+  s->field6 = (unsigned)ENUM_CLASS_REF(B, B_a);
+  s->field7 = (int)ENUM_CLASS_REF(B, B_a);
+  s->field8 = (int)ENUM_CLASS_REF(B, B_a);
+  s->field9 = (int)ENUM_CLASS_REF(B, B_a);
+  s->field10 = (D)ENUM_CLASS_REF(B, B_a);
+  s->field11 = (D)ENUM_CLASS_REF(B, B_a);
+  s->field12 = (D)ENUM_CLASS_REF(B, B_a);
+};
+
+void write_low_constantC(S_C *s) {
+  s->field1 = ENUM_CLASS_REF(C, C_a);
+  s->field2 = ENUM_CLASS_REF(C, C_a);
+  s->field3 = ENUM_CLASS_REF(C, C_a);
+  s->field4 = (unsigned)ENUM_CLASS_REF(C, C_a);
+  s->field5 = (unsigned)ENUM_CLASS_REF(C, C_a);
+  s->field6 = (unsigned)ENUM_CLASS_REF(C, C_a);
+  s->field7 = (int)ENUM_CLASS_REF(C, C_a);
+  s->field8 = (int)ENUM_CLASS_REF(C, C_a);
+  s->field9 = (int)ENUM_CLASS_REF(C, C_a);
+  s->field10 = (D)ENUM_CLASS_REF(C, C_a);
+  s->field11 = (D)ENUM_CLASS_REF(C, C_a);
+  s->field12 = (D)ENUM_CLASS_REF(C, C_a);
+};
+
+void write_high_constantA(S_A *s) {
+  s->field1 = A_d;
+  // cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value 
from 3 to 1}}
+  // c-warning@-2 {{implicit truncation from 'int' to bit-field changes value 
from 3 to 1}}
+  s->field2 = A_d;
+  s->field3 = A_d;
+  s->field4 = A_d;
+  // cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value 
from 3 to 1}}
+  // c-warning@-2 {{implicit truncation from 'int' to bit-field changes value 
from 3 to 1}}
+  s->field5 = A_d;
+  s->field6 = A_d;
+  s->field7 = A_d;
+  // cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value 
from 3 to -1}}
+  // c-warning@-2 {{implicit truncation from 'int' to bit-field changes value 
from 3 to -1}}
+  s->field8 = A_d;
+  // cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value 
from 3 to -1}}
+  // c-warning@-2 {{implicit truncation from 'int' to bit-field changes value 
from 3 to -1}}
+  s->field9 = A_d;
+  s->field10 = (D)A_d;
+  // cpp-warning@-1 {{implicit truncation from 'D' to bit-field changes value 
from 3 to 1}}
+  // c-warning@-2 {{implicit truncation from 'D' (aka 'enum D') to bit-field 
changes value from 3 to 1}}
+  s->field11 = (D)A_d;
+  s->field12 = (D)A_d;
+};
+
+void write_high_constantB(S_B *s) {
+  s->field1 = ENUM_CLASS_REF(B, B_d);
+  // cpp-warning@-1 {{implicit truncation from 'B' to bit-field changes value 
from 3 to 1}}
+  // c-warning@-2 {{implicit truncation from 'int' to bit-field changes value 
from 3 to -1}}
+  s->field2 = ENUM_CLASS_REF(B, B_d);
+  // c-warning@-1 {{implicit truncation from 'int' to bit-field changes value 
from 3 to -1}}
+  s->field3 = ENUM_CLASS_REF(B, B_d);
+  s->field4 = (unsigned)ENUM_CLASS_REF(B, B_d);
+  // expected-warning@-1 {{implicit truncation from 'unsigned int' to 
bit-field changes value from 3 to 1}}
+  s->field5 = (unsigned)ENUM_CLASS_REF(B, B_d);
+  s->field6 = (unsigned)ENUM_CLASS_REF(B, B_d);
+  s->field7 = (int)ENUM_CLASS_REF(B, B_d);
+  // expected-warning@-1 {{implicit truncation from 'int' to bit-field changes 
value from 3 to -1}}
+  s->field8 = (int)ENUM_CLASS_REF(B, B_d);
+  // expected-warning@-1 {{implicit truncation from 'int' to bit-field changes 
value from 3 to -1}}
+  s->field9 = (int)ENUM_CLASS_REF(B, B_d);
+};
+
+
+void write_high_constantC(S_C *s) {
+  s->field1 = ENUM_CLASS_REF(C, C_d);
+  // cpp-warning@-1 {{implicit truncation from 'C' to bit-field changes value 
from 3 to 1}}
+  // c-warning@-2 {{implicit truncation from 'unsigned int' to bit-field 
changes value from 3 to 1}}
+  s->field2 = ENUM_CLASS_REF(C, C_d);
+  s->field3 = ENUM_CLASS_REF(C, C_d);
+  s->field4 = (unsigned)ENUM_CLASS_REF(C, C_d);
+  // expected-warning@-1 {{implicit truncation from 'unsigned int' to 
bit-field changes value from 3 to 1}}
+  s->field5 = (unsigned)ENUM_CLASS_REF(C, C_d);
+  s->field6 = (unsigned)ENUM_CLASS_REF(C, C_d);
+  s->field7 = (int)ENUM_CLASS_REF(C, C_d);
+  // expected-warning@-1 {{implicit truncation from 'int' to bit-field changes 
value from 3 to -1}}
+  s->field8 = (int)ENUM_CLASS_REF(C, C_d);
+  // expected-warning@-1 {{implicit truncation from 'int' to bit-field changes 
value from 3 to -1}}
+  s->field9 = (int)ENUM_CLASS_REF(C, C_d);
+};


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to