r365518 - [ObjC] Add a warning for implicit conversions of a constant non-boolean value to BOOL

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 9 10:29:41 PDT 2019


Author: epilk
Date: Tue Jul  9 10:29:40 2019
New Revision: 365518

URL: http://llvm.org/viewvc/llvm-project?rev=365518&view=rev
Log:
[ObjC] Add a warning for implicit conversions of a constant non-boolean value to BOOL

rdar://51954400

Differential revision: https://reviews.llvm.org/D63912

Added:
    cfe/trunk/test/Sema/objc-bool-constant-conversion-fixit.m
    cfe/trunk/test/Sema/objc-bool-constant-conversion.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaChecking.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=365518&r1=365517&r2=365518&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Jul  9 10:29:40 2019
@@ -48,8 +48,10 @@ def BitFieldWidth : DiagGroup<"bitfield-
 def CoroutineMissingUnhandledException :
   DiagGroup<"coroutine-missing-unhandled-exception">;
 def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException]>;
-def ConstantConversion :
-  DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
+def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">;
+def ConstantConversion : DiagGroup<"constant-conversion",
+                                   [BitFieldConstantConversion,
+                                    ObjCBoolConstantConversion]>;
 def LiteralConversion : DiagGroup<"literal-conversion">;
 def StringConversion : DiagGroup<"string-conversion">;
 def SignConversion : DiagGroup<"sign-conversion">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=365518&r1=365517&r2=365518&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jul  9 10:29:40 2019
@@ -3248,6 +3248,10 @@ def warn_impcast_integer_precision_const
 def warn_impcast_bitfield_precision_constant : Warning<
   "implicit truncation from %2 to bit-field changes value from %0 to %1">,
   InGroup<BitFieldConstantConversion>;
+def warn_impcast_constant_int_to_objc_bool : Warning<
+  "implicit conversion from constant value %0 to BOOL; "
+  "the only well defined values for BOOL are YES and NO">,
+  InGroup<ObjCBoolConstantConversion>;
 
 def warn_impcast_fixed_point_range : Warning<
   "implicit conversion from %0 cannot fit within the range of values for %1">,

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=365518&r1=365517&r2=365518&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Jul  9 10:29:40 2019
@@ -11149,6 +11149,11 @@ static bool isSameWidthConstantConversio
   return true;
 }
 
+static bool isObjCSignedCharBool(Sema &S, QualType Ty) {
+  return Ty->isSpecificBuiltinType(BuiltinType::SChar) &&
+         S.getLangOpts().ObjC && S.NSAPIObj->isObjCBOOLType(Ty);
+}
+
 static void
 CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
                         bool *ICContext = nullptr) {
@@ -11192,6 +11197,29 @@ CheckImplicitConversion(Sema &S, Expr *E
     }
   }
 
+  // If the we're converting a constant to an ObjC BOOL on a platform where BOOL
+  // is a typedef for signed char (macOS), then that constant value has to be 1
+  // or 0.
+  if (isObjCSignedCharBool(S, T) && Source->isIntegralType(S.Context)) {
+    Expr::EvalResult Result;
+    if (E->EvaluateAsInt(Result, S.getASTContext(),
+                         Expr::SE_AllowSideEffects) &&
+        Result.Val.getInt() != 1 && Result.Val.getInt() != 0) {
+      auto Builder = S.Diag(CC, diag::warn_impcast_constant_int_to_objc_bool)
+                     << Result.Val.getInt().toString(10);
+      Expr *Ignored = E->IgnoreImplicit();
+      bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) ||
+                         isa<BinaryOperator>(Ignored) ||
+                         isa<CXXOperatorCallExpr>(Ignored);
+      SourceLocation EndLoc = S.getLocForEndOfToken(E->getEndLoc());
+      if (NeedsParens)
+        Builder << FixItHint::CreateInsertion(E->getBeginLoc(), "(")
+                << FixItHint::CreateInsertion(EndLoc, ")");
+      Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO");
+      return;
+    }
+  }
+
   // Check implicit casts from Objective-C collection literals to specialized
   // collection types, e.g., NSArray<NSString *> *.
   if (auto *ArrayLiteral = dyn_cast<ObjCArrayLiteral>(E))

Added: cfe/trunk/test/Sema/objc-bool-constant-conversion-fixit.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-bool-constant-conversion-fixit.m?rev=365518&view=auto
==============================================================================
--- cfe/trunk/test/Sema/objc-bool-constant-conversion-fixit.m (added)
+++ cfe/trunk/test/Sema/objc-bool-constant-conversion-fixit.m Tue Jul  9 10:29:40 2019
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -Werror=constant-conversion %s -fixit-recompile -fixit-to-temporary -E -o - | FileCheck %s
+
+typedef signed char BOOL;
+
+BOOL b;
+
+int main() {
+  BOOL b = 2;
+  // CHECK: BOOL b = 2 ? YES : NO;
+
+  b = b ? 2 : 1;
+  // CHECK: b = b ? 2 ? YES : NO : 1;
+
+  b = b ? 1 : 2;
+  // CHECK: b = b ? 1 : 2 ? YES : NO;
+
+  b = b ? 2 : 2;
+  // CHECK: b = b ? 2 ? YES : NO : 2 ? YES : NO;
+
+  b = 1 + 1;
+  // CHECK: b = (1 + 1) ? YES : NO;
+
+  b = 1 | 2;
+  // CHECK: b = (1 | 2) ? YES : NO;
+
+  b = 1 << 1;
+  // CHECK: b = (1 << 1) ? YES : NO;
+}
+
+ at interface BoolProp
+ at property BOOL b;
+ at end
+
+void f(BoolProp *bp) {
+  bp.b = 43;
+  // CHECK: bp.b = 43 ? YES : NO;
+
+  [bp setB:43];
+  // CHECK: [bp setB:43 ? YES : NO];
+}

Added: cfe/trunk/test/Sema/objc-bool-constant-conversion.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-bool-constant-conversion.m?rev=365518&view=auto
==============================================================================
--- cfe/trunk/test/Sema/objc-bool-constant-conversion.m (added)
+++ cfe/trunk/test/Sema/objc-bool-constant-conversion.m Tue Jul  9 10:29:40 2019
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+typedef signed char BOOL;
+#define YES __objc_yes
+#define NO __objc_no
+
+BOOL B;
+
+int main() {
+  B = 0;
+  B = 1;
+  B = YES;
+  B = NO;
+
+  B = -1; // expected-warning{{implicit conversion from constant value -1 to BOOL; the only well defined values for BOOL are YES and NO}}
+  B = 0 - 1; // expected-warning{{implicit conversion from constant value -1 to BOOL; the only well defined values for BOOL are YES and NO}}
+  B = YES + YES; // expected-warning {{implicit conversion from constant value 2 to BOOL; the only well defined values for BOOL are YES and NO}}
+  B = YES | YES;
+
+  B = B ? 2 : 2; // expected-warning 2 {{implicit conversion from constant value 2 to BOOL; the only well defined values for BOOL are YES and NO}}
+
+  BOOL Init = -1; // expected-warning{{implicit conversion from constant value -1 to BOOL; the only well defined values for BOOL are YES and NO}}
+  BOOL Init2 = B ? 2 : 2; // expected-warning 2 {{implicit conversion from constant value 2 to BOOL; the only well defined values for BOOL are YES and NO}}
+
+  void takesbool(BOOL);
+  takesbool(43); // expected-warning {{implicit conversion from constant value 43 to BOOL; the only well defined values for BOOL are YES and NO}}
+
+  BOOL OutOfRange = 400; // expected-warning{{implicit conversion from constant value 400 to BOOL; the only well defined values for BOOL are YES and NO}}
+}
+
+ at interface BoolProp
+ at property BOOL b;
+ at end
+
+void f(BoolProp *bp) {
+  bp.b = 43; // expected-warning {{implicit conversion from constant value 43 to BOOL; the only well defined values for BOOL are YES and NO}}
+  [bp setB:43]; // expected-warning {{implicit conversion from constant value 43 to BOOL; the only well defined values for BOOL are YES and NO}}
+}




More information about the cfe-commits mailing list