[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

Bhuminjay Soni via cfe-commits cfe-commits at lists.llvm.org
Sat Mar 16 03:41:13 PDT 2024


https://github.com/11happy updated https://github.com/llvm/llvm-project/pull/81976

>From 07c73f087a430f5115ecdfec23730c5afcab37f3 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 16 Feb 2024 14:26:36 +0530
Subject: [PATCH 1/2] fix unnecessary warning when using bitand with boolean

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 clang/lib/Sema/SemaChecking.cpp         | 24 ++++++++++++++++++------
 clang/test/Sema/warn-bitwise-and-bool.c |  4 ++--
 clang/test/Sema/warn-bitwise-or-bool.c  |  4 ++--
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 502b24bcdf8b42..e43892cbf35890 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16191,12 +16191,24 @@ static void AnalyzeImplicitConversions(
         BO->getRHS()->isKnownToHaveBooleanValue() &&
         BO->getLHS()->HasSideEffects(S.Context) &&
         BO->getRHS()->HasSideEffects(S.Context)) {
-      S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
-          << (BO->getOpcode() == BO_And ? "&" : "|") << OrigE->getSourceRange()
-          << FixItHint::CreateReplacement(
-                 BO->getOperatorLoc(),
-                 (BO->getOpcode() == BO_And ? "&&" : "||"));
-      S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+      clang::SourceManager &SM = S.getSourceManager();
+      clang::LangOptions LO = S.getLangOpts();
+      clang::SourceLocation BLoc = BO->getOperatorLoc();
+      clang::SourceLocation ELoc =
+          clang::Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
+      llvm::StringRef SR = clang::Lexer::getSourceText(
+          clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO);
+
+      if (SR.str() == "&" || SR.str() == "|") {
+
+        S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
+            << (BO->getOpcode() == BO_And ? "&" : "|")
+            << OrigE->getSourceRange()
+            << FixItHint::CreateReplacement(
+                   BO->getOperatorLoc(),
+                   (BO->getOpcode() == BO_And ? "&&" : "||"));
+        S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+      }
     }
 
   // For conditional operators, we analyze the arguments as if they
diff --git a/clang/test/Sema/warn-bitwise-and-bool.c b/clang/test/Sema/warn-bitwise-and-bool.c
index 6bec1be1abdef6..23e7afcc59f8aa 100644
--- a/clang/test/Sema/warn-bitwise-and-bool.c
+++ b/clang/test/Sema/warn-bitwise-and-bool.c
@@ -45,8 +45,8 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = bar() & (i > 4);
   b = (i == 7) & foo();
 #ifdef __cplusplus
-  b = foo() bitand bar(); // expected-warning {{use of bitwise '&' with boolean operands}}
-                          // expected-note at -1 {{cast one or both operands to int to silence this warning}}
+  b = foo() bitand bar(); // Ok, no warning expected
+                          
 #endif
 
   if (foo() & bar())      // expected-warning {{use of bitwise '&' with boolean operands}}
diff --git a/clang/test/Sema/warn-bitwise-or-bool.c b/clang/test/Sema/warn-bitwise-or-bool.c
index ae86790901aac5..e84f59cf8f766a 100644
--- a/clang/test/Sema/warn-bitwise-or-bool.c
+++ b/clang/test/Sema/warn-bitwise-or-bool.c
@@ -45,8 +45,8 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = bar() | (i > 4);
   b = (i == 7) | foo();
 #ifdef __cplusplus
-  b = foo() bitor bar();  // expected-warning {{use of bitwise '|' with boolean operands}}
-                          // expected-note at -1 {{cast one or both operands to int to silence this warning}}
+  b = foo() bitor bar();  //Ok, no warning expected
+                          
 #endif
 
   if (foo() | bar())      // expected-warning {{use of bitwise '|' with boolean operands}}

>From a0ba9e05bb9d0443f386fd57eef3b4e6e2bd1217 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sat, 16 Mar 2024 16:11:00 +0530
Subject: [PATCH 2/2] add release notes and add tests

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 clang/docs/ReleaseNotes.rst             |  5 +++++
 clang/lib/Sema/SemaChecking.cpp         | 16 +++++++++-------
 clang/test/Sema/warn-bitwise-and-bool.c |  6 ++++++
 clang/test/Sema/warn-bitwise-or-bool.c  |  4 ++++
 4 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 254e0a9cb72979..177f424abaa73c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -106,6 +106,11 @@ Improvements to Clang's diagnostics
 - Clang now applies syntax highlighting to the code snippets it
   prints.
 
+- Clang now does not warn in cases where bitand operator is 
+  intentionally used with boolean operands, distinguishing it
+  from potential typographical errors or unintended bitwise operations.
+  Fixes (`#77601 <https://github.com/llvm/llvm-project/issues/77601>`)
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e43892cbf35890..f3444b1b51a824 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16191,14 +16191,16 @@ static void AnalyzeImplicitConversions(
         BO->getRHS()->isKnownToHaveBooleanValue() &&
         BO->getLHS()->HasSideEffects(S.Context) &&
         BO->getRHS()->HasSideEffects(S.Context)) {
-      clang::SourceManager &SM = S.getSourceManager();
-      clang::LangOptions LO = S.getLangOpts();
-      clang::SourceLocation BLoc = BO->getOperatorLoc();
-      clang::SourceLocation ELoc =
-          clang::Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
-      llvm::StringRef SR = clang::Lexer::getSourceText(
+      SourceManager &SM = S.getSourceManager();
+      const LangOptions &LO = S.getLangOpts();
+      SourceLocation BLoc = BO->getOperatorLoc();
+      SourceLocation ELoc = Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
+      StringRef SR = clang::Lexer::getSourceText(
           clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO);
-
+      // To reduce false positives, only issue the diagnostic if the operator
+      // is explicitly spelled as a punctuator. This suppresses the diagnostic
+      // when using 'bitand' or 'bitor' either as keywords in C++ or as macros
+      // in C, along with other macro spellings the user might invent.
       if (SR.str() == "&" || SR.str() == "|") {
 
         S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
diff --git a/clang/test/Sema/warn-bitwise-and-bool.c b/clang/test/Sema/warn-bitwise-and-bool.c
index 23e7afcc59f8aa..c30498e2bd8d1a 100644
--- a/clang/test/Sema/warn-bitwise-and-bool.c
+++ b/clang/test/Sema/warn-bitwise-and-bool.c
@@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const));
 void sink(boolean);
 
 #define FOO foo()
+#define MY_AND &
+#define My_BITAND bitand
 
 void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = a & b;
@@ -44,8 +46,11 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = b & foo();
   b = bar() & (i > 4);
   b = (i == 7) & foo();
+  b = b MY_AND foo();     // OK, no warning expected
+
 #ifdef __cplusplus
   b = foo() bitand bar(); // Ok, no warning expected
+  b = foo() My_BITAND bar(); // Ok, no warning expected
                           
 #endif
 
@@ -60,4 +65,5 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
 
   int n = i + 10;
   b = (n & (n - 1));
+
 }
diff --git a/clang/test/Sema/warn-bitwise-or-bool.c b/clang/test/Sema/warn-bitwise-or-bool.c
index e84f59cf8f766a..e45ef28da0a70d 100644
--- a/clang/test/Sema/warn-bitwise-or-bool.c
+++ b/clang/test/Sema/warn-bitwise-or-bool.c
@@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const));
 void sink(boolean);
 
 #define FOO foo()
+#define MY_OR |
+#define My_BITOR bitor
 
 void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = a | b;
@@ -44,8 +46,10 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = b | foo();
   b = bar() | (i > 4);
   b = (i == 7) | foo();
+  b = b MY_OR foo();     // OK, no warning expected
 #ifdef __cplusplus
   b = foo() bitor bar();  //Ok, no warning expected
+  b = foo() My_BITOR bar(); // Ok, no warning expected
                           
 #endif
 



More information about the cfe-commits mailing list