rcraik updated this revision to Diff 34339.
rcraik added a comment.

I've updated the message to make it a bit clearer that this is a portability 
concern. Are there any further concerns with this patch?


http://reviews.llvm.org/D10018

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/Misc/warning-flags.c
  test/Sema/c11-bitfield-width.c

Index: test/Sema/c11-bitfield-width.c
===================================================================
--- test/Sema/c11-bitfield-width.c
+++ test/Sema/c11-bitfield-width.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c11
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c99
+
+struct A {
+  _Bool : 0;    // ok
+  _Bool : 3;    // expected-warning {{size of anonymous bit-field (3 bits) exceeds the minimum width required to represent all valid values of that bit-field type}}
+  _Bool : 5;    // expected-warning {{size of anonymous bit-field (5 bits) exceeds the minimum width required to represent all valid values of that bit-field type}}
+  _Bool : 7;    // expected-warning {{size of anonymous bit-field (7 bits) exceeds the minimum width required to represent all valid values of that bit-field type}}
+  _Bool a : 1;  // ok
+  _Bool b : 2;  // expected-warning {{size of bit-field 'b' (2 bits) exceeds the minimum width required to represent all valid values of that bit-field type}}
+  _Bool c : 4;  // expected-warning {{size of bit-field 'c' (4 bits) exceeds the minimum width required to represent all valid values of that bit-field type}}
+  _Bool d : 8;  // expected-warning {{size of bit-field 'd' (8 bits) exceeds the minimum width required to represent all valid values of that bit-field type}}
+};
Index: test/Misc/warning-flags.c
===================================================================
--- test/Misc/warning-flags.c
+++ test/Misc/warning-flags.c
@@ -18,7 +18,7 @@
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (92):
+CHECK: Warnings without flags (90):
 CHECK-NEXT:   ext_excess_initializers
 CHECK-NEXT:   ext_excess_initializers_in_char_array_initializer
 CHECK-NEXT:   ext_expected_semi_decl_list
@@ -44,10 +44,8 @@
 CHECK-NEXT:   pp_pragma_sysheader_in_main_file
 CHECK-NEXT:   w_asm_qualifier_ignored
 CHECK-NEXT:   warn_accessor_property_type_mismatch
-CHECK-NEXT:   warn_anon_bitfield_width_exceeds_type_size
 CHECK-NEXT:   warn_arcmt_nsalloc_realloc
 CHECK-NEXT:   warn_asm_label_on_auto_decl
-CHECK-NEXT:   warn_bitfield_width_exceeds_type_size
 CHECK-NEXT:   warn_c_kext
 CHECK-NEXT:   warn_call_to_pure_virtual_member_function_from_ctor_dtor
 CHECK-NEXT:   warn_call_wrong_number_of_arguments
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -12604,6 +12604,20 @@
         Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size)
           << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;        
     }
+    // C11 6.7.2.1p4 + footnote 122/C99 6.7.2.1p3 - the width of a bitfield
+    // of type _Bool may be erroneous if it exceeds 1 bit.
+    // Warn about _Bool bitfields > 1 bit as they will not be portable across
+    // different platforms
+    if ((getLangOpts().C11 || getLangOpts().C99) && 
+        FieldTy->isBooleanType() &&
+        Value.getZExtValue() > 1) {
+      if (FieldName)
+        Diag(FieldLoc, diag::warn_bitfield_width_longer_than_necessary)
+            << FieldName << (unsigned)Value.getZExtValue();
+      else
+        Diag(FieldLoc, diag::warn_anon_bitfield_width_longer_than_necessary)
+            << (unsigned)Value.getZExtValue();
+    }
   }
 
   return BitWidth;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4317,14 +4317,20 @@
   "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">;
 def err_incorrect_number_of_vector_initializers : Error<
   "number of elements must be either one or match the size of the vector">;
+def warn_bitfield_width_longer_than_necessary : Warning<
+  "size of bit-field %0 (%1 bits) exceeds the minimum width required to "
+  "represent all valid values of that bit-field type">, InGroup<BitFieldWidth>;
+def warn_anon_bitfield_width_longer_than_necessary : Warning<
+  "size of anonymous bit-field (%0 bits) exceeds the minimum width required to "
+  "represent all valid values of that bit-field type">, InGroup<BitFieldWidth>;
 
 // Used by C++ which allows bit-fields that are wider than the type.
 def warn_bitfield_width_exceeds_type_size: Warning<
   "size of bit-field %0 (%1 bits) exceeds the size of its type; value will be "
-  "truncated to %2 bits">;
+  "truncated to %2 bits">, InGroup<BitFieldWidth>;
 def warn_anon_bitfield_width_exceeds_type_size : Warning<
   "size of anonymous bit-field (%0 bits) exceeds size of its type; value will "
-  "be truncated to %1 bits">;
+  "be truncated to %1 bits">, InGroup<BitFieldWidth>;
 
 def warn_missing_braces : Warning<
   "suggest braces around initialization of subobject">,
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -32,6 +32,7 @@
 def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
 def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
 def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
+def BitFieldWidth : DiagGroup<"bitfield-width">;
 def ConstantConversion :
   DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
 def LiteralConversion : DiagGroup<"literal-conversion">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to