Mordante created this revision.
Mordante added reviewers: rsmith, majnemer, aaron.ballman.
Mordante added a project: clang.

Note: I'm not entirely happy with the text of the diagnostics and I'm open to 
suggestions.

Fixes PR23505: Large bitfield: Assertion `getActiveBits() <= 64 && "Too many 
bits for uint64_t"' failed


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71142

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Sema/bitfield.c


Index: clang/test/Sema/bitfield.c
===================================================================
--- clang/test/Sema/bitfield.c
+++ clang/test/Sema/bitfield.c
@@ -28,6 +28,12 @@
 
   _Bool : 2;   // expected-error {{width of anonymous bit-field (2 bits) 
exceeds width of its type (1 bit)}}
   _Bool h : 5; // expected-error {{width of bit-field 'h' (5 bits) exceeds 
width of its type (1 bit)}}
+
+  // PR23505
+  _Bool : 1 + (unsigned __int128)0xffffffffffffffff;   // expected-error 
{{width of anonymous bit-field doesn't fit in a 64 bit unsigned integer}}
+  _Bool i : 1 + (unsigned __int128)0xffffffffffffffff; // expected-error 
{{width of bit-field 'i' doesn't fit in a 64 bit unsigned integer}}
+  int : 1 + (unsigned __int128)0xffffffffffffffff;     // expected-error 
{{width of anonymous bit-field doesn't fit in a 64 bit unsigned integer}}
+  int j : 1 + (unsigned __int128)0xffffffffffffffff;   // expected-error 
{{width of bit-field 'j' doesn't fit in a 64 bit unsigned integer}}
 };
 
 struct b {unsigned x : 2;} x;
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -15842,6 +15842,17 @@
     uint64_t TypeWidth = Context.getIntWidth(FieldTy);
     bool BitfieldIsOverwide = Value.ugt(TypeWidth);
 
+    // Don't accept too wide bit-fields they will cause assertion failures
+    // when used.
+    if (BitfieldIsOverwide && Value.ugt(UINT64_MAX)) {
+      if (FieldName)
+        return Diag(FieldLoc, diag::warn_bitfield_width_exceeds_maximum_width)
+               << FieldName;
+
+      return Diag(FieldLoc,
+                  diag::warn_anon_bitfield_width_exceeds_maximum_width);
+    }
+
     // Over-wide bitfields are an error in C or when using the MSVC bitfield
     // ABI.
     bool CStdConstraintViolation =
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5183,6 +5183,10 @@
   "number of elements must be either one or match the size of the vector">;
 
 // Used by C++ which allows bit-fields that are wider than the type.
+def warn_bitfield_width_exceeds_maximum_width: Error<
+  "width of bit-field %0 doesn't fit in a 64 bit unsigned integer">;
+def warn_anon_bitfield_width_exceeds_maximum_width : Error<
+  "width of anonymous bit-field doesn't fit in a 64 bit unsigned integer">;
 def warn_bitfield_width_exceeds_type_width: Warning<
   "width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
   "be truncated to %2 bit%s2">, InGroup<BitFieldWidth>;


Index: clang/test/Sema/bitfield.c
===================================================================
--- clang/test/Sema/bitfield.c
+++ clang/test/Sema/bitfield.c
@@ -28,6 +28,12 @@
 
   _Bool : 2;   // expected-error {{width of anonymous bit-field (2 bits) exceeds width of its type (1 bit)}}
   _Bool h : 5; // expected-error {{width of bit-field 'h' (5 bits) exceeds width of its type (1 bit)}}
+
+  // PR23505
+  _Bool : 1 + (unsigned __int128)0xffffffffffffffff;   // expected-error {{width of anonymous bit-field doesn't fit in a 64 bit unsigned integer}}
+  _Bool i : 1 + (unsigned __int128)0xffffffffffffffff; // expected-error {{width of bit-field 'i' doesn't fit in a 64 bit unsigned integer}}
+  int : 1 + (unsigned __int128)0xffffffffffffffff;     // expected-error {{width of anonymous bit-field doesn't fit in a 64 bit unsigned integer}}
+  int j : 1 + (unsigned __int128)0xffffffffffffffff;   // expected-error {{width of bit-field 'j' doesn't fit in a 64 bit unsigned integer}}
 };
 
 struct b {unsigned x : 2;} x;
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -15842,6 +15842,17 @@
     uint64_t TypeWidth = Context.getIntWidth(FieldTy);
     bool BitfieldIsOverwide = Value.ugt(TypeWidth);
 
+    // Don't accept too wide bit-fields they will cause assertion failures
+    // when used.
+    if (BitfieldIsOverwide && Value.ugt(UINT64_MAX)) {
+      if (FieldName)
+        return Diag(FieldLoc, diag::warn_bitfield_width_exceeds_maximum_width)
+               << FieldName;
+
+      return Diag(FieldLoc,
+                  diag::warn_anon_bitfield_width_exceeds_maximum_width);
+    }
+
     // Over-wide bitfields are an error in C or when using the MSVC bitfield
     // ABI.
     bool CStdConstraintViolation =
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5183,6 +5183,10 @@
   "number of elements must be either one or match the size of the vector">;
 
 // Used by C++ which allows bit-fields that are wider than the type.
+def warn_bitfield_width_exceeds_maximum_width: Error<
+  "width of bit-field %0 doesn't fit in a 64 bit unsigned integer">;
+def warn_anon_bitfield_width_exceeds_maximum_width : Error<
+  "width of anonymous bit-field doesn't fit in a 64 bit unsigned integer">;
 def warn_bitfield_width_exceeds_type_width: Warning<
   "width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
   "be truncated to %2 bit%s2">, InGroup<BitFieldWidth>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to