Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -1082,11 +1082,13 @@ ObjCStringComparison ]>; +def ObjCSignedCharBoolBitfield : DiagGroup<"objc-signed-char-bool-bitfield">; def ObjCSignedCharBool : DiagGroup<"objc-signed-char-bool", [ObjCSignedCharBoolImplicitIntConversion, ObjCSignedCharBoolImplicitFloatConversion, ObjCBoolConstantConversion, - TautologicalObjCBoolCompare]>; + TautologicalObjCBoolCompare, + ObjCSignedCharBoolBitfield]>; // Inline ASM warnings. def ASMOperandWidths : DiagGroup<"asm-operand-widths">; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5471,6 +5471,10 @@ InGroup, DefaultIgnore; def note_change_bitfield_sign : Note< "consider making the bitfield type %select{unsigned|signed}0">; +def warn_objc_signed_char_bool_bitfield : Warning< + "BOOL bit-field of width 1 cannot represent YES when BOOL " + "is a signed type">, + InGroup; def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11401,9 +11401,10 @@ /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. - /// Returns false on success. + /// Returns BitWidth on success. /// Can optionally return whether the bit-field is of width 0 - ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + ExprResult VerifyBitField(SourceLocation FieldLoc, SourceRange TypeRange, + IdentifierInfo *FieldName, QualType FieldTy, bool IsMsStruct, Expr *BitWidth, bool *ZeroWidth = nullptr); Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -16169,6 +16169,7 @@ // Note that FieldName may be null for anonymous bitfields. ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, + SourceRange TypeRange, IdentifierInfo *FieldName, QualType FieldTy, bool IsMsStruct, Expr *BitWidth, bool *ZeroWidth) { @@ -16259,6 +16260,16 @@ Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width) << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth; } + + if (getLangOpts().ObjC && NSAPIObj->isObjCBOOLType(FieldTy) && + FieldTy->isSpecificBuiltinType(BuiltinType::SChar) && + Value == 1) { + auto Builder = Diag(FieldLoc, diag::warn_objc_signed_char_bool_bitfield); + // The Foundation headers that define BOOL include , so its + // reasonable to assume that 'bool' is available. + if (TypeRange.isValid()) + Builder << FixItHint::CreateReplacement(TypeRange, "bool"); + } } return BitWidth; @@ -16485,7 +16496,8 @@ BitWidth = nullptr; // If this is declared as a bit-field, check the bit-field. if (BitWidth) { - BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, + BitWidth = VerifyBitField(Loc, TInfo->getTypeLoc().getSourceRange(), + II, T, Record->isMsStruct(Context), BitWidth, &ZeroWidth).get(); if (!BitWidth) { InvalidDecl = true; @@ -16676,7 +16688,8 @@ if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 - BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).get(); + BitWidth = VerifyBitField(Loc, TInfo->getTypeLoc().getSourceRange(), + II, T, /*IsMsStruct*/false, BitWidth).get(); if (!BitWidth) D.setInvalidType(); } else { Index: clang/test/SemaObjC/signed-char-bool-bitfield-fixit.m =================================================================== --- /dev/null +++ clang/test/SemaObjC/signed-char-bool-bitfield-fixit.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -Wobjc-signed-char-bool %s -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s + +typedef signed char BOOL; + +struct S { + BOOL bf : 1; + // CHECK: fix-it:"{{.*}}.m":{6:3-6:7}:"bool" +}; + +@interface X { + BOOL bf : 1; + // CHECK: fix-it:"{{.*}}.m":{11:3-11:7}:"bool" +} +@end Index: clang/test/SemaObjC/signed-char-bool-bitfield.m =================================================================== --- /dev/null +++ clang/test/SemaObjC/signed-char-bool-bitfield.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s -Wobjc-signed-char-bool +// RUN: %clang_cc1 -xobjective-c++ -verify %s -Wobjc-signed-char-bool + +typedef signed char BOOL; + +struct S { + BOOL b : 1; // expected-warning {{BOOL bit-field of width 1 cannot represent YES when BOOL is a signed type}} + BOOL b2 : 2; +}; + +@interface X { + BOOL b : 1; // expected-warning {{BOOL bit-field of width 1 cannot represent YES when BOOL is a signed type}} + BOOL b2 : 2; +} +@end