Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------------------------------
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">,
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() ||
Expand Down
21 changes: 21 additions & 0 deletions clang/test/Sema/shift-bool.cpp
Original file line number Diff line number Diff line change
@@ -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'}}
}