[PATCH] D141414: [clang] add warning on shifting boolean type

2023-01-10 Thread Angelo Matni via Phabricator via cfe-commits
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>;
+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>;
+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>;
+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_widt

[PATCH] D141414: [clang] add warning on shifting boolean type

2023-01-24 Thread Angelo Matni via Phabricator via cfe-commits
angelomatnigoogle updated this revision to Diff 491923.
angelomatnigoogle added a comment.

Consolidated shift-bool warning; fixed relevant unit tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141414/new/

https://reviews.llvm.org/D141414

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/Interp/shifts.cpp
  clang/test/Analysis/svalbuilder-simplify-no-crash.c
  clang/test/CXX/over/over.built/p18.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,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int f(int x) {
+  const bool b = 1;
+  const bool c = b << x; // expected-warning {{left shifting 'bool' will 
implicitly cast to 'int'; consider 'bool && (shift_count | desired_type_width - 
1)' to avoid implicitly relying on the width of 'int'}}
+  const bool d = b >> x; // expected-warning {{right shifting 'bool' will 
implicitly cast to 'int'; consider 'bool & !shift_count' to avoid implicitly 
relying on the width of 'int'}}
+  return 0;
+}
Index: clang/test/CXX/over/over.built/p18.cpp
===
--- clang/test/CXX/over/over.built/p18.cpp
+++ clang/test/CXX/over/over.built/p18.cpp
@@ -56,7 +56,7 @@
 
   (void)(i << 3);
   (void)(f << 3);  // expected-error {{invalid operands}}
-  (void)(b << 3);
+  (void)(b << 3);  // expected-warning {{left shifting 'bool' will implicitly 
cast to 'int'; consider 'bool && (shift_count | desired_type_width - 1)' to 
avoid implicitly relying on the width of 'int'}}
   (void)(pi << 3); // expected-error {{invalid operands}}
   (void)(pt << 3); // FIXME
   (void)(t << 3);
@@ -69,7 +69,7 @@
 
   (void)(i >> 3);
   (void)(f >> 3);  // expected-error {{invalid operands}}
-  (void)(b >> 3);
+  (void)(b >> 3);  // expected-warning {{right shifting 'bool' will implicitly 
cast to 'int'; consider 'bool & !shift_count' to avoid implicitly relying on 
the width of 'int'}}
   (void)(pi >> 3); // expected-error {{invalid operands}}
   (void)(pt >> 3); // FIXME
   (void)(t >> 3);
Index: clang/test/Analysis/svalbuilder-simplify-no-crash.c
===
--- clang/test/Analysis/svalbuilder-simplify-no-crash.c
+++ clang/test/Analysis/svalbuilder-simplify-no-crash.c
@@ -9,5 +9,6 @@
 void crashing(long a, _Bool b) {
   (void)(a & 1 && 0);
   b = a & 1;
-  (void)(b << 1); // expected-warning{{core.UndefinedBinaryOperatorResult}}
+  (void)(b << 1); // expected-warning{{core.UndefinedBinaryOperatorResult}} \
+  // expected-warning {{left shifting 'bool' will implicitly 
cast to 'int'; consider 'bool && (shift_count | desired_type_width - 1)' to 
avoid implicitly relying on the width of 'int'}}
 }
Index: clang/test/AST/Interp/shifts.cpp
===
--- clang/test/AST/Interp/shifts.cpp
+++ clang/test/AST/Interp/shifts.cpp
@@ -109,7 +109,13 @@
   static_assert(m == 1, "");
   constexpr unsigned char c = 0 << 8;
   static_assert(c == 0, "");
-  static_assert(true << 1, "");
+
+  constexpr unsigned b = true << 1; // expected-warning {{left shifting 'bool' 
will implicitly cast to 'int'; consider 'bool && (shift_count | 
desired_type_width - 1)' to avoid implicitly relying on the width of 'int'}} \
+// cxx17-warning {{left shifting 'bool' 
will implicitly cast to 'int'; consider 'bool && (shift_count | 
desired_type_width - 1)' to avoid implicitly relying on the width of 'int'}} \
+// ref-warning {{left shifting 'bool' will 
implicitly cast to 'int'; consider 'bool && (shift_count | desired_type_width - 
1)' to avoid implicitly relying on the width of 'int'}} \
+// ref-cxx17-warning {{left shifting 
'bool' will implicitly cast to 'int'; consider 'bool && (shift_count | 
desired_type_width - 1)' to avoid implicitly relying on the width of 'int'}}
+  static_assert(b, ""); 
+
   static_assert(1 << (__INT_WIDTH__ +1) == 0, "");  // expected-error {{not an 
integral constant expression}} \
 // expected-note {{>= 
width of type 'int'}} \
 // cxx17-error {{not an 
integral constant expression}} \
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -11950,6 +11950,10 @@
   SourceLocation Loc, BinaryOperatorKind Opc,
   bool IsCompAssign) {
   checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
+  if (LHS.get()->IgnoreParenImpCasts()->getType()->isBooleanType())
+

[PATCH] D141414: [clang] add warning on shifting boolean type

2023-08-22 Thread Angelo Matni via Phabricator via cfe-commits
angelomatnigoogle added a comment.

Pardon me for losing sight on this change. Within the week, I will revisit this 
change based on the current outstanding comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141414/new/

https://reviews.llvm.org/D141414

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits