erik.pilkington created this revision.
erik.pilkington added reviewers: rjmccall, steven_wu.
Herald added subscribers: ributzka, dexonsmith, jkorous.
Instead, recommend using a real boolean type. Its possible to get away with 
BOOL:1, if you only read from it in a context where its contextually converted 
to bool, but its still broken if you, for instance, store it into a BOOL 
variable or try to compare it with another BOOL. Given that, I don't think 
there is any good reason to use it when there are better alternatives available.

rdar://29707989


https://reviews.llvm.org/D77070

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaObjC/signed-char-bool-bitfield-fixit.m
  clang/test/SemaObjC/signed-char-bool-bitfield.m

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
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/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 <stdbool.h>, 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/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/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5471,6 +5471,10 @@
   InGroup<BitFieldEnumConversion>, 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<ObjCSignedCharBoolBitfield>;
 
 def warn_missing_braces : Warning<
   "suggest braces around initialization of subobject">,
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">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D77070: [SemaObjC]... Erik Pilkington via Phabricator via cfe-commits

Reply via email to