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">; 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; +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; // 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; 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; def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, 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: 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: 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}} +};