Skip to content

Commit ab28c1d

Browse files
authored
fix unnecessary warning when using bitand with boolean operators (#81976)
This pull request fixes #77601 where using the `bitand` operator with boolean operands should not trigger the warning, as it would indicate an intentional use of bitwise AND rather than a typo or error. Fixes #77601
1 parent daebe5c commit ab28c1d

File tree

4 files changed

+38
-10
lines changed

4 files changed

+38
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@ Improvements to Clang's diagnostics
250250
such as attempting to call ``free`` on an unallocated object. Fixes
251251
`#79443 <https://github.com/llvm/llvm-project/issues/79443>`_.
252252

253+
- Clang no longer warns when the ``bitand`` operator is used with boolean
254+
operands, distinguishing it from potential typographical errors or unintended
255+
bitwise operations. Fixes #GH77601.
256+
253257
Improvements to Clang's time-trace
254258
----------------------------------
255259

clang/lib/Sema/SemaChecking.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16605,12 +16605,26 @@ static void AnalyzeImplicitConversions(
1660516605
BO->getRHS()->isKnownToHaveBooleanValue() &&
1660616606
BO->getLHS()->HasSideEffects(S.Context) &&
1660716607
BO->getRHS()->HasSideEffects(S.Context)) {
16608-
S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
16609-
<< (BO->getOpcode() == BO_And ? "&" : "|") << OrigE->getSourceRange()
16610-
<< FixItHint::CreateReplacement(
16611-
BO->getOperatorLoc(),
16612-
(BO->getOpcode() == BO_And ? "&&" : "||"));
16613-
S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
16608+
SourceManager &SM = S.getSourceManager();
16609+
const LangOptions &LO = S.getLangOpts();
16610+
SourceLocation BLoc = BO->getOperatorLoc();
16611+
SourceLocation ELoc = Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
16612+
StringRef SR = clang::Lexer::getSourceText(
16613+
clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO);
16614+
// To reduce false positives, only issue the diagnostic if the operator
16615+
// is explicitly spelled as a punctuator. This suppresses the diagnostic
16616+
// when using 'bitand' or 'bitor' either as keywords in C++ or as macros
16617+
// in C, along with other macro spellings the user might invent.
16618+
if (SR.str() == "&" || SR.str() == "|") {
16619+
16620+
S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
16621+
<< (BO->getOpcode() == BO_And ? "&" : "|")
16622+
<< OrigE->getSourceRange()
16623+
<< FixItHint::CreateReplacement(
16624+
BO->getOperatorLoc(),
16625+
(BO->getOpcode() == BO_And ? "&&" : "||"));
16626+
S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
16627+
}
1661416628
}
1661516629

1661616630
// For conditional operators, we analyze the arguments as if they

clang/test/Sema/warn-bitwise-and-bool.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const));
1919
void sink(boolean);
2020

2121
#define FOO foo()
22+
#define MY_AND &
23+
#define My_BITAND bitand
2224

2325
void test(boolean a, boolean b, int *p, volatile int *q, int i) {
2426
b = a & b;
@@ -44,9 +46,12 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
4446
b = b & foo();
4547
b = bar() & (i > 4);
4648
b = (i == 7) & foo();
49+
b = b MY_AND foo(); // OK, no warning expected
50+
4751
#ifdef __cplusplus
48-
b = foo() bitand bar(); // expected-warning {{use of bitwise '&' with boolean operands}}
49-
// expected-note@-1 {{cast one or both operands to int to silence this warning}}
52+
b = foo() bitand bar(); // Ok, no warning expected
53+
b = foo() My_BITAND bar(); // Ok, no warning expected
54+
5055
#endif
5156

5257
if (foo() & bar()) // expected-warning {{use of bitwise '&' with boolean operands}}
@@ -60,4 +65,5 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
6065

6166
int n = i + 10;
6267
b = (n & (n - 1));
68+
6369
}

clang/test/Sema/warn-bitwise-or-bool.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const));
1919
void sink(boolean);
2020

2121
#define FOO foo()
22+
#define MY_OR |
23+
#define My_BITOR bitor
2224

2325
void test(boolean a, boolean b, int *p, volatile int *q, int i) {
2426
b = a | b;
@@ -44,9 +46,11 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
4446
b = b | foo();
4547
b = bar() | (i > 4);
4648
b = (i == 7) | foo();
49+
b = b MY_OR foo(); // OK, no warning expected
4750
#ifdef __cplusplus
48-
b = foo() bitor bar(); // expected-warning {{use of bitwise '|' with boolean operands}}
49-
// expected-note@-1 {{cast one or both operands to int to silence this warning}}
51+
b = foo() bitor bar(); //Ok, no warning expected
52+
b = foo() My_BITOR bar(); // Ok, no warning expected
53+
5054
#endif
5155

5256
if (foo() | bar()) // expected-warning {{use of bitwise '|' with boolean operands}}

0 commit comments

Comments
 (0)