angelomatnigoogle created this revision.
angelomatnigoogle added reviewers: arsenm, shafik.
Herald added a project: All.
angelomatnigoogle requested review of this revision.
Herald added subscribers: cfe-commits, wdng.
Herald added a project: clang.

Warn on operations "b << x" and "b >> x"

Github issue #28334


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D141414

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/warn-shift-bool.cpp


Index: clang/test/Sema/warn-shift-bool.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/warn-shift-bool.cpp
@@ -0,0 +1,7 @@
+
+// RUN: %clang_cc1 -fsyntax-only -Wshift-cast-dependent-overflow -fblocks 
-verify %s
+
+int f(int x) {
+  const bool b = 1;
+  return b << x; // expected-warning{{left shifting bool relies on implicit 
cast type width; consider re-write 'bool && (shift_count | desired_type_width - 
1)'}}
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -11945,11 +11945,22 @@
   return LHSType;
 }
 
+static void checkBooleanShift(Sema &S, ExprResult &LHS, SourceLocation Loc, 
BinaryOperatorKind Opc) {
+  if (LHS.get()->IgnoreParenImpCasts()->getType()->isBooleanType()) {
+    if (Opc == BO_Shl) {
+      S.Diag(Loc, diag::warn_shift_left_on_bool_type);
+    } else if (Opc == BO_Shr) {
+      S.Diag(Loc, diag::warn_shift_right_on_bool_type);
+    }
+  }
+}
+
 // C99 6.5.7
 QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
                                   SourceLocation Loc, BinaryOperatorKind Opc,
                                   bool IsCompAssign) {
   checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
+  checkBooleanShift(*this, LHS, Loc, Opc);
 
   // Vector shifts promote their scalar inputs to vector type.
   if (LHS.get()->getType()->isVectorType() ||
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6603,6 +6603,11 @@
 def warn_shift_result_gt_typewidth : Warning<
   "signed shift result (%0) requires %1 bits to represent, but %2 only has "
   "%3 bits">, InGroup<DiagGroup<"shift-overflow">>;
+def warn_shift_left_on_bool_type : Warning<
+  "left shifting bool relies on implicit cast type width; consider re-write 
'bool && (shift_count | desired_type_width - 1)'">,
+  InGroup<DiagGroup<"shift-cast-dependent-overflow">>;
+def warn_shift_right_on_bool_type : Warning<
+  "right shifting bool equals itself if shifting 0 bits or false otherwise; 
consider re-write 'bool & !shift_count'">;
 def warn_shift_result_sets_sign_bit : Warning<
   "signed shift result (%0) sets the sign bit of the shift expression's "
   "type (%1) and becomes negative">,


Index: clang/test/Sema/warn-shift-bool.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/warn-shift-bool.cpp
@@ -0,0 +1,7 @@
+
+// RUN: %clang_cc1 -fsyntax-only -Wshift-cast-dependent-overflow -fblocks -verify %s
+
+int f(int x) {
+  const bool b = 1;
+  return b << x; // expected-warning{{left shifting bool relies on implicit cast type width; consider re-write 'bool && (shift_count | desired_type_width - 1)'}}
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -11945,11 +11945,22 @@
   return LHSType;
 }
 
+static void checkBooleanShift(Sema &S, ExprResult &LHS, SourceLocation Loc, BinaryOperatorKind Opc) {
+  if (LHS.get()->IgnoreParenImpCasts()->getType()->isBooleanType()) {
+    if (Opc == BO_Shl) {
+      S.Diag(Loc, diag::warn_shift_left_on_bool_type);
+    } else if (Opc == BO_Shr) {
+      S.Diag(Loc, diag::warn_shift_right_on_bool_type);
+    }
+  }
+}
+
 // C99 6.5.7
 QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
                                   SourceLocation Loc, BinaryOperatorKind Opc,
                                   bool IsCompAssign) {
   checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
+  checkBooleanShift(*this, LHS, Loc, Opc);
 
   // Vector shifts promote their scalar inputs to vector type.
   if (LHS.get()->getType()->isVectorType() ||
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6603,6 +6603,11 @@
 def warn_shift_result_gt_typewidth : Warning<
   "signed shift result (%0) requires %1 bits to represent, but %2 only has "
   "%3 bits">, InGroup<DiagGroup<"shift-overflow">>;
+def warn_shift_left_on_bool_type : Warning<
+  "left shifting bool relies on implicit cast type width; consider re-write 'bool && (shift_count | desired_type_width - 1)'">,
+  InGroup<DiagGroup<"shift-cast-dependent-overflow">>;
+def warn_shift_right_on_bool_type : Warning<
+  "right shifting bool equals itself if shifting 0 bits or false otherwise; consider re-write 'bool & !shift_count'">;
 def warn_shift_result_sets_sign_bit : Warning<
   "signed shift result (%0) sets the sign bit of the shift expression's "
   "type (%1) and becomes negative">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to