Skip to content

[Clang] add -Wshift-bool warning to handle shifting of bool #127336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Mar 6, 2025

Conversation

a-tarasyuk
Copy link
Member

@a-tarasyuk a-tarasyuk commented Feb 15, 2025

Fixes #28334


This PR introduces the -Wshift-bool warning to detect and warn against shifting bool values using the >> operator. Shifting a bool implicitly converts it to an int, which can lead to unintended behavior.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Feb 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2025

@llvm/pr-subscribers-clang

Author: Oleksandr T. (a-tarasyuk)

Changes

Fixes #28334


This PR introduces the -Wshift-bool warning to detect and warn against shifting bool values using the << or >> operators. Shifting a bool implicitly converts it to an int, which can lead to unintended behavior.


Full diff: https://github.com/llvm/llvm-project/pull/127336.diff

5 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/include/clang/Basic/DiagnosticGroups.td (+2)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+6)
  • (added) clang/test/Sema/shift-bool.cpp (+21)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6056a6964fbcc..d623d7daf05ea 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -138,6 +138,7 @@ Improvements to Clang's diagnostics
 - Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
 - A statement attribute applied to a ``case`` label no longer suppresses
   'bypassing variable initialization' diagnostics (#84072).
+- The ``-Wshift-bool`` warning has been added to warn about shifting a ``boolean``. (#GH28334)
 
 Improvements to Clang's time-trace
 ----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 05e39899e6f25..193aea3a8dfc3 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -461,6 +461,8 @@ def DanglingField : DiagGroup<"dangling-field">;
 def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
 def DanglingGsl : DiagGroup<"dangling-gsl">;
 def ReturnStackAddress : DiagGroup<"return-stack-address">;
+def ShiftBool: DiagGroup<"shift-bool">;
+
 // Name of this warning in GCC
 def : DiagGroup<"return-local-addr", [ReturnStackAddress]>;
 def Dangling : DiagGroup<"dangling", [DanglingAssignment,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c4f0fc55b4a38..754cf1e14799b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7115,6 +7115,9 @@ 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">,
   InGroup<DiagGroup<"shift-sign-overflow">>, DefaultIgnore;
+def warn_shift_bool : Warning<
+  "%select{left|right}0 shifting a `bool` implicitly converts it to 'int'">,
+  InGroup<ShiftBool>, DefaultIgnore;
 
 def warn_precedence_bitwise_rel : Warning<
   "%0 has lower precedence than %1; %1 will be evaluated first">,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3cd4010740d19..0816403b2df2a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11246,6 +11246,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
   if (S.getLangOpts().OpenCL)
     return;
 
+  if (LHS.get()->IgnoreParenImpCasts()->getType()->isBooleanType()) {
+    S.Diag(Loc, diag::warn_shift_bool)
+        << (Opc == BO_Shr) /*left|right*/ << LHS.get()->getSourceRange();
+    return;
+  }
+
   // Check right/shifter operand
   Expr::EvalResult RHSResult;
   if (RHS.get()->isValueDependent() ||
diff --git a/clang/test/Sema/shift-bool.cpp b/clang/test/Sema/shift-bool.cpp
new file mode 100644
index 0000000000000..dfbc1a1e73307
--- /dev/null
+++ b/clang/test/Sema/shift-bool.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -Wshift-bool -verify %s
+
+void t() {
+  int x = 10;
+  bool y = true;
+
+  bool a = y << x; // expected-warning {{left shifting a `bool` implicitly converts it to 'int'}}
+  bool b = y >> x; // expected-warning {{right shifting a `bool` implicitly converts it to 'int'}}
+
+  bool c = false << x; // expected-warning {{left shifting a `bool` implicitly converts it to 'int'}}
+  bool d = false >> x; // expected-warning {{right shifting a `bool` implicitly converts it to 'int'}}
+
+  bool e = y << 5; // expected-warning {{left shifting a `bool` implicitly converts it to 'int'}}
+  bool f = y >> 5; // expected-warning {{right shifting a `bool` implicitly converts it to 'int'}}
+
+  bool g = y << -1; // expected-warning {{left shifting a `bool` implicitly converts it to 'int'}}
+  bool h = y >> -1; // expected-warning {{right shifting a `bool` implicitly converts it to 'int'}}
+
+  bool i = y << 0; // expected-warning {{left shifting a `bool` implicitly converts it to 'int'}}
+  bool j = y >> 0; // expected-warning {{right shifting a `bool` implicitly converts it to 'int'}}
+}

@a-tarasyuk a-tarasyuk requested a review from Fznamznon February 21, 2025 12:51
Copy link
Contributor

@Fznamznon Fznamznon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy whenever @AaronBallman is.

@a-tarasyuk a-tarasyuk requested a review from AaronBallman March 5, 2025 20:19
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@a-tarasyuk a-tarasyuk merged commit 93f0f3d into llvm:main Mar 6, 2025
12 checks passed
Copy link
Collaborator

@shafik shafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also warns on expressions that result in a bool e.g. https://godbolt.org/z/aY3cons4T

bool a = (x < y) << 1;

Assuming it does, we should add a test to cover this case as well.

frederik-h pushed a commit to frederik-h/llvm-project that referenced this pull request Mar 18, 2025
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
)

Fixes llvm#28334

--- 

This PR introduces the `-Wshift-bool` warning to detect and warn against
shifting `bool` values using the `>>` operator. Shifting a `bool`
implicitly converts it to an `int`, which can lead to unintended
behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No warning on shifted boolean expression
5 participants