[clang-tools-extra] [clang-tidy] Add misc-bool-bitwise-operation check (PR #167552)
Denis Mikhailov via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 17 05:31:08 PST 2026
https://github.com/denzor200 updated https://github.com/llvm/llvm-project/pull/167552
>From 710b7b4de1fdef8f4b159d5cc3503f151e8ecbfc Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Tue, 21 Oct 2025 19:52:57 +0300
Subject: [PATCH 01/49] Stock files were taken
---
.../misc/BoolBitwiseOperationCheck.cpp | 181 ++++++++
.../misc/BoolBitwiseOperationCheck.h | 42 ++
.../clang-tidy/misc/CMakeLists.txt | 1 +
.../clang-tidy/misc/MiscTidyModule.cpp | 3 +
clang-tools-extra/docs/ReleaseNotes.rst | 7 +
.../docs/clang-tidy/checks/list.rst | 11 +-
.../checks/misc/bool-bitwise-operation.rst | 62 +++
...-operation-change-possible-side-effect.cpp | 82 ++++
.../bool-bitwise-operation-ignore-macros.cpp | 53 +++
.../bool-bitwise-operation-nontraditional.cpp | 399 ++++++++++++++++++
.../checkers/misc/bool-bitwise-operation.c | 26 ++
.../checkers/misc/bool-bitwise-operation.cpp | 399 ++++++++++++++++++
12 files changed, 1261 insertions(+), 5 deletions(-)
create mode 100644 clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
new file mode 100644
index 0000000000000..f37e1482c4a7d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -0,0 +1,181 @@
+//===--- BoolBitwiseOperationCheck.cpp - clang-tidy -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "BoolBitwiseOperationCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include <array>
+#include <optional>
+#include <utility>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::misc {
+
+static const NamedDecl *
+getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
+ if (BO->isCompoundAssignmentOp()) {
+ const auto *DeclRefLHS =
+ dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreImpCasts());
+ return DeclRefLHS ? DeclRefLHS->getDecl() : nullptr;
+ }
+ return nullptr;
+}
+
+constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
+ OperatorsTransformation{{{"|", "||"},
+ {"|=", "||"},
+ {"&", "&&"},
+ {"&=", "&&"},
+ {"bitand", "and"},
+ {"and_eq", "and"},
+ {"bitor", "or"},
+ {"or_eq", "or"}}};
+
+static llvm::StringRef translate(llvm::StringRef Value) {
+ for (const auto &[Bitwise, Logical] : OperatorsTransformation) {
+ if (Value == Bitwise)
+ return Logical;
+ }
+
+ return {};
+}
+
+BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ StrictMode(Options.get("StrictMode", false)),
+ IgnoreMacros(Options.get("IgnoreMacros", false)) {}
+
+void BoolBitwiseOperationCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "StrictMode", StrictMode);
+ Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+}
+
+void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ binaryOperator(
+ unless(isExpansionInSystemHeader()),
+ hasAnyOperatorName("|", "&", "|=", "&="),
+ hasEitherOperand(expr(hasType(booleanType()))),
+ optionally(hasParent( // to simple implement transformations like
+ // `a&&b|c` -> `a&&(b||c)`
+ binaryOperator().bind("p"))))
+ .bind("op"),
+ this);
+}
+
+void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedExpr = Result.Nodes.getNodeAs<BinaryOperator>("op");
+
+ auto DiagEmitter = [MatchedExpr, this] {
+ const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign(MatchedExpr);
+ return diag(MatchedExpr->getOperatorLoc(),
+ "use logical operator '%0' for boolean %select{variable "
+ "%2|values}1 instead of bitwise operator '%3'")
+ << translate(MatchedExpr->getOpcodeStr()) << (ND == nullptr) << ND
+ << MatchedExpr->getOpcodeStr();
+ };
+
+ const bool HasVolatileOperand = llvm::any_of(
+ std::array{MatchedExpr->getLHS(), MatchedExpr->getRHS()},
+ [](const Expr *E) {
+ return E->IgnoreImpCasts()->getType().isVolatileQualified();
+ });
+ if (HasVolatileOperand)
+ return static_cast<void>(DiagEmitter());
+
+ const bool HasSideEffects = MatchedExpr->getRHS()->HasSideEffects(
+ *Result.Context, /*IncludePossibleEffects=*/!StrictMode);
+ if (HasSideEffects)
+ return static_cast<void>(DiagEmitter());
+
+ SourceLocation Loc = MatchedExpr->getOperatorLoc();
+
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return static_cast<void>(IgnoreMacros || DiagEmitter());
+
+ Loc = Result.SourceManager->getSpellingLoc(Loc);
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return static_cast<void>(IgnoreMacros || DiagEmitter());
+
+ const CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc);
+ if (TokenRange.isInvalid())
+ return static_cast<void>(IgnoreMacros || DiagEmitter());
+
+ const StringRef FixSpelling = translate(Lexer::getSourceText(
+ TokenRange, *Result.SourceManager, Result.Context->getLangOpts()));
+
+ if (FixSpelling.empty())
+ return static_cast<void>(DiagEmitter());
+
+ FixItHint InsertEqual;
+ if (MatchedExpr->isCompoundAssignmentOp()) {
+ const auto *DeclRefLHS =
+ dyn_cast<DeclRefExpr>(MatchedExpr->getLHS()->IgnoreImpCasts());
+ if (!DeclRefLHS)
+ return static_cast<void>(DiagEmitter());
+ const SourceLocation LocLHS = DeclRefLHS->getEndLoc();
+ if (LocLHS.isInvalid() || LocLHS.isMacroID())
+ return static_cast<void>(IgnoreMacros || DiagEmitter());
+ const SourceLocation InsertLoc = clang::Lexer::getLocForEndOfToken(
+ LocLHS, 0, *Result.SourceManager, Result.Context->getLangOpts());
+ if (InsertLoc.isInvalid() || InsertLoc.isMacroID())
+ return static_cast<void>(IgnoreMacros || DiagEmitter());
+ InsertEqual = FixItHint::CreateInsertion(
+ InsertLoc, " = " + DeclRefLHS->getDecl()->getNameAsString());
+ }
+
+ auto ReplaceOperator = FixItHint::CreateReplacement(TokenRange, FixSpelling);
+
+ const auto *Parent = Result.Nodes.getNodeAs<BinaryOperator>("p");
+ std::optional<BinaryOperatorKind> ParentOpcode;
+ if (Parent)
+ ParentOpcode = Parent->getOpcode();
+
+ const auto *RHS =
+ dyn_cast<BinaryOperator>(MatchedExpr->getRHS()->IgnoreImpCasts());
+ std::optional<BinaryOperatorKind> RHSOpcode;
+ if (RHS)
+ RHSOpcode = RHS->getOpcode();
+
+ const Expr *SurroundedExpr = nullptr;
+ if ((MatchedExpr->getOpcode() == BO_Or && ParentOpcode == BO_LAnd) ||
+ (MatchedExpr->getOpcode() == BO_And &&
+ llvm::is_contained({BO_Xor, BO_Or}, ParentOpcode))) {
+ const Expr *Side = Parent->getLHS()->IgnoreParenImpCasts() == MatchedExpr
+ ? Parent->getLHS()
+ : Parent->getRHS();
+ SurroundedExpr = Side->IgnoreImpCasts();
+ assert(SurroundedExpr->IgnoreParens() == MatchedExpr);
+ } else if (MatchedExpr->getOpcode() == BO_AndAssign && RHSOpcode == BO_LOr)
+ SurroundedExpr = RHS;
+
+ if (SurroundedExpr && isa<ParenExpr>(SurroundedExpr))
+ SurroundedExpr = nullptr;
+
+ FixItHint InsertBrace1;
+ FixItHint InsertBrace2;
+ if (SurroundedExpr) {
+ const SourceLocation InsertFirstLoc = SurroundedExpr->getBeginLoc();
+ const SourceLocation InsertSecondLoc = clang::Lexer::getLocForEndOfToken(
+ SurroundedExpr->getEndLoc(), 0, *Result.SourceManager,
+ Result.Context->getLangOpts());
+ if (InsertFirstLoc.isInvalid() || InsertFirstLoc.isMacroID() ||
+ InsertSecondLoc.isInvalid() || InsertSecondLoc.isMacroID())
+ return static_cast<void>(IgnoreMacros || DiagEmitter());
+ InsertBrace1 = FixItHint::CreateInsertion(InsertFirstLoc, "(");
+ InsertBrace2 = FixItHint::CreateInsertion(InsertSecondLoc, ")");
+ }
+
+ DiagEmitter() << InsertEqual << ReplaceOperator << InsertBrace1
+ << InsertBrace2;
+}
+
+} // namespace clang::tidy::misc
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
new file mode 100644
index 0000000000000..b1056e53c50c9
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -0,0 +1,42 @@
+//===--- BoolBitwiseOperationCheck.h - clang-tidy ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLBITWISEOPERATIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLBITWISEOPERATIONCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::misc {
+
+/// Finds potentially inefficient use of bitwise operators such as ``&``, ``|``
+/// and their compound analogues on Boolean values where logical operators like
+/// ``&&`` and ``||`` would be more appropriate.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc/bool-bitwise-operation.html
+class BoolBitwiseOperationCheck : public ClangTidyCheck {
+public:
+ BoolBitwiseOperationCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus || LangOpts.C99;
+ }
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+
+private:
+ bool StrictMode;
+ bool IgnoreMacros;
+};
+
+} // namespace clang::tidy::misc
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLBITWISEOPERATIONCHECK_H
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index 2cfee5fd10713..21065eb5432fe 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -18,6 +18,7 @@ add_custom_target(genconfusable DEPENDS Confusables.inc)
set_target_properties(genconfusable PROPERTIES FOLDER "Clang Tools Extra/Sourcegenning")
add_clang_library(clangTidyMiscModule STATIC
+ BoolBitwiseOperationCheck.cpp
ConstCorrectnessCheck.cpp
CoroutineHostileRAIICheck.cpp
DefinitionsInHeadersCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index 6f4af6c44dcb4..8221e07f3880c 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -9,6 +9,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
+#include "BoolBitwiseOperationCheck.h"
#include "ConfusableIdentifierCheck.h"
#include "ConstCorrectnessCheck.h"
#include "CoroutineHostileRAIICheck.h"
@@ -40,6 +41,8 @@ namespace misc {
class MiscModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<BoolBitwiseOperationCheck>(
+ "misc-bool-bitwise-operation");
CheckFactories.registerCheck<ConfusableIdentifierCheck>(
"misc-confusable-identifiers");
CheckFactories.registerCheck<ConstCorrectnessCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 8a0151f567c24..5ad73c43fa180 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -210,6 +210,13 @@ New checks
Finds calls to STL library iterator algorithms that could be replaced with
LLVM range-based algorithms from ``llvm/ADT/STLExtras.h``.
+- New :doc:`misc-bool-bitwise-operation
+ <clang-tidy/checks/misc/bool-bitwise-operation>` check.
+
+ Finds potentially inefficient use of bitwise operators such as ``&``, ``|``
+ and their compound analogues on Boolean values where logical operators like
+ ``&&`` and ``||`` would be more appropriate.
+
- New :doc:`misc-override-with-different-visibility
<clang-tidy/checks/misc/override-with-different-visibility>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index a324d18704c01..d1344d4c47f8c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -174,7 +174,9 @@ Clang-Tidy Checks
:doc:`bugprone-use-after-move <bugprone/use-after-move>`,
:doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes"
:doc:`cert-dcl58-cpp <cert/dcl58-cpp>`,
+ :doc:`cert-env33-c <cert/env33-c>`,
:doc:`cert-err33-c <cert/err33-c>`,
+ :doc:`cert-err52-cpp <cert/err52-cpp>`,
:doc:`cert-err60-cpp <cert/err60-cpp>`,
:doc:`cert-flp30-c <cert/flp30-c>`,
:doc:`cert-mem57-cpp <cert/mem57-cpp>`,
@@ -261,6 +263,7 @@ Clang-Tidy Checks
:doc:`llvmlibc-implementation-in-namespace <llvmlibc/implementation-in-namespace>`,
:doc:`llvmlibc-inline-function-decl <llvmlibc/inline-function-decl>`, "Yes"
:doc:`llvmlibc-restrict-system-libc-headers <llvmlibc/restrict-system-libc-headers>`, "Yes"
+ :doc:`misc-bool-bitwise-operation <misc/bool-bitwise-operation>`, "Yes"
:doc:`misc-confusable-identifiers <misc/confusable-identifiers>`,
:doc:`misc-const-correctness <misc/const-correctness>`, "Yes"
:doc:`misc-coroutine-hostile-raii <misc/coroutine-hostile-raii>`,
@@ -372,7 +375,7 @@ Clang-Tidy Checks
:doc:`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`, "Yes"
:doc:`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>`,
- :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
+ :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
:doc:`readability-const-return-type <readability/const-return-type>`, "Yes"
:doc:`readability-container-contains <readability/container-contains>`, "Yes"
:doc:`readability-container-data-pointer <readability/container-data-pointer>`, "Yes"
@@ -442,9 +445,7 @@ Check aliases
:doc:`cert-dcl54-cpp <cert/dcl54-cpp>`, :doc:`misc-new-delete-overloads <misc/new-delete-overloads>`,
:doc:`cert-dcl59-cpp <cert/dcl59-cpp>`, :doc:`google-build-namespaces <google/build-namespaces>`,
:doc:`cert-err09-cpp <cert/err09-cpp>`, :doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`,
- :doc:`cert-env33-c <cert/env33-c>`, :doc:`bugprone-command-processor <bugprone/command-processor>`,
:doc:`cert-err34-c <cert/err34-c>`, :doc:`bugprone-unchecked-string-to-number-conversion <bugprone/unchecked-string-to-number-conversion>`,
- :doc:`cert-err52-cpp <cert/err52-cpp>`, :doc:`modernize-avoid-setjmp-longjmp <modernize/avoid-setjmp-longjmp>`,
:doc:`cert-err58-cpp <cert/err58-cpp>`, :doc:`bugprone-throwing-static-initialization <bugprone/throwing-static-initialization>`,
:doc:`cert-err61-cpp <cert/err61-cpp>`, :doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`,
:doc:`cert-exp42-c <cert/exp42-c>`, :doc:`bugprone-suspicious-memory-comparison <bugprone/suspicious-memory-comparison>`,
@@ -571,12 +572,12 @@ Check aliases
:doc:`cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines/non-private-member-variables-in-classes>`, :doc:`misc-non-private-member-variables-in-classes <misc/non-private-member-variables-in-classes>`,
:doc:`cppcoreguidelines-use-default-member-init <cppcoreguidelines/use-default-member-init>`, :doc:`modernize-use-default-member-init <modernize/use-default-member-init>`, "Yes"
:doc:`fuchsia-header-anon-namespaces <fuchsia/header-anon-namespaces>`, :doc:`google-build-namespaces <google/build-namespaces>`,
- :doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
+ :doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
:doc:`google-readability-function-size <google/readability-function-size>`, :doc:`readability-function-size <readability/function-size>`,
:doc:`google-readability-namespace-comments <google/readability-namespace-comments>`, :doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`hicpp-avoid-c-arrays <hicpp/avoid-c-arrays>`, :doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`,
:doc:`hicpp-avoid-goto <hicpp/avoid-goto>`, :doc:`cppcoreguidelines-avoid-goto <cppcoreguidelines/avoid-goto>`,
- :doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
+ :doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
:doc:`hicpp-deprecated-headers <hicpp/deprecated-headers>`, :doc:`modernize-deprecated-headers <modernize/deprecated-headers>`, "Yes"
:doc:`hicpp-explicit-conversions <hicpp/explicit-conversions>`, :doc:`google-explicit-constructor <google/explicit-constructor>`, "Yes"
:doc:`hicpp-function-size <hicpp/function-size>`, :doc:`readability-function-size <readability/function-size>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
new file mode 100644
index 0000000000000..3682a74a5119d
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -0,0 +1,62 @@
+.. title:: clang-tidy - misc-bool-bitwise-operation
+
+misc-bool-bitwise-operation
+===========================
+
+Finds potentially inefficient use of bitwise operators such as ``&``, ``|``
+and their compound analogues on Boolean values where logical operators like
+``&&`` and ``||`` would be more appropriate.
+
+Bitwise operations on Booleans can incur unnecessary performance overhead due
+to implicit integer conversions and missed short-circuit evaluation.
+
+.. code-block:: c++
+
+ bool invalid = false;
+ invalid |= x > limit.x; // warning: use logical operator '||' for boolean variable 'invalid' instead of bitwise operator '|='
+ invalid |= y > limit.y; // warning: use logical operator '||' for boolean variable 'invalid' instead of bitwise operator '|='
+ invalid |= z > limit.z; // warning: use logical operator '||' for boolean variable 'invalid' instead of bitwise operator '|='
+ if (invalid) {
+ // error handling
+ }
+
+These 3 warnings suggest assigning the result of a logical ``||`` operation
+instead of using the ``|=`` operator:
+
+.. code-block:: c++
+
+ bool invalid = false;
+ invalid = invalid || x > limit.x;
+ invalid = invalid || y > limit.x;
+ invalid = invalid || z > limit.z;
+ if (invalid) {
+ // error handling
+ }
+
+Limitations
+-----------
+
+* Bitwise operators inside templates aren't matched.
+
+.. code-block:: c++
+
+ template <typename X>
+ void f(X a, X b) {
+ a | b;
+ }
+
+ // even 'f(true, false)' (or similar) won't trigger the warning.
+
+Options
+-------
+
+.. option:: StrictMode
+
+ Enabling this option promotes more fix-it hints even when they might
+ change evaluation order or skip side effects. Default value is `false`.
+
+.. option:: IgnoreMacros
+
+ This option disables the warning if a macro inside the expression body
+ prevents replacing a bitwise operator with a logical one. Default value
+ is `false`.
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
new file mode 100644
index 0000000000000..a92d32f55701f
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
@@ -0,0 +1,82 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t \
+// RUN: -config="{CheckOptions: { \
+// RUN: misc-bool-bitwise-operation.StrictMode: true }}"
+
+bool function_with_possible_side_effects();
+
+void bad_possible_side_effects() {
+ bool a = true, b = false;
+
+ a | function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || function_with_possible_side_effects();
+
+ a & function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && function_with_possible_side_effects();
+
+ a |= function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || function_with_possible_side_effects();
+
+ a &= function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && function_with_possible_side_effects();
+
+ bool c = true;
+
+ a &= function_with_possible_side_effects() && c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && function_with_possible_side_effects() && c;
+
+ a &= b && function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && b && function_with_possible_side_effects();
+
+ a |= function_with_possible_side_effects() || c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || function_with_possible_side_effects() || c;
+
+ a |= b || function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || b || function_with_possible_side_effects();
+}
+
+void bad_definitely_side_effects() {
+ bool a = true, b = false;
+ int acc = 0;
+
+ a | (acc++, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a & (acc++, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= (acc++, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a &= (acc++, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ bool c = true;
+
+ a &= (acc++, b) && c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a &= b && (acc++, c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= (acc++, b) || c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= b || (acc++, c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
new file mode 100644
index 0000000000000..5b879063bae6b
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t \
+// RUN: -config="{CheckOptions: { \
+// RUN: misc-bool-bitwise-operation.IgnoreMacros: true }}"
+
+#define CAT(a, b) a ## b
+#define IDENT(a) a
+
+void bad_in_macro() {
+ bool a = true, b = false;
+
+ // change operator - BAD
+ IDENT(a |) b;
+ a IDENT(& b);
+ IDENT(a |=) b;
+ a IDENT(&= b);
+
+ // change operator - GOOD
+ IDENT(a) | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a) || b;
+ a & IDENT(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && IDENT(b);
+ IDENT(a) & IDENT(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a) && IDENT(b);
+
+ // insert `)` - BAD
+ bool c = true, e = false;
+ a && b | IDENT(c &&) e;
+
+ // insert `)` - GOOD
+ a && b | c IDENT(&& e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && (b || c) IDENT(&& e);
+
+ // insert `(` - BAD
+ a IDENT(&& b) | c && e;
+
+ // insert `(` - GOOD
+ IDENT(a &&) b | c && e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a &&) (b || c) && e;
+
+ bool ab = false;
+ // insert ` = a` - BAD
+ CAT(a, b) &= b;
+
+ // insert ` = a`- GOOD
+ b &= CAT(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'b' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = b && CAT(a, b);
+}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
new file mode 100644
index 0000000000000..d0700dbe309b5
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -0,0 +1,399 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+bool& normal() {
+ int a = 100, b = 200;
+
+ a bitor b;
+ a bitand b;
+ a or_eq b;
+ a and_eq b;
+
+ static bool st = false;
+ return st;
+}
+
+bool bad() noexcept __attribute__((pure)) {
+ bool a = true, b = false;
+ a bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or b;
+ a bitand b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and b;
+ a or_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a or b;
+ a and_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a and b;
+
+ return true;
+}
+
+bool global_1 = bad() bitor bad();
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: bool global_1 = bad() or bad();
+bool global_2 = bad() bitand bad();
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+// CHECK-FIXES: bool global_2 = bad() and bad();
+
+using Boolean = bool;
+
+bool bad_typedef() {
+ Boolean a = true, b = false;
+ a bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or b;
+ a bitand b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and b;
+ a or_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a or b;
+ a and_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a and b;
+ return true;
+}
+
+bool function_with_possible_side_effects();
+
+void bad_side_effects() {
+ bool a = true, b = false;
+
+ a bitor function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a bitand function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ function_with_possible_side_effects() bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() or a;
+
+ function_with_possible_side_effects() bitand a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() and a;
+ a or_eq function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a and_eq function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // count of evaluation with side effect remains the same, so the fixit will be provided
+ bool c = true;
+
+ a or function_with_possible_side_effects() bitor c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or function_with_possible_side_effects() or c;
+
+ function_with_possible_side_effects() or b bitor c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() or b or c;
+
+ a and function_with_possible_side_effects() bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and function_with_possible_side_effects() and c;
+
+ function_with_possible_side_effects() and b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() and b and c;
+
+ // but here the count of evaluation migh be changed - no fix must be provided
+
+ a and_eq function_with_possible_side_effects() and c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a and_eq b and function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a or_eq function_with_possible_side_effects() or c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a or_eq b or function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+void bad_side_effects_volatile() {
+ bool a = true;
+ volatile bool b = false;
+ a bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a bitand b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a or_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a and_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+void bad_with_priors() {
+ bool a = false, b = true, c = true;
+ a and b bitor c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and (b or c);
+ a and b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and b and c;
+ a or b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or b and c;
+ a or b bitor c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or b or c;
+ b bitor c and a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b or c) and a;
+
+ bool q = (true and false bitor true) and (false bitor true and (false and true bitor false));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:53: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:84: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool q = (true and (false or true)) and ((false or true) and (false and (true or false)));
+}
+
+void bad_with_priors2() {
+ bool a = false, b = true, c = true;
+ a xor b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a xor (b and c);
+
+ // braces added in the first change
+ a bitor b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or (b and c);
+
+ b bitand c xor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) xor a;
+
+ // braces added in the first change
+ b bitand c bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) or a;
+}
+
+template<typename T>
+T ident(T val) { return val; }
+
+// cases to check `hasAncestor` works as we expected:
+void bad_has_ancestor() {
+ bool a = false, b = true, c = true;
+ bool d = false;
+ d xor (a and b bitand c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: d xor (a and b and c);
+
+ a xor ident(b bitand c or a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a xor ident(b and c or a);
+
+ a bitor ident(a ? b bitand c : c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a bitor ident(a ? b and c : c);
+}
+
+void bad_with_priors_already_braced() {
+ bool a = false, b = true, c = true;
+ a and (b bitor c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and (b or c);
+ (b bitor c) and a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b or c) and a;
+
+ bool q = (true and (false bitor true)) and ((false bitor true) and (false and (true bitor false)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:56: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:89: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool q = (true and (false or true)) and ((false or true) and (false and (true or false)));
+
+ a xor (b bitand c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a xor (b and c);
+
+ a bitor (b bitand c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or (b and c);
+
+ (b bitand c) xor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) xor a;
+
+ (b bitand c) bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) or a;
+}
+
+void bad_with_priors_compound() {
+ bool a = false, b = true, c = true;
+ a and_eq b or c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a and (b or c);
+ a or_eq b or c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a or b or c;
+ a and_eq b and c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a and b and c;
+ a or_eq b and c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a or b and c;
+}
+
+void bad_with_priors_compound_already_braced() {
+ bool a = false, b = true, c = true;
+ a and_eq (b or c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a and (b or c);
+}
+
+void bad_no_fixit() {
+ bool b = false;
+ normal() or_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ normal() and_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+#define MY_OR bitor
+#define MY_AND bitand
+#define MY_OR_ASSIGN or_eq
+#define MY_AND_ASSIGN and_eq
+#define MY_LOG_AND and
+
+#define CAT(a, b) a ## b
+#define IDENT(a) a
+
+void bad_in_macro() {
+ bool a = true, b = false;
+
+ // change operator - BAD
+ IDENT(a bitor) b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a IDENT(bitand b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ IDENT(a or_eq) b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a IDENT(and_eq b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // change operator - GOOD
+ IDENT(a) bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a) or b;
+ a bitand IDENT(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and IDENT(b);
+ IDENT(a) bitand IDENT(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a) and IDENT(b);
+
+ // insert `)` - BAD
+ bool c = true, e = false;
+ a and b bitor IDENT(c and) e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // insert `)` - GOOD
+ a and b bitor c IDENT(and e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a and (b or c) IDENT(and e);
+
+ // insert `(` - BAD
+ a IDENT(and b) bitor c and e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // insert `(` - GOOD
+ IDENT(a and) b bitor c and e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a and) (b or c) and e;
+
+ bool ab = false;
+ // insert ` = a` - BAD
+ CAT(a, b) and_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean variable 'ab' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // insert ` = a`- GOOD
+ b and_eq CAT(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'b' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = b and CAT(a, b);
+}
+
+void bad_in_macro_fixit() {
+ bool a = true, b = false;
+
+ // FIXME: implement fixit for all of these cases
+
+ a MY_OR b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ a MY_AND b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ a MY_OR_ASSIGN b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ a MY_AND_ASSIGN b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ IDENT(a and_eq b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+}
+
+template<typename T>
+void good_in_unreachable_template(T a, T b) {
+ a bitor b;
+ a bitand b;
+ a or_eq b;
+ a and_eq b;
+}
+
+template<typename T>
+int bad_in_template(T a, T b) {
+ bool c = false;
+ // FIXME: at least warning should be provided in these cases
+ // a bitor b;
+ // a bitand b;
+ // a or_eq b;
+ // a and_eq b;
+ // c and_eq a;
+ return 0;
+}
+
+template<typename T>
+int bad_in_template_lamnda_captured(T a, T b) {
+ [=] mutable {
+ bool c = false;
+ // FIXME: at least warning should be provided in these cases
+ // a bitor b;
+ // a bitand b;
+ // a or_eq b;
+ // b and_eq a;
+ }();
+ return 0;
+}
+
+int dummy = bad_in_template(true, false) + bad_in_template_lamnda_captured(false, true);
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
new file mode 100644
index 0000000000000..777189f12bbd3
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+void normal() {
+ int a = 100, b = 200;
+
+ a | b;
+ a & b;
+ a |= b;
+ a &= b;
+}
+
+void bad() {
+ _Bool a = 1, b = 0;
+ a | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || b;
+ a & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && b;
+ a |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || b;
+ a &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && b;
+}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
new file mode 100644
index 0000000000000..86db240bb6efb
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -0,0 +1,399 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+bool& normal() {
+ int a = 100, b = 200;
+
+ a | b;
+ a & b;
+ a |= b;
+ a &= b;
+
+ static bool st = false;
+ return st;
+}
+
+bool bad() noexcept __attribute__((pure)) {
+ bool a = true, b = false;
+ a | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || b;
+ a & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && b;
+ a |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || b;
+ a &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && b;
+
+ return true;
+}
+
+bool global_1 = bad() | bad();
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: bool global_1 = bad() || bad();
+bool global_2 = bad() & bad();
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+// CHECK-FIXES: bool global_2 = bad() && bad();
+
+using Boolean = bool;
+
+bool bad_typedef() {
+ Boolean a = true, b = false;
+ a | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || b;
+ a & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && b;
+ a |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || b;
+ a &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && b;
+ return true;
+}
+
+bool function_with_possible_side_effects();
+
+void bad_side_effects() {
+ bool a = true, b = false;
+
+ a | function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a & function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ function_with_possible_side_effects() | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() || a;
+
+ function_with_possible_side_effects() & a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() && a;
+ a |= function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a &= function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // count of evaluation with side effect remains the same, so the fixit will be provided
+ bool c = true;
+
+ a || function_with_possible_side_effects() | c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || function_with_possible_side_effects() || c;
+
+ function_with_possible_side_effects() || b | c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() || b || c;
+
+ a && function_with_possible_side_effects() & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && function_with_possible_side_effects() && c;
+
+ function_with_possible_side_effects() && b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: function_with_possible_side_effects() && b && c;
+
+ // but here the count of evaluation migh be changed - no fix must be provided
+
+ a &= function_with_possible_side_effects() && c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a &= b && function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= function_with_possible_side_effects() || c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= b || function_with_possible_side_effects();
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+void bad_side_effects_volatile() {
+ bool a = true;
+ volatile bool b = false;
+ a | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+void bad_with_priors() {
+ bool a = false, b = true, c = true;
+ a && b | c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && (b || c);
+ a && b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && b && c;
+ a || b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || b && c;
+ a || b | c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || b || c;
+ b | c && a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b || c) && a;
+
+ bool q = (true && false | true) && (false | true && (false && true | false));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:72: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool q = (true && (false || true)) && ((false || true) && (false && (true || false)));
+}
+
+void bad_with_priors2() {
+ bool a = false, b = true, c = true;
+ a ^ b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a ^ (b && c);
+
+ // braces added in the first change
+ a | b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || (b && c);
+
+ b & c ^ a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) ^ a;
+
+ // braces added in the first change
+ b & c | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) || a;
+}
+
+template<typename T>
+T ident(T val) { return val; }
+
+// cases to check `hasAncestor` works as we expected:
+void bad_has_ancestor() {
+ bool a = false, b = true, c = true;
+ bool d = false;
+ d ^ (a && b & c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: d ^ (a && b && c);
+
+ a ^ ident(b & c || a);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a ^ ident(b && c || a);
+
+ a | ident(a ? b & c : c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a | ident(a ? b && c : c);
+}
+
+void bad_with_priors_already_braced() {
+ bool a = false, b = true, c = true;
+ a && (b | c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && (b || c);
+ (b | c) && a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b || c) && a;
+
+ bool q = (true && (false | true)) && ((false | true) && (false && (true | false)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:50: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:77: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool q = (true && (false || true)) && ((false || true) && (false && (true || false)));
+
+ a ^ (b & c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a ^ (b && c);
+
+ a | (b & c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || (b && c);
+
+ (b & c) ^ a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) ^ a;
+
+ (b & c) | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) || a;
+}
+
+void bad_with_priors_compound() {
+ bool a = false, b = true, c = true;
+ a &= b || c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && (b || c);
+ a |= b || c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || b || c;
+ a &= b && c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && b && c;
+ a |= b && c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a || b && c;
+}
+
+void bad_with_priors_compound_already_braced() {
+ bool a = false, b = true, c = true;
+ a &= (b || c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a = a && (b || c);
+}
+
+void bad_no_fixit() {
+ bool b = false;
+ normal() |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ normal() &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+#define MY_OR |
+#define MY_AND &
+#define MY_OR_ASSIGN |=
+#define MY_AND_ASSIGN &=
+#define MY_LOG_AND &&
+
+#define CAT(a, b) a ## b
+#define IDENT(a) a
+
+void bad_in_macro() {
+ bool a = true, b = false;
+
+ // change operator - BAD
+ IDENT(a |) b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a IDENT(& b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ IDENT(a |=) b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a IDENT(&= b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // change operator - GOOD
+ IDENT(a) | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a) || b;
+ a & IDENT(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && IDENT(b);
+ IDENT(a) & IDENT(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a) && IDENT(b);
+
+ // insert `)` - BAD
+ bool c = true, e = false;
+ a && b | IDENT(c &&) e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // insert `)` - GOOD
+ a && b | c IDENT(&& e);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && (b || c) IDENT(&& e);
+
+ // insert `(` - BAD
+ a IDENT(&& b) | c && e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // insert `(` - GOOD
+ IDENT(a &&) b | c && e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: IDENT(a &&) (b || c) && e;
+
+ bool ab = false;
+ // insert ` = a` - BAD
+ CAT(a, b) &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean variable 'ab' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // insert ` = a`- GOOD
+ b &= CAT(a, b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'b' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = b && CAT(a, b);
+}
+
+void bad_in_macro_fixit() {
+ bool a = true, b = false;
+
+ // FIXME: implement fixit for all of these cases
+
+ a MY_OR b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ a MY_AND b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ a MY_OR_ASSIGN b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ a MY_AND_ASSIGN b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ IDENT(a &= b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+}
+
+template<typename T>
+void good_in_unreachable_template(T a, T b) {
+ a | b;
+ a & b;
+ a |= b;
+ a &= b;
+}
+
+template<typename T>
+int bad_in_template(T a, T b) {
+ bool c = false;
+ // FIXME: at least warning should be provided in these cases
+ // a | b;
+ // a & b;
+ // a |= b;
+ // a &= b;
+ // c &= a;
+ return 0;
+}
+
+template<typename T>
+int bad_in_template_lamnda_captured(T a, T b) {
+ [=] mutable {
+ bool c = false;
+ // FIXME: at least warning should be provided in these cases
+ // a | b;
+ // a & b;
+ // a |= b;
+ // b &= a;
+ }();
+ return 0;
+}
+
+int dummy = bad_in_template(true, false) + bad_in_template_lamnda_captured(false, true);
\ No newline at end of file
>From 0a1b47f8e3e6057fb8940a5873b6426ad6774697 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Thu, 6 Nov 2025 19:59:01 +0300
Subject: [PATCH 02/49] Fix realworld case with unsigned flags
---
.../misc/BoolBitwiseOperationCheck.cpp | 72 ++++++-
.../bool-bitwise-operation-nontraditional.cpp | 43 ++--
...itwise-operation-not-only-bool-operand.cpp | 197 ++++++++++++++++++
.../checkers/misc/bool-bitwise-operation.cpp | 44 ++--
4 files changed, 311 insertions(+), 45 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index f37e1482c4a7d..6880322d85390 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -17,6 +17,68 @@ using namespace clang::ast_matchers;
namespace clang::tidy::misc {
+static const Stmt* ignoreParenExpr(const Stmt* S) {
+ while (const auto* PE = dyn_cast<ParenExpr>(S)) {
+ S = PE->getSubExpr();
+ }
+ return S;
+}
+
+template<typename R>
+static bool
+containsNodeIgnoringParenExpr(R&& children, const Stmt* Node) {
+ for (const Stmt* Child : children) {
+ if (ignoreParenExpr(Child) == Node) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool isBooleanImplicitCastStmt(const Stmt* S) {
+ const auto* ICE = dyn_cast<ImplicitCastExpr>(S);
+ return ICE && ICE->getType()->isBooleanType();
+}
+
+namespace {
+AST_MATCHER(BinaryOperator, assignsToBoolean) {
+ auto Parents = Finder->getASTContext().getParents(Node);
+
+ for (const auto& Parent : Parents) {
+ // Check for Decl parents
+ if (const auto* D = Parent.template get<Decl>()) {
+ const Expr* InitExpr = nullptr;
+
+ if (const auto* VD = dyn_cast<VarDecl>(D)) {
+ InitExpr = VD->getInit();
+ } else if (const auto* FD = dyn_cast<FieldDecl>(D)) {
+ InitExpr = FD->getInClassInitializer();
+ } else if (const auto* NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ if (NTTPD->getType()->isBooleanType()) {
+ return true;
+ }
+ }
+
+ if (InitExpr && isBooleanImplicitCastStmt(InitExpr)) {
+ return true;
+ }
+ }
+
+ // Check for Stmt parents
+ if (const auto* S = Parent.template get<Stmt>()) {
+ for (const Stmt* Child : S->children()) {
+ if (isBooleanImplicitCastStmt(Child) && containsNodeIgnoringParenExpr(Child->children(), &Node)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+} // namespace
+
static const NamedDecl *
getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
if (BO->isCompoundAssignmentOp()) {
@@ -27,6 +89,8 @@ getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
return nullptr;
}
+constexpr std::array<llvm::StringRef, 4U> OperatorsNames{"|", "&", "|=", "&="};
+
constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
OperatorsTransformation{{{"|", "||"},
{"|=", "||"},
@@ -62,8 +126,12 @@ void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
binaryOperator(
unless(isExpansionInSystemHeader()),
- hasAnyOperatorName("|", "&", "|=", "&="),
- hasEitherOperand(expr(hasType(booleanType()))),
+ hasAnyOperatorName(OperatorsNames),
+ anyOf(
+ hasOperands(expr(hasType(booleanType())), expr(hasType(booleanType()))),
+ assignsToBoolean()
+ ),
+ // isBooleanLikeOperands(),
optionally(hasParent( // to simple implement transformations like
// `a&&b|c` -> `a&&(b||c)`
binaryOperator().bind("p"))))
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index d0700dbe309b5..59ee910fbfa5d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -167,25 +167,26 @@ void bad_with_priors() {
void bad_with_priors2() {
bool a = false, b = true, c = true;
+ bool r;
a xor b bitand c;
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor (b and c);
// braces added in the first change
- a bitor b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: a or (b and c);
+ r = a bitor b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = a or (b and c);
- b bitand c xor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: (b and c) xor a;
+ r = b bitand c xor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (b and c) xor a;
// braces added in the first change
- b bitand c bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: (b and c) or a;
+ r = b bitand c bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (b and c) or a;
}
template<typename T>
@@ -204,13 +205,13 @@ void bad_has_ancestor() {
// CHECK-FIXES: a xor ident(b and c or a);
a bitor ident(a ? b bitand c : c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a bitor ident(a ? b and c : c);
}
void bad_with_priors_already_braced() {
bool a = false, b = true, c = true;
+ bool r;
a and (b bitor c);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and (b or c);
@@ -228,19 +229,19 @@ void bad_with_priors_already_braced() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor (b and c);
- a bitor (b bitand c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: a or (b and c);
+ r = a bitor (b bitand c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = a or (b and c);
(b bitand c) xor a;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b and c) xor a;
- (b bitand c) bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: (b and c) or a;
+ r = (b bitand c) bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (b and c) or a;
}
void bad_with_priors_compound() {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
new file mode 100644
index 0000000000000..6c3fd5ff0a140
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -0,0 +1,197 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+// got from clang/lib/APINotes/APINotesWriter.cpp
+
+void general(unsigned flags, bool value) {
+ (flags << 1) | value;
+ flags = (flags << 1) | value;
+}
+
+void take(bool value) {}
+
+// TODO: (flags << 1) | (flags << 2) | value
+
+template<bool bb = true | 1>
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: template<bool bb = true || 1>
+void assign_to_boolean(unsigned flags, bool value) {
+ struct A { bool a = true | 1; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct A { bool a = true || 1; };
+ struct B { union { bool a = true | 1; }; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct B { union { bool a = true || 1; }; };
+ bool result = (flags << 1) | value;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result = (flags << 1) || value;
+ bool a = (flags << 2) | value,
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a = (flags << 2) || value,
+ b = (flags << 4) | value,
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = (flags << 4) || value,
+ c = (flags << 8) | value;
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c = (flags << 8) || value;
+ result = (flags << 1) | value;
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (flags << 1) || value;
+ take((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take((flags << 1) || value);
+}
+
+template<bool bb = (true | 1)>
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: template<bool bb = (true || 1)>
+void assign_to_boolean_parens(unsigned flags, bool value) {
+ struct A { bool a = (true | 1); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct A { bool a = (true || 1); };
+ struct B { union { bool a = (true | 1); }; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct B { union { bool a = (true || 1); }; };
+ bool result = ((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result = ((flags << 1) || value);
+ bool a = ((flags << 2) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a = ((flags << 2) || value),
+ b = ((flags << 4) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = ((flags << 4) || value),
+ c = ((flags << 8) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c = ((flags << 8) || value);
+ result = ((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = ((flags << 1) || value);
+ take(((flags << 1) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(((flags << 1) || value));
+}
+
+template<bool bb = ((true | 1))>
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: template<bool bb = ((true || 1))>
+void assign_to_boolean_parens2(unsigned flags, bool value) {
+ struct A { bool a = ((true | 1)); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct A { bool a = ((true || 1)); };
+ struct B { union { bool a = ((true | 1)); }; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct B { union { bool a = ((true || 1)); }; };
+ bool result = (((flags << 1) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result = (((flags << 1) || value));
+ bool a = (((flags << 2) | value)),
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a = (((flags << 2) || value)),
+ b = (((flags << 4) | value)),
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = (((flags << 4) || value)),
+ c = (((flags << 8) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c = (((flags << 8) || value));
+ result = (((flags << 1) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (((flags << 1) || value));
+ take((((flags << 1) | value)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take((((flags << 1) || value)));
+}
+
+// functional cast
+template<bool bb = bool(true | 1)>
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: template<bool bb = bool(true || 1)>
+void assign_to_boolean_fcast(unsigned flags, bool value) {
+ struct A { bool a = bool(true | 1); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct A { bool a = bool(true || 1); };
+ struct B { union { bool a = bool(true | 1); }; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct B { union { bool a = bool(true || 1); }; };
+ bool result = bool((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result = bool((flags << 1) || value);
+ bool a = bool((flags << 2) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a = bool((flags << 2) || value),
+ b = bool((flags << 4) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = bool((flags << 4) || value),
+ c = bool((flags << 8) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c = bool((flags << 8) || value);
+ result = bool((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = bool((flags << 1) || value);
+ take(bool((flags << 1) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(bool((flags << 1) || value));
+}
+
+// C-style cast
+template<bool bb = (bool)(true | 1)>
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: template<bool bb = (bool)(true || 1)>
+void assign_to_boolean_ccast(unsigned flags, bool value) {
+ struct A { bool a = (bool)(true | 1); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct A { bool a = (bool)(true || 1); };
+ struct B { union { bool a = (bool)(true | 1); }; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct B { union { bool a = (bool)(true || 1); }; };
+ bool result = (bool)((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result = (bool)((flags << 1) || value);
+ bool a = (bool)((flags << 2) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a = (bool)((flags << 2) || value),
+ b = (bool)((flags << 4) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = (bool)((flags << 4) || value),
+ c = (bool)((flags << 8) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c = (bool)((flags << 8) || value);
+ result = (bool)((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (bool)((flags << 1) || value);
+ take(bool((flags << 1) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(bool((flags << 1) || value));
+}
+
+// static_cast
+template<bool bb = static_cast<bool>(true | 1)>
+// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-FIXES: template<bool bb = static_cast<bool>(true || 1)>
+void assign_to_boolean_scast(unsigned flags, bool value) {
+ struct A { bool a = static_cast<bool>(true | 1); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct A { bool a = static_cast<bool>(true || 1); };
+ struct B { union { bool a = static_cast<bool>(true | 1); }; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: struct B { union { bool a = static_cast<bool>(true || 1); }; };
+ bool result = static_cast<bool>((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result = static_cast<bool>((flags << 1) || value);
+ bool a = static_cast<bool>((flags << 2) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a = static_cast<bool>((flags << 2) || value),
+ b = static_cast<bool>((flags << 4) | value),
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b = static_cast<bool>((flags << 4) || value),
+ c = static_cast<bool>((flags << 8) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c = static_cast<bool>((flags << 8) || value);
+ result = static_cast<bool>((flags << 1) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = static_cast<bool>((flags << 1) || value);
+ take(static_cast<bool>((flags << 1) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(static_cast<bool>((flags << 1) || value));
+}
+
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 86db240bb6efb..f58bd7c513ac9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -167,25 +167,25 @@ void bad_with_priors() {
void bad_with_priors2() {
bool a = false, b = true, c = true;
+ bool r;
a ^ b & c;
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ (b && c);
-
// braces added in the first change
- a | b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: a || (b && c);
+ r = a | b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = a || (b && c);
- b & c ^ a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: (b && c) ^ a;
+ r = b & c ^ a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (b && c) ^ a;
// braces added in the first change
- b & c | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: (b && c) || a;
+ r = b & c | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (b && c) || a;
}
template<typename T>
@@ -204,13 +204,13 @@ void bad_has_ancestor() {
// CHECK-FIXES: a ^ ident(b && c || a);
a | ident(a ? b & c : c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a | ident(a ? b && c : c);
}
void bad_with_priors_already_braced() {
bool a = false, b = true, c = true;
+ bool r;
a && (b | c);
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && (b || c);
@@ -228,19 +228,19 @@ void bad_with_priors_already_braced() {
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ (b && c);
- a | (b & c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: a || (b && c);
+ r = a | (b & c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = a || (b && c);
(b & c) ^ a;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b && c) ^ a;
- (b & c) | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: (b && c) || a;
+ r = (b & c) | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (b && c) || a;
}
void bad_with_priors_compound() {
>From 5bc7f73ca5522972e1680511010bc8a665cd8281 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Fri, 7 Nov 2025 19:02:36 +0300
Subject: [PATCH 03/49] refactor a lot
---
.../misc/BoolBitwiseOperationCheck.cpp | 195 +++++++++---------
.../misc/BoolBitwiseOperationCheck.h | 9 +
.../bool-bitwise-operation-nontraditional.cpp | 13 ++
.../checkers/misc/bool-bitwise-operation.cpp | 13 ++
4 files changed, 137 insertions(+), 93 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 6880322d85390..1df170e5353f9 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -17,68 +17,46 @@ using namespace clang::ast_matchers;
namespace clang::tidy::misc {
-static const Stmt* ignoreParenExpr(const Stmt* S) {
- while (const auto* PE = dyn_cast<ParenExpr>(S)) {
- S = PE->getSubExpr();
- }
- return S;
-}
-
-template<typename R>
-static bool
-containsNodeIgnoringParenExpr(R&& children, const Stmt* Node) {
- for (const Stmt* Child : children) {
- if (ignoreParenExpr(Child) == Node) {
- return true;
+static const DynTypedNode *ignoreParensTowardsTheRoot(const DynTypedNode *N,
+ ASTContext *AC) {
+ if (const auto *S = N->get<Stmt>()) {
+ if (isa<ParenExpr>(S)) {
+ auto Parents = AC->getParents(*S);
+ for (const auto &Parent : Parents) {
+ return ignoreParensTowardsTheRoot(&Parent, AC);
+ }
}
}
- return false;
+ return N;
}
-static bool isBooleanImplicitCastStmt(const Stmt* S) {
- const auto* ICE = dyn_cast<ImplicitCastExpr>(S);
- return ICE && ICE->getType()->isBooleanType();
-}
+static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
+ TraversalKindScope RAII(*AC, TK_AsIs);
+ auto Parents = AC->getParents(*BinOp);
-namespace {
-AST_MATCHER(BinaryOperator, assignsToBoolean) {
- auto Parents = Finder->getASTContext().getParents(Node);
-
- for (const auto& Parent : Parents) {
- // Check for Decl parents
- if (const auto* D = Parent.template get<Decl>()) {
- const Expr* InitExpr = nullptr;
-
- if (const auto* VD = dyn_cast<VarDecl>(D)) {
- InitExpr = VD->getInit();
- } else if (const auto* FD = dyn_cast<FieldDecl>(D)) {
- InitExpr = FD->getInClassInitializer();
- } else if (const auto* NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ for (const auto &Parent : Parents) {
+ const auto *ParentNoParen = ignoreParensTowardsTheRoot(&Parent, AC);
+ // Special handling for `template<bool bb=true|1>` cases
+ if (const auto *D = ParentNoParen->get<Decl>()) {
+ if (const auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
if (NTTPD->getType()->isBooleanType()) {
return true;
}
}
-
- if (InitExpr && isBooleanImplicitCastStmt(InitExpr)) {
- return true;
- }
}
-
- // Check for Stmt parents
- if (const auto* S = Parent.template get<Stmt>()) {
- for (const Stmt* Child : S->children()) {
- if (isBooleanImplicitCastStmt(Child) && containsNodeIgnoringParenExpr(Child->children(), &Node)) {
+
+ if (const auto *S = ParentNoParen->get<Stmt>()) {
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(S)) {
+ if (ICE->getType()->isBooleanType()) {
return true;
}
}
}
}
-
+
return false;
}
-} // namespace
-
static const NamedDecl *
getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
if (BO->isCompoundAssignmentOp()) {
@@ -89,8 +67,6 @@ getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
return nullptr;
}
-constexpr std::array<llvm::StringRef, 4U> OperatorsNames{"|", "&", "|=", "&="};
-
constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
OperatorsTransformation{{{"|", "||"},
{"|=", "||"},
@@ -103,13 +79,32 @@ constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
static llvm::StringRef translate(llvm::StringRef Value) {
for (const auto &[Bitwise, Logical] : OperatorsTransformation) {
- if (Value == Bitwise)
+ if (Value == Bitwise) {
return Logical;
+ }
}
return {};
}
+static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC) {
+ for (const auto &[Bitwise, _] : OperatorsTransformation) {
+ if (BinOp->getOpcodeStr() == Bitwise) {
+ const bool hasBooleanOperands = llvm::all_of(
+ std::array{BinOp->getLHS(), BinOp->getRHS()}, [](const Expr *E) {
+ return E->IgnoreImpCasts()->getType().getTypePtr()->isBooleanType();
+ });
+ if (hasBooleanOperands) {
+ return true;
+ }
+ if (assignsToBoolean(BinOp, AC)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
@@ -124,52 +119,43 @@ void BoolBitwiseOperationCheck::storeOptions(
void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- binaryOperator(
- unless(isExpansionInSystemHeader()),
- hasAnyOperatorName(OperatorsNames),
- anyOf(
- hasOperands(expr(hasType(booleanType())), expr(hasType(booleanType()))),
- assignsToBoolean()
- ),
- // isBooleanLikeOperands(),
- optionally(hasParent( // to simple implement transformations like
- // `a&&b|c` -> `a&&(b||c)`
- binaryOperator().bind("p"))))
- .bind("op"),
+ binaryOperator(unless(isExpansionInSystemHeader()),
+ unless(hasParent(binaryOperator())) // ignoring parenExpr
+ )
+ .bind("binOpRoot"),
this);
}
-void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *MatchedExpr = Result.Nodes.getNodeAs<BinaryOperator>("op");
-
- auto DiagEmitter = [MatchedExpr, this] {
- const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign(MatchedExpr);
- return diag(MatchedExpr->getOperatorLoc(),
+void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
+ const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+ const clang::SourceManager &SM, clang::ASTContext &Ctx) {
+ auto DiagEmitter = [BinOp, this] {
+ const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign(BinOp);
+ return diag(BinOp->getOperatorLoc(),
"use logical operator '%0' for boolean %select{variable "
"%2|values}1 instead of bitwise operator '%3'")
- << translate(MatchedExpr->getOpcodeStr()) << (ND == nullptr) << ND
- << MatchedExpr->getOpcodeStr();
+ << translate(BinOp->getOpcodeStr()) << (ND == nullptr) << ND
+ << BinOp->getOpcodeStr();
};
const bool HasVolatileOperand = llvm::any_of(
- std::array{MatchedExpr->getLHS(), MatchedExpr->getRHS()},
- [](const Expr *E) {
+ std::array{BinOp->getLHS(), BinOp->getRHS()}, [](const Expr *E) {
return E->IgnoreImpCasts()->getType().isVolatileQualified();
});
if (HasVolatileOperand)
return static_cast<void>(DiagEmitter());
- const bool HasSideEffects = MatchedExpr->getRHS()->HasSideEffects(
- *Result.Context, /*IncludePossibleEffects=*/!StrictMode);
+ const bool HasSideEffects = BinOp->getRHS()->HasSideEffects(
+ Ctx, /*IncludePossibleEffects=*/!StrictMode);
if (HasSideEffects)
return static_cast<void>(DiagEmitter());
- SourceLocation Loc = MatchedExpr->getOperatorLoc();
+ SourceLocation Loc = BinOp->getOperatorLoc();
if (Loc.isInvalid() || Loc.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
- Loc = Result.SourceManager->getSpellingLoc(Loc);
+ Loc = SM.getSpellingLoc(Loc);
if (Loc.isInvalid() || Loc.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
@@ -177,23 +163,23 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
if (TokenRange.isInvalid())
return static_cast<void>(IgnoreMacros || DiagEmitter());
- const StringRef FixSpelling = translate(Lexer::getSourceText(
- TokenRange, *Result.SourceManager, Result.Context->getLangOpts()));
+ const StringRef FixSpelling =
+ translate(Lexer::getSourceText(TokenRange, SM, Ctx.getLangOpts()));
if (FixSpelling.empty())
return static_cast<void>(DiagEmitter());
FixItHint InsertEqual;
- if (MatchedExpr->isCompoundAssignmentOp()) {
+ if (BinOp->isCompoundAssignmentOp()) {
const auto *DeclRefLHS =
- dyn_cast<DeclRefExpr>(MatchedExpr->getLHS()->IgnoreImpCasts());
+ dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts());
if (!DeclRefLHS)
return static_cast<void>(DiagEmitter());
const SourceLocation LocLHS = DeclRefLHS->getEndLoc();
if (LocLHS.isInvalid() || LocLHS.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
- const SourceLocation InsertLoc = clang::Lexer::getLocForEndOfToken(
- LocLHS, 0, *Result.SourceManager, Result.Context->getLangOpts());
+ const SourceLocation InsertLoc =
+ clang::Lexer::getLocForEndOfToken(LocLHS, 0, SM, Ctx.getLangOpts());
if (InsertLoc.isInvalid() || InsertLoc.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
InsertEqual = FixItHint::CreateInsertion(
@@ -202,27 +188,25 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
auto ReplaceOperator = FixItHint::CreateReplacement(TokenRange, FixSpelling);
- const auto *Parent = Result.Nodes.getNodeAs<BinaryOperator>("p");
std::optional<BinaryOperatorKind> ParentOpcode;
- if (Parent)
- ParentOpcode = Parent->getOpcode();
+ if (ParentBinOp)
+ ParentOpcode = ParentBinOp->getOpcode();
- const auto *RHS =
- dyn_cast<BinaryOperator>(MatchedExpr->getRHS()->IgnoreImpCasts());
+ const auto *RHS = dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts());
std::optional<BinaryOperatorKind> RHSOpcode;
if (RHS)
RHSOpcode = RHS->getOpcode();
const Expr *SurroundedExpr = nullptr;
- if ((MatchedExpr->getOpcode() == BO_Or && ParentOpcode == BO_LAnd) ||
- (MatchedExpr->getOpcode() == BO_And &&
+ if ((BinOp->getOpcode() == BO_Or && ParentOpcode == BO_LAnd) ||
+ (BinOp->getOpcode() == BO_And &&
llvm::is_contained({BO_Xor, BO_Or}, ParentOpcode))) {
- const Expr *Side = Parent->getLHS()->IgnoreParenImpCasts() == MatchedExpr
- ? Parent->getLHS()
- : Parent->getRHS();
+ const Expr *Side = ParentBinOp->getLHS()->IgnoreParenImpCasts() == BinOp
+ ? ParentBinOp->getLHS()
+ : ParentBinOp->getRHS();
SurroundedExpr = Side->IgnoreImpCasts();
- assert(SurroundedExpr->IgnoreParens() == MatchedExpr);
- } else if (MatchedExpr->getOpcode() == BO_AndAssign && RHSOpcode == BO_LOr)
+ assert(SurroundedExpr->IgnoreParens() == BinOp);
+ } else if (BinOp->getOpcode() == BO_AndAssign && RHSOpcode == BO_LOr)
SurroundedExpr = RHS;
if (SurroundedExpr && isa<ParenExpr>(SurroundedExpr))
@@ -233,8 +217,7 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
if (SurroundedExpr) {
const SourceLocation InsertFirstLoc = SurroundedExpr->getBeginLoc();
const SourceLocation InsertSecondLoc = clang::Lexer::getLocForEndOfToken(
- SurroundedExpr->getEndLoc(), 0, *Result.SourceManager,
- Result.Context->getLangOpts());
+ SurroundedExpr->getEndLoc(), 0, SM, Ctx.getLangOpts());
if (InsertFirstLoc.isInvalid() || InsertFirstLoc.isMacroID() ||
InsertSecondLoc.isInvalid() || InsertSecondLoc.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
@@ -246,4 +229,30 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
<< InsertBrace2;
}
+void BoolBitwiseOperationCheck::visitBinaryTreesNode(
+ const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+ const clang::SourceManager &SM, clang::ASTContext &Ctx) {
+ if (!BinOp) {
+ return;
+ }
+
+ if (isBooleanBitwise(BinOp, &Ctx)) {
+ emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx);
+ }
+
+ visitBinaryTreesNode(
+ dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp,
+ SM, Ctx);
+ visitBinaryTreesNode(
+ dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp,
+ SM, Ctx);
+}
+
+void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *binOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
+ const SourceManager &SM = *Result.SourceManager;
+ ASTContext &Ctx = *Result.Context;
+ visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx);
+}
+
} // namespace clang::tidy::misc
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index b1056e53c50c9..e1939afe772a7 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -32,6 +32,15 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
return TK_IgnoreUnlessSpelledInSource;
}
+private:
+ void emitWarningAndChangeOperatorsIfPossible(
+ const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+ const clang::SourceManager &SM, clang::ASTContext &Ctx);
+ void visitBinaryTreesNode(const BinaryOperator *BinOp,
+ const BinaryOperator *ParentBinOp,
+ const clang::SourceManager &SM,
+ clang::ASTContext &Ctx);
+
private:
bool StrictMode;
bool IgnoreMacros;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 59ee910fbfa5d..4b50072849919 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -125,6 +125,9 @@ void bad_side_effects() {
void bad_side_effects_volatile() {
bool a = true;
volatile bool b = false;
+ bool c = true;
+ bool r;
+
a bitor b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
@@ -138,6 +141,16 @@ void bad_side_effects_volatile() {
a and_eq b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ r = (a bitor c) bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (a or c) bitor b;
+
+ r = a bitor c bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = a or c bitor b;
}
void bad_with_priors() {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index f58bd7c513ac9..56ca15b8d6729 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -125,6 +125,9 @@ void bad_side_effects() {
void bad_side_effects_volatile() {
bool a = true;
volatile bool b = false;
+ bool c = true;
+ bool r;
+
a | b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
@@ -138,6 +141,16 @@ void bad_side_effects_volatile() {
a &= b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ r = (a | c) | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = (a || c) | b;
+
+ r = a | c | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: r = a || c | b;
}
void bad_with_priors() {
>From 14dcf62ce58fe5e70ec70c9136711d3d5b1e4ae8 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Fri, 7 Nov 2025 20:01:30 +0300
Subject: [PATCH 04/49] Implement more cases with unsigned flags
---
.../misc/BoolBitwiseOperationCheck.cpp | 18 +++---
.../misc/BoolBitwiseOperationCheck.h | 3 +-
...itwise-operation-not-only-bool-operand.cpp | 60 ++++++++++++++++++-
3 files changed, 71 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 1df170e5353f9..c89050bd70d5d 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -87,7 +87,7 @@ static llvm::StringRef translate(llvm::StringRef Value) {
return {};
}
-static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC) {
+static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::optional<bool>& rootAssignsToBoolean) {
for (const auto &[Bitwise, _] : OperatorsTransformation) {
if (BinOp->getOpcodeStr() == Bitwise) {
const bool hasBooleanOperands = llvm::all_of(
@@ -95,9 +95,11 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC) {
return E->IgnoreImpCasts()->getType().getTypePtr()->isBooleanType();
});
if (hasBooleanOperands) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
return true;
}
- if (assignsToBoolean(BinOp, AC)) {
+ if (assignsToBoolean(BinOp, AC) || rootAssignsToBoolean.value_or(false)) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
return true;
}
}
@@ -231,28 +233,30 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
void BoolBitwiseOperationCheck::visitBinaryTreesNode(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
- const clang::SourceManager &SM, clang::ASTContext &Ctx) {
+ const clang::SourceManager &SM, clang::ASTContext &Ctx,
+ std::optional<bool>& rootAssignsToBoolean) {
if (!BinOp) {
return;
}
- if (isBooleanBitwise(BinOp, &Ctx)) {
+ if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean)) {
emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx);
}
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp,
- SM, Ctx);
+ SM, Ctx, rootAssignsToBoolean);
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp,
- SM, Ctx);
+ SM, Ctx, rootAssignsToBoolean);
}
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *binOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
- visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx);
+ std::optional<bool> rootAssignsToBoolean = std::nullopt;
+ visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx, rootAssignsToBoolean);
}
} // namespace clang::tidy::misc
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index e1939afe772a7..a04188027d3c2 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -39,7 +39,8 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
void visitBinaryTreesNode(const BinaryOperator *BinOp,
const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM,
- clang::ASTContext &Ctx);
+ clang::ASTContext &Ctx,
+ std::optional<bool>& rootAssignsToBoolean);
private:
bool StrictMode;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index 6c3fd5ff0a140..364f23940b16e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -5,11 +5,13 @@
void general(unsigned flags, bool value) {
(flags << 1) | value;
flags = (flags << 1) | value;
+ flags = (flags << 1) | (flags << 2) | value;
+ flags = (flags << 1) | (flags << 2) | (flags << 4) | value;
}
-void take(bool value) {}
+// TODO: compound operators
-// TODO: (flags << 1) | (flags << 2) | value
+void take(bool value) {}
template<bool bb = true | 1>
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -39,6 +41,15 @@ void assign_to_boolean(unsigned flags, bool value) {
take((flags << 1) | value);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take((flags << 1) || value);
+ result = (flags << 1) | (flags << 2) | value;
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (flags << 1) || (flags << 2) || value;
+ result = (flags << 1) | (flags << 2) | (flags << 4) | value;
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (flags << 1) || (flags << 2) || (flags << 4) || value;
}
template<bool bb = (true | 1)>
@@ -69,6 +80,15 @@ void assign_to_boolean_parens(unsigned flags, bool value) {
take(((flags << 1) | value));
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(((flags << 1) || value));
+ result = ((flags << 1) | (flags << 2) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = ((flags << 1) || (flags << 2) || value);
+ result = ((flags << 1) | (flags << 2) | (flags << 4) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = ((flags << 1) || (flags << 2) || (flags << 4) || value);
}
template<bool bb = ((true | 1))>
@@ -99,6 +119,15 @@ void assign_to_boolean_parens2(unsigned flags, bool value) {
take((((flags << 1) | value)));
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take((((flags << 1) || value)));
+ result = (((flags << 1) | (flags << 2) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (((flags << 1) || (flags << 2) || value));
+ result = (((flags << 1) | (flags << 2) | (flags << 4) | value));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (((flags << 1) || (flags << 2) || (flags << 4) || value));
}
// functional cast
@@ -130,6 +159,15 @@ void assign_to_boolean_fcast(unsigned flags, bool value) {
take(bool((flags << 1) | value));
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(bool((flags << 1) || value));
+ result = bool((flags << 1) | (flags << 2) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = bool((flags << 1) || (flags << 2) || value);
+ result = bool((flags << 1) | (flags << 2) | (flags << 4) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:62: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = bool((flags << 1) || (flags << 2) || (flags << 4) || value);
}
// C-style cast
@@ -161,6 +199,15 @@ void assign_to_boolean_ccast(unsigned flags, bool value) {
take(bool((flags << 1) | value));
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(bool((flags << 1) || value));
+ result = (bool)((flags << 1) | (flags << 2) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (bool)((flags << 1) || (flags << 2) || value);
+ result = (bool)((flags << 1) | (flags << 2) | (flags << 4) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:64: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = (bool)((flags << 1) || (flags << 2) || (flags << 4) || value);
}
// static_cast
@@ -192,6 +239,15 @@ void assign_to_boolean_scast(unsigned flags, bool value) {
take(static_cast<bool>((flags << 1) | value));
// CHECK-MESSAGES: :[[@LINE-1]]:41: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(static_cast<bool>((flags << 1) || value));
+ result = static_cast<bool>((flags << 1) | (flags << 2) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = static_cast<bool>((flags << 1) || (flags << 2) || value);
+ result = static_cast<bool>((flags << 1) | (flags << 2) | (flags << 4) | value);
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:75: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result = static_cast<bool>((flags << 1) || (flags << 2) || (flags << 4) || value);
}
>From 52844e3cc54061a7c8733dd3cdaa18405633740f Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Fri, 7 Nov 2025 20:01:54 +0300
Subject: [PATCH 05/49] No parentheses for single stmt ifs
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index c89050bd70d5d..e0d412791f52c 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -39,17 +39,15 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
// Special handling for `template<bool bb=true|1>` cases
if (const auto *D = ParentNoParen->get<Decl>()) {
if (const auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- if (NTTPD->getType()->isBooleanType()) {
+ if (NTTPD->getType()->isBooleanType())
return true;
- }
}
}
if (const auto *S = ParentNoParen->get<Stmt>()) {
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(S)) {
- if (ICE->getType()->isBooleanType()) {
+ if (ICE->getType()->isBooleanType())
return true;
- }
}
}
}
@@ -79,9 +77,8 @@ constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
static llvm::StringRef translate(llvm::StringRef Value) {
for (const auto &[Bitwise, Logical] : OperatorsTransformation) {
- if (Value == Bitwise) {
+ if (Value == Bitwise)
return Logical;
- }
}
return {};
@@ -235,13 +232,11 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM, clang::ASTContext &Ctx,
std::optional<bool>& rootAssignsToBoolean) {
- if (!BinOp) {
+ if (!BinOp)
return;
- }
- if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean)) {
+ if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean))
emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx);
- }
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp,
>From d7ae3058c0e0a42c85dd5af8fff7a85b446830eb Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 01:37:32 +0300
Subject: [PATCH 06/49] Important todo
---
.../misc/bool-bitwise-operation-not-only-bool-operand.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index 364f23940b16e..56a3ba78f76ac 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -10,6 +10,7 @@ void general(unsigned flags, bool value) {
}
// TODO: compound operators
+// TODO: make sure parens dont spoil prior for compound operators
void take(bool value) {}
>From 793dc97ba640e3f70eb471db4fd2aa86450f61a8 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 14:28:42 +0300
Subject: [PATCH 07/49] Implement compound operator case with unsigned flags
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 9 +++++++++
...e-operation-not-only-bool-operand-compound.cpp | 15 +++++++++++++++
...ol-bitwise-operation-not-only-bool-operand.cpp | 4 ++--
3 files changed, 26 insertions(+), 2 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index e0d412791f52c..725a9ebd0bdd2 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -13,6 +13,8 @@
#include <optional>
#include <utility>
+// TODO: change warning message
+
using namespace clang::ast_matchers;
namespace clang::tidy::misc {
@@ -99,6 +101,10 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::o
rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
return true;
}
+ if (BinOp->isCompoundAssignmentOp() && BinOp->getLHS()->IgnoreImpCasts()->getType().getTypePtr()->isBooleanType()) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
+ return true;
+ }
}
}
return false;
@@ -232,6 +238,7 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM, clang::ASTContext &Ctx,
std::optional<bool>& rootAssignsToBoolean) {
+ //llvm::outs() << "ENTER " << rootAssignsToBoolean << "\n";
if (!BinOp)
return;
@@ -244,6 +251,8 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode(
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp,
SM, Ctx, rootAssignsToBoolean);
+
+ //llvm::outs() << "LEAVE\n";
}
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
new file mode 100644
index 0000000000000..48f630392b76c
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+void general(unsigned flags, bool value) {
+ flags |= value;
+}
+
+void assign_to_boolean(unsigned flags, bool value) {
+ value |= flags << 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean variable 'value' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: value = value || flags << 1;
+ value |= (flags << 1) | (flags << 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean variable 'value' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: value = value || (flags << 1) || (flags << 2);
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index 56a3ba78f76ac..7f447910ce406 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -1,6 +1,6 @@
// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
-// got from clang/lib/APINotes/APINotesWriter.cpp
+// The case is taken from the real code in clang/lib/APINotes/APINotesWriter.cpp
void general(unsigned flags, bool value) {
(flags << 1) | value;
@@ -9,8 +9,8 @@ void general(unsigned flags, bool value) {
flags = (flags << 1) | (flags << 2) | (flags << 4) | value;
}
-// TODO: compound operators
// TODO: make sure parens dont spoil prior for compound operators
+// TODO: r = value |= flags << 1; (when r boolean, value unsigned)
void take(bool value) {}
>From 6e523d8b2021132b857195c5cd44fab83f343d47 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 15:03:05 +0300
Subject: [PATCH 08/49] review from 5chmidti
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 725a9ebd0bdd2..6778e7d5ec317 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -41,14 +41,14 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
// Special handling for `template<bool bb=true|1>` cases
if (const auto *D = ParentNoParen->get<Decl>()) {
if (const auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- if (NTTPD->getType()->isBooleanType())
+ if (NTTPD->getType().getDesugaredType(*AC)->isBooleanType())
return true;
}
}
if (const auto *S = ParentNoParen->get<Stmt>()) {
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(S)) {
- if (ICE->getType()->isBooleanType())
+ if (ICE->getType().getDesugaredType(*AC)->isBooleanType())
return true;
}
}
@@ -90,8 +90,8 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::o
for (const auto &[Bitwise, _] : OperatorsTransformation) {
if (BinOp->getOpcodeStr() == Bitwise) {
const bool hasBooleanOperands = llvm::all_of(
- std::array{BinOp->getLHS(), BinOp->getRHS()}, [](const Expr *E) {
- return E->IgnoreImpCasts()->getType().getTypePtr()->isBooleanType();
+ std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
+ return E->IgnoreImpCasts()->getType().getDesugaredType(*AC)->isBooleanType();
});
if (hasBooleanOperands) {
rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
@@ -101,7 +101,7 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::o
rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
return true;
}
- if (BinOp->isCompoundAssignmentOp() && BinOp->getLHS()->IgnoreImpCasts()->getType().getTypePtr()->isBooleanType()) {
+ if (BinOp->isCompoundAssignmentOp() && BinOp->getLHS()->IgnoreImpCasts()->getType().getDesugaredType(*AC)->isBooleanType()) {
rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
return true;
}
@@ -144,8 +144,8 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
};
const bool HasVolatileOperand = llvm::any_of(
- std::array{BinOp->getLHS(), BinOp->getRHS()}, [](const Expr *E) {
- return E->IgnoreImpCasts()->getType().isVolatileQualified();
+ std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
+ return E->IgnoreImpCasts()->getType().getDesugaredType(Ctx).isVolatileQualified();
});
if (HasVolatileOperand)
return static_cast<void>(DiagEmitter());
>From 352d11840dc652bd1ac6178fd1e2e93cdada8dee Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 19:20:58 +0300
Subject: [PATCH 09/49] Restore old unit-tests
---
.../misc/BoolBitwiseOperationCheck.cpp | 25 ++++++--
.../bool-bitwise-operation-nontraditional.cpp | 56 +++++++++---------
...eration-not-only-bool-operand-compound.cpp | 5 ++
...itwise-operation-not-only-bool-operand.cpp | 3 -
.../checkers/misc/bool-bitwise-operation.cpp | 57 +++++++++----------
5 files changed, 78 insertions(+), 68 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 6778e7d5ec317..204d650b4a552 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -87,13 +87,22 @@ static llvm::StringRef translate(llvm::StringRef Value) {
}
static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::optional<bool>& rootAssignsToBoolean) {
+ if (!BinOp)
+ return false;
+
for (const auto &[Bitwise, _] : OperatorsTransformation) {
if (BinOp->getOpcodeStr() == Bitwise) {
- const bool hasBooleanOperands = llvm::all_of(
- std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
- return E->IgnoreImpCasts()->getType().getDesugaredType(*AC)->isBooleanType();
- });
- if (hasBooleanOperands) {
+ const bool lhsBoolean = BinOp->getLHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ const bool rhsBoolean = BinOp->getRHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ if (lhsBoolean && rhsBoolean) {
rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
return true;
}
@@ -101,10 +110,14 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::o
rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
return true;
}
- if (BinOp->isCompoundAssignmentOp() && BinOp->getLHS()->IgnoreImpCasts()->getType().getDesugaredType(*AC)->isBooleanType()) {
+ if (BinOp->isCompoundAssignmentOp() && lhsBoolean) {
rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
return true;
}
+ if (std::optional<bool> DummyFlag = false; (lhsBoolean || isBooleanBitwise(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), AC, DummyFlag)) && (rhsBoolean || isBooleanBitwise(dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), AC, DummyFlag))) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
+ return true;
+ }
}
}
return false;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 4b50072849919..14b8dcf1ac0ce 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -126,7 +126,6 @@ void bad_side_effects_volatile() {
bool a = true;
volatile bool b = false;
bool c = true;
- bool r;
a bitor b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -142,15 +141,15 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
- r = (a bitor c) bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (a or c) bitor b;
+ (a bitor c) bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (a or c) bitor b;
- r = a bitor c bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = a or c bitor b;
+ a bitor c bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or c bitor b;
}
void bad_with_priors() {
@@ -186,20 +185,20 @@ void bad_with_priors2() {
// CHECK-FIXES: a xor (b and c);
// braces added in the first change
- r = a bitor b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = a or (b and c);
+ a bitor b bitand c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or (b and c);
- r = b bitand c xor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (b and c) xor a;
+ b bitand c xor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) xor a;
// braces added in the first change
- r = b bitand c bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (b and c) or a;
+ b bitand c bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) or a;
}
template<typename T>
@@ -224,7 +223,6 @@ void bad_has_ancestor() {
void bad_with_priors_already_braced() {
bool a = false, b = true, c = true;
- bool r;
a and (b bitor c);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and (b or c);
@@ -242,19 +240,19 @@ void bad_with_priors_already_braced() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor (b and c);
- r = a bitor (b bitand c);
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:20: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = a or (b and c);
+ a bitor (b bitand c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or (b and c);
(b bitand c) xor a;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b and c) xor a;
- r = (b bitand c) bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (b and c) or a;
+ (b bitand c) bitor a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b and c) or a;
}
void bad_with_priors_compound() {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
index 48f630392b76c..ec9f536afe0a8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
@@ -2,6 +2,11 @@
void general(unsigned flags, bool value) {
flags |= value;
+
+ unsigned mask = 0b1100;
+ bool result = flags &= mask;
+ auto result2 = flags &= mask;
+ result = flags |= flags << 1;
}
void assign_to_boolean(unsigned flags, bool value) {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index 7f447910ce406..603d49c7b24e6 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -9,9 +9,6 @@ void general(unsigned flags, bool value) {
flags = (flags << 1) | (flags << 2) | (flags << 4) | value;
}
-// TODO: make sure parens dont spoil prior for compound operators
-// TODO: r = value |= flags << 1; (when r boolean, value unsigned)
-
void take(bool value) {}
template<bool bb = true | 1>
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 56ca15b8d6729..2cc725cb8781f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -126,7 +126,6 @@ void bad_side_effects_volatile() {
bool a = true;
volatile bool b = false;
bool c = true;
- bool r;
a | b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -142,15 +141,15 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
- r = (a | c) | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (a || c) | b;
+ (a | c) | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (a || c) | b;
- r = a | c | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = a || c | b;
+ a | c | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || c | b;
}
void bad_with_priors() {
@@ -180,25 +179,24 @@ void bad_with_priors() {
void bad_with_priors2() {
bool a = false, b = true, c = true;
- bool r;
a ^ b & c;
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ (b && c);
// braces added in the first change
- r = a | b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = a || (b && c);
+ a | b & c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || (b && c);
- r = b & c ^ a;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (b && c) ^ a;
+ b & c ^ a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) ^ a;
// braces added in the first change
- r = b & c | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (b && c) || a;
+ b & c | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) || a;
}
template<typename T>
@@ -223,7 +221,6 @@ void bad_has_ancestor() {
void bad_with_priors_already_braced() {
bool a = false, b = true, c = true;
- bool r;
a && (b | c);
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && (b || c);
@@ -241,19 +238,19 @@ void bad_with_priors_already_braced() {
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ (b && c);
- r = a | (b & c);
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = a || (b && c);
+ a | (b & c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || (b && c);
(b & c) ^ a;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b && c) ^ a;
- r = (b & c) | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-FIXES: r = (b && c) || a;
+ (b & c) | a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (b && c) || a;
}
void bad_with_priors_compound() {
>From 0d4aa3bb269a9ece5c44a531b15c5887c06476c4 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 19:51:01 +0300
Subject: [PATCH 10/49] Refactor && Change warning mesage
---
.../misc/BoolBitwiseOperationCheck.cpp | 77 ++++----
...-operation-change-possible-side-effect.cpp | 8 +-
.../bool-bitwise-operation-ignore-macros.cpp | 10 +-
.../bool-bitwise-operation-nontraditional.cpp | 122 ++++++-------
...eration-not-only-bool-operand-compound.cpp | 2 +-
...itwise-operation-not-only-bool-operand.cpp | 168 +++++++++---------
.../checkers/misc/bool-bitwise-operation.c | 4 +-
.../checkers/misc/bool-bitwise-operation.cpp | 122 ++++++-------
8 files changed, 261 insertions(+), 252 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 204d650b4a552..a37935ea3a0d0 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -13,8 +13,6 @@
#include <optional>
#include <utility>
-// TODO: change warning message
-
using namespace clang::ast_matchers;
namespace clang::tidy::misc {
@@ -86,37 +84,48 @@ static llvm::StringRef translate(llvm::StringRef Value) {
return {};
}
-static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, std::optional<bool>& rootAssignsToBoolean) {
+static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
+ std::optional<bool> &rootAssignsToBoolean) {
if (!BinOp)
return false;
for (const auto &[Bitwise, _] : OperatorsTransformation) {
if (BinOp->getOpcodeStr() == Bitwise) {
- const bool lhsBoolean = BinOp->getLHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
- const bool rhsBoolean = BinOp->getRHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
- if (lhsBoolean && rhsBoolean) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
- return true;
- }
- if (assignsToBoolean(BinOp, AC) || rootAssignsToBoolean.value_or(false)) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
- return true;
- }
- if (BinOp->isCompoundAssignmentOp() && lhsBoolean) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
- return true;
- }
- if (std::optional<bool> DummyFlag = false; (lhsBoolean || isBooleanBitwise(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), AC, DummyFlag)) && (rhsBoolean || isBooleanBitwise(dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), AC, DummyFlag))) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
- return true;
+ bool lhsBoolean = BinOp->getLHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ bool rhsBoolean = BinOp->getRHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ for (int i = 0; i < 2; ++i) {
+ if (lhsBoolean && rhsBoolean) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
+ return true;
+ }
+ if (assignsToBoolean(BinOp, AC) ||
+ rootAssignsToBoolean.value_or(false)) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
+ return true;
+ }
+ if (BinOp->isCompoundAssignmentOp() && lhsBoolean) {
+ rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
+ return true;
+ }
+ std::optional<bool> DummyFlag = false;
+ lhsBoolean =
+ lhsBoolean ||
+ isBooleanBitwise(dyn_cast<BinaryOperator>(
+ BinOp->getLHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+ rhsBoolean =
+ rhsBoolean ||
+ isBooleanBitwise(dyn_cast<BinaryOperator>(
+ BinOp->getRHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
}
}
}
@@ -151,14 +160,17 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign(BinOp);
return diag(BinOp->getOperatorLoc(),
"use logical operator '%0' for boolean %select{variable "
- "%2|values}1 instead of bitwise operator '%3'")
+ "%2|semantics}1 instead of bitwise operator '%3'")
<< translate(BinOp->getOpcodeStr()) << (ND == nullptr) << ND
<< BinOp->getOpcodeStr();
};
const bool HasVolatileOperand = llvm::any_of(
std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
- return E->IgnoreImpCasts()->getType().getDesugaredType(Ctx).isVolatileQualified();
+ return E->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(Ctx)
+ .isVolatileQualified();
});
if (HasVolatileOperand)
return static_cast<void>(DiagEmitter());
@@ -250,8 +262,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
void BoolBitwiseOperationCheck::visitBinaryTreesNode(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM, clang::ASTContext &Ctx,
- std::optional<bool>& rootAssignsToBoolean) {
- //llvm::outs() << "ENTER " << rootAssignsToBoolean << "\n";
+ std::optional<bool> &rootAssignsToBoolean) {
if (!BinOp)
return;
@@ -264,8 +275,6 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode(
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp,
SM, Ctx, rootAssignsToBoolean);
-
- //llvm::outs() << "LEAVE\n";
}
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
index a92d32f55701f..d58f3ecd836fd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
@@ -8,11 +8,11 @@ void bad_possible_side_effects() {
bool a = true, b = false;
a | function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || function_with_possible_side_effects();
a & function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && function_with_possible_side_effects();
a |= function_with_possible_side_effects();
@@ -47,11 +47,11 @@ void bad_definitely_side_effects() {
int acc = 0;
a | (acc++, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a & (acc++, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= (acc++, b);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
index 5b879063bae6b..43faddcc3beea 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
@@ -16,13 +16,13 @@ void bad_in_macro() {
// change operator - GOOD
IDENT(a) | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a) || b;
a & IDENT(b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && IDENT(b);
IDENT(a) & IDENT(b);
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a) && IDENT(b);
// insert `)` - BAD
@@ -31,7 +31,7 @@ void bad_in_macro() {
// insert `)` - GOOD
a && b | c IDENT(&& e);
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && (b || c) IDENT(&& e);
// insert `(` - BAD
@@ -39,7 +39,7 @@ void bad_in_macro() {
// insert `(` - GOOD
IDENT(a &&) b | c && e;
- // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a &&) (b || c) && e;
bool ab = false;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 14b8dcf1ac0ce..314f2087dcf3a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -15,10 +15,10 @@ bool& normal() {
bool bad() noexcept __attribute__((pure)) {
bool a = true, b = false;
a bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or b;
a bitand b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and b;
a or_eq b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -31,10 +31,10 @@ bool bad() noexcept __attribute__((pure)) {
}
bool global_1 = bad() bitor bad();
-// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool global_1 = bad() or bad();
bool global_2 = bad() bitand bad();
-// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool global_2 = bad() and bad();
using Boolean = bool;
@@ -42,10 +42,10 @@ using Boolean = bool;
bool bad_typedef() {
Boolean a = true, b = false;
a bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or b;
a bitand b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and b;
a or_eq b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -62,19 +62,19 @@ void bad_side_effects() {
bool a = true, b = false;
a bitor function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a bitand function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
function_with_possible_side_effects() bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() or a;
function_with_possible_side_effects() bitand a;
- // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() and a;
a or_eq function_with_possible_side_effects();
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -88,19 +88,19 @@ void bad_side_effects() {
bool c = true;
a or function_with_possible_side_effects() bitor c;
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or function_with_possible_side_effects() or c;
function_with_possible_side_effects() or b bitor c;
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() or b or c;
a and function_with_possible_side_effects() bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and function_with_possible_side_effects() and c;
function_with_possible_side_effects() and b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() and b and c;
// but here the count of evaluation migh be changed - no fix must be provided
@@ -128,10 +128,10 @@ void bad_side_effects_volatile() {
bool c = true;
a bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a bitand b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a or_eq b;
@@ -142,38 +142,38 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
(a bitor c) bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (a or c) bitor b;
a bitor c bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or c bitor b;
}
void bad_with_priors() {
bool a = false, b = true, c = true;
a and b bitor c;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and (b or c);
a and b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and b and c;
a or b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or b and c;
a or b bitor c;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or b or c;
b bitor c and a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b or c) and a;
bool q = (true and false bitor true) and (false bitor true and (false and true bitor false));
- // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:53: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:84: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:53: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:84: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool q = (true and (false or true)) and ((false or true) and (false and (true or false)));
}
@@ -181,23 +181,23 @@ void bad_with_priors2() {
bool a = false, b = true, c = true;
bool r;
a xor b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor (b and c);
// braces added in the first change
a bitor b bitand c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or (b and c);
b bitand c xor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b and c) xor a;
// braces added in the first change
b bitand c bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b and c) or a;
}
@@ -209,49 +209,49 @@ void bad_has_ancestor() {
bool a = false, b = true, c = true;
bool d = false;
d xor (a and b bitand c);
- // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: d xor (a and b and c);
a xor ident(b bitand c or a);
- // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor ident(b and c or a);
a bitor ident(a ? b bitand c : c);
- // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a bitor ident(a ? b and c : c);
}
void bad_with_priors_already_braced() {
bool a = false, b = true, c = true;
a and (b bitor c);
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and (b or c);
(b bitor c) and a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b or c) and a;
bool q = (true and (false bitor true)) and ((false bitor true) and (false and (true bitor false)));
- // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:56: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:89: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:56: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:89: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool q = (true and (false or true)) and ((false or true) and (false and (true or false)));
a xor (b bitand c);
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor (b and c);
a bitor (b bitand c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a or (b and c);
(b bitand c) xor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b and c) xor a;
(b bitand c) bitor a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b and c) or a;
}
@@ -281,10 +281,10 @@ void bad_with_priors_compound_already_braced() {
void bad_no_fixit() {
bool b = false;
normal() or_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
normal() and_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
@@ -302,10 +302,10 @@ void bad_in_macro() {
// change operator - BAD
IDENT(a bitor) b;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a IDENT(bitand b);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
IDENT(a or_eq) b;
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -316,34 +316,34 @@ void bad_in_macro() {
// change operator - GOOD
IDENT(a) bitor b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a) or b;
a bitand IDENT(b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and IDENT(b);
IDENT(a) bitand IDENT(b);
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a) and IDENT(b);
// insert `)` - BAD
bool c = true, e = false;
a and b bitor IDENT(c and) e;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// insert `)` - GOOD
a and b bitor c IDENT(and e);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and (b or c) IDENT(and e);
// insert `(` - BAD
a IDENT(and b) bitor c and e;
- // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// insert `(` - GOOD
IDENT(a and) b bitor c and e;
- // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a and) (b or c) and e;
bool ab = false;
@@ -364,9 +364,9 @@ void bad_in_macro_fixit() {
// FIXME: implement fixit for all of these cases
a MY_OR b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
a MY_AND b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
a MY_OR_ASSIGN b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
a MY_AND_ASSIGN b;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
index ec9f536afe0a8..2369da53d26ef 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
@@ -15,6 +15,6 @@ void assign_to_boolean(unsigned flags, bool value) {
// CHECK-FIXES: value = value || flags << 1;
value |= (flags << 1) | (flags << 2);
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean variable 'value' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: value = value || (flags << 1) || (flags << 2);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index 603d49c7b24e6..e0cd992fa78a4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -12,239 +12,239 @@ void general(unsigned flags, bool value) {
void take(bool value) {}
template<bool bb = true | 1>
-// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: template<bool bb = true || 1>
void assign_to_boolean(unsigned flags, bool value) {
struct A { bool a = true | 1; };
- // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct A { bool a = true || 1; };
struct B { union { bool a = true | 1; }; };
- // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct B { union { bool a = true || 1; }; };
bool result = (flags << 1) | value;
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool result = (flags << 1) || value;
bool a = (flags << 2) | value,
- // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool a = (flags << 2) || value,
b = (flags << 4) | value,
- // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = (flags << 4) || value,
c = (flags << 8) | value;
- // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: c = (flags << 8) || value;
result = (flags << 1) | value;
- // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (flags << 1) || value;
take((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take((flags << 1) || value);
result = (flags << 1) | (flags << 2) | value;
- // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (flags << 1) || (flags << 2) || value;
result = (flags << 1) | (flags << 2) | (flags << 4) | value;
- // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (flags << 1) || (flags << 2) || (flags << 4) || value;
}
template<bool bb = (true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: template<bool bb = (true || 1)>
void assign_to_boolean_parens(unsigned flags, bool value) {
struct A { bool a = (true | 1); };
- // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct A { bool a = (true || 1); };
struct B { union { bool a = (true | 1); }; };
- // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct B { union { bool a = (true || 1); }; };
bool result = ((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool result = ((flags << 1) || value);
bool a = ((flags << 2) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool a = ((flags << 2) || value),
b = ((flags << 4) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = ((flags << 4) || value),
c = ((flags << 8) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: c = ((flags << 8) || value);
result = ((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = ((flags << 1) || value);
take(((flags << 1) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(((flags << 1) || value));
result = ((flags << 1) | (flags << 2) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = ((flags << 1) || (flags << 2) || value);
result = ((flags << 1) | (flags << 2) | (flags << 4) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = ((flags << 1) || (flags << 2) || (flags << 4) || value);
}
template<bool bb = ((true | 1))>
-// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: template<bool bb = ((true || 1))>
void assign_to_boolean_parens2(unsigned flags, bool value) {
struct A { bool a = ((true | 1)); };
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct A { bool a = ((true || 1)); };
struct B { union { bool a = ((true | 1)); }; };
- // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct B { union { bool a = ((true || 1)); }; };
bool result = (((flags << 1) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool result = (((flags << 1) || value));
bool a = (((flags << 2) | value)),
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool a = (((flags << 2) || value)),
b = (((flags << 4) | value)),
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = (((flags << 4) || value)),
c = (((flags << 8) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: c = (((flags << 8) || value));
result = (((flags << 1) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (((flags << 1) || value));
take((((flags << 1) | value)));
- // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take((((flags << 1) || value)));
result = (((flags << 1) | (flags << 2) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (((flags << 1) || (flags << 2) || value));
result = (((flags << 1) | (flags << 2) | (flags << 4) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (((flags << 1) || (flags << 2) || (flags << 4) || value));
}
// functional cast
template<bool bb = bool(true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: template<bool bb = bool(true || 1)>
void assign_to_boolean_fcast(unsigned flags, bool value) {
struct A { bool a = bool(true | 1); };
- // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct A { bool a = bool(true || 1); };
struct B { union { bool a = bool(true | 1); }; };
- // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct B { union { bool a = bool(true || 1); }; };
bool result = bool((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool result = bool((flags << 1) || value);
bool a = bool((flags << 2) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool a = bool((flags << 2) || value),
b = bool((flags << 4) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = bool((flags << 4) || value),
c = bool((flags << 8) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: c = bool((flags << 8) || value);
result = bool((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = bool((flags << 1) || value);
take(bool((flags << 1) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(bool((flags << 1) || value));
result = bool((flags << 1) | (flags << 2) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = bool((flags << 1) || (flags << 2) || value);
result = bool((flags << 1) | (flags << 2) | (flags << 4) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:62: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:62: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = bool((flags << 1) || (flags << 2) || (flags << 4) || value);
}
// C-style cast
template<bool bb = (bool)(true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: template<bool bb = (bool)(true || 1)>
void assign_to_boolean_ccast(unsigned flags, bool value) {
struct A { bool a = (bool)(true | 1); };
- // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct A { bool a = (bool)(true || 1); };
struct B { union { bool a = (bool)(true | 1); }; };
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct B { union { bool a = (bool)(true || 1); }; };
bool result = (bool)((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool result = (bool)((flags << 1) || value);
bool a = (bool)((flags << 2) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool a = (bool)((flags << 2) || value),
b = (bool)((flags << 4) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = (bool)((flags << 4) || value),
c = (bool)((flags << 8) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: c = (bool)((flags << 8) || value);
result = (bool)((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (bool)((flags << 1) || value);
take(bool((flags << 1) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(bool((flags << 1) || value));
result = (bool)((flags << 1) | (flags << 2) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (bool)((flags << 1) || (flags << 2) || value);
result = (bool)((flags << 1) | (flags << 2) | (flags << 4) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:64: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:64: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (bool)((flags << 1) || (flags << 2) || (flags << 4) || value);
}
// static_cast
template<bool bb = static_cast<bool>(true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: template<bool bb = static_cast<bool>(true || 1)>
void assign_to_boolean_scast(unsigned flags, bool value) {
struct A { bool a = static_cast<bool>(true | 1); };
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct A { bool a = static_cast<bool>(true || 1); };
struct B { union { bool a = static_cast<bool>(true | 1); }; };
- // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: struct B { union { bool a = static_cast<bool>(true || 1); }; };
bool result = static_cast<bool>((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool result = static_cast<bool>((flags << 1) || value);
bool a = static_cast<bool>((flags << 2) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool a = static_cast<bool>((flags << 2) || value),
b = static_cast<bool>((flags << 4) | value),
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = static_cast<bool>((flags << 4) || value),
c = static_cast<bool>((flags << 8) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: c = static_cast<bool>((flags << 8) || value);
result = static_cast<bool>((flags << 1) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = static_cast<bool>((flags << 1) || value);
take(static_cast<bool>((flags << 1) | value));
- // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: take(static_cast<bool>((flags << 1) || value));
result = static_cast<bool>((flags << 1) | (flags << 2) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = static_cast<bool>((flags << 1) || (flags << 2) || value);
result = static_cast<bool>((flags << 1) | (flags << 2) | (flags << 4) | value);
- // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:75: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:75: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = static_cast<bool>((flags << 1) || (flags << 2) || (flags << 4) || value);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
index 777189f12bbd3..04c831ab63dd0 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
@@ -12,10 +12,10 @@ void normal() {
void bad() {
_Bool a = 1, b = 0;
a | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || b;
a & b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b;
a |= b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 2cc725cb8781f..5c2eb5d065514 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -15,10 +15,10 @@ bool& normal() {
bool bad() noexcept __attribute__((pure)) {
bool a = true, b = false;
a | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || b;
a & b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b;
a |= b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -31,10 +31,10 @@ bool bad() noexcept __attribute__((pure)) {
}
bool global_1 = bad() | bad();
-// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool global_1 = bad() || bad();
bool global_2 = bad() & bad();
-// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool global_2 = bad() && bad();
using Boolean = bool;
@@ -42,10 +42,10 @@ using Boolean = bool;
bool bad_typedef() {
Boolean a = true, b = false;
a | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || b;
a & b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b;
a |= b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -62,19 +62,19 @@ void bad_side_effects() {
bool a = true, b = false;
a | function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a & function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
function_with_possible_side_effects() | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() || a;
function_with_possible_side_effects() & a;
- // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() && a;
a |= function_with_possible_side_effects();
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -88,19 +88,19 @@ void bad_side_effects() {
bool c = true;
a || function_with_possible_side_effects() | c;
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || function_with_possible_side_effects() || c;
function_with_possible_side_effects() || b | c;
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() || b || c;
a && function_with_possible_side_effects() & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && function_with_possible_side_effects() && c;
function_with_possible_side_effects() && b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() && b && c;
// but here the count of evaluation migh be changed - no fix must be provided
@@ -128,10 +128,10 @@ void bad_side_effects_volatile() {
bool c = true;
a | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a & b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= b;
@@ -142,60 +142,60 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
(a | c) | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (a || c) | b;
a | c | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || c | b;
}
void bad_with_priors() {
bool a = false, b = true, c = true;
a && b | c;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && (b || c);
a && b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b && c;
a || b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || b && c;
a || b | c;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || b || c;
b | c && a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b || c) && a;
bool q = (true && false | true) && (false | true && (false && true | false));
- // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:72: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:72: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool q = (true && (false || true)) && ((false || true) && (false && (true || false)));
}
void bad_with_priors2() {
bool a = false, b = true, c = true;
a ^ b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ (b && c);
// braces added in the first change
a | b & c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || (b && c);
b & c ^ a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b && c) ^ a;
// braces added in the first change
b & c | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b && c) || a;
}
@@ -207,49 +207,49 @@ void bad_has_ancestor() {
bool a = false, b = true, c = true;
bool d = false;
d ^ (a && b & c);
- // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: d ^ (a && b && c);
a ^ ident(b & c || a);
- // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ ident(b && c || a);
a | ident(a ? b & c : c);
- // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a | ident(a ? b && c : c);
}
void bad_with_priors_already_braced() {
bool a = false, b = true, c = true;
a && (b | c);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && (b || c);
(b | c) && a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b || c) && a;
bool q = (true && (false | true)) && ((false | true) && (false && (true | false)));
- // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:50: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-3]]:77: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:50: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:77: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: bool q = (true && (false || true)) && ((false || true) && (false && (true || false)));
a ^ (b & c);
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a ^ (b && c);
a | (b & c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a || (b && c);
(b & c) ^ a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b && c) ^ a;
(b & c) | a;
- // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
- // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: (b && c) || a;
}
@@ -279,10 +279,10 @@ void bad_with_priors_compound_already_braced() {
void bad_no_fixit() {
bool b = false;
normal() |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
normal() &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
@@ -300,10 +300,10 @@ void bad_in_macro() {
// change operator - BAD
IDENT(a |) b;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a IDENT(& b);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
IDENT(a |=) b;
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
@@ -314,34 +314,34 @@ void bad_in_macro() {
// change operator - GOOD
IDENT(a) | b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a) || b;
a & IDENT(b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && IDENT(b);
IDENT(a) & IDENT(b);
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a) && IDENT(b);
// insert `)` - BAD
bool c = true, e = false;
a && b | IDENT(c &&) e;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// insert `)` - GOOD
a && b | c IDENT(&& e);
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && (b || c) IDENT(&& e);
// insert `(` - BAD
a IDENT(&& b) | c && e;
- // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// insert `(` - GOOD
IDENT(a &&) b | c && e;
- // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: IDENT(a &&) (b || c) && e;
bool ab = false;
@@ -362,9 +362,9 @@ void bad_in_macro_fixit() {
// FIXME: implement fixit for all of these cases
a MY_OR b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
a MY_AND b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean values instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
a MY_OR_ASSIGN b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
a MY_AND_ASSIGN b;
>From dfa7ce4d2b8a1f44188836b8c312ba4f0a68f234 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 21:37:57 +0300
Subject: [PATCH 11/49] Implement handling of members
---
.../misc/BoolBitwiseOperationCheck.cpp | 38 +++--
.../bool-bitwise-operation-static-members.cpp | 35 +++++
.../bool-bitwise-operation-struct-members.cpp | 143 ++++++++++++++++++
3 files changed, 204 insertions(+), 12 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index a37935ea3a0d0..65e936e054b72 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -58,9 +58,10 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
static const NamedDecl *
getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
if (BO->isCompoundAssignmentOp()) {
- const auto *DeclRefLHS =
- dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreImpCasts());
- return DeclRefLHS ? DeclRefLHS->getDecl() : nullptr;
+ if (const auto *DeclRefLHS = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreImpCasts()))
+ return DeclRefLHS->getDecl();
+ else if (const auto *MemberLHS = dyn_cast<MemberExpr>(BO->getLHS()->IgnoreImpCasts()))
+ return MemberLHS->getMemberDecl();
}
return nullptr;
}
@@ -132,6 +133,17 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
return false;
}
+static const Expr* getValidCompoundsLHS(const BinaryOperator* BinOp) {
+ assert(BinOp->isCompoundAssignmentOp());
+
+ if (const auto *DeclRefLHS = dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts()))
+ return DeclRefLHS;
+ else if (const auto *MemberLHS = dyn_cast<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts()))
+ return MemberLHS;
+
+ return nullptr;
+}
+
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
@@ -159,9 +171,8 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
auto DiagEmitter = [BinOp, this] {
const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign(BinOp);
return diag(BinOp->getOperatorLoc(),
- "use logical operator '%0' for boolean %select{variable "
- "%2|semantics}1 instead of bitwise operator '%3'")
- << translate(BinOp->getOpcodeStr()) << (ND == nullptr) << ND
+ "use logical operator '%0' for boolean %select{%select{member|variable}2 %3|semantics}1 instead of bitwise operator '%4'")
+ << translate(BinOp->getOpcodeStr()) << (ND == nullptr) << (!isa<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts())) << ND
<< BinOp->getOpcodeStr();
};
@@ -201,19 +212,22 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
FixItHint InsertEqual;
if (BinOp->isCompoundAssignmentOp()) {
- const auto *DeclRefLHS =
- dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts());
- if (!DeclRefLHS)
+ const auto *LHS = getValidCompoundsLHS(BinOp);
+ if (!LHS)
return static_cast<void>(DiagEmitter());
- const SourceLocation LocLHS = DeclRefLHS->getEndLoc();
+ const SourceLocation LocLHS = LHS->getEndLoc();
if (LocLHS.isInvalid() || LocLHS.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
const SourceLocation InsertLoc =
clang::Lexer::getLocForEndOfToken(LocLHS, 0, SM, Ctx.getLangOpts());
if (InsertLoc.isInvalid() || InsertLoc.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
- InsertEqual = FixItHint::CreateInsertion(
- InsertLoc, " = " + DeclRefLHS->getDecl()->getNameAsString());
+ auto SourceText = static_cast<std::string>(Lexer::getSourceText(
+ CharSourceRange::getTokenRange(LHS->getSourceRange()),
+ SM, Ctx.getLangOpts()
+ ));
+ llvm::erase_if(SourceText, [](unsigned char ch) { return std::isspace(ch); });
+ InsertEqual = FixItHint::CreateInsertion(InsertLoc, " = " + SourceText);
}
auto ReplaceOperator = FixItHint::CreateReplacement(TokenRange, FixSpelling);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp
new file mode 100644
index 0000000000000..1ba4108c4c9c6
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+struct A {
+ static int first;
+ static bool second;
+};
+
+int A::first = 100;
+bool A::second = false;
+
+void normal() {
+ int b = 200;
+
+ A::first | b;
+ A::first & b;
+ A::first |= b;
+ A::first &= b;
+}
+
+void bad() {
+ bool b = false;
+
+ A::second | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: A::second || b;
+ A::second & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: A::second && b;
+ A::second |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '||' for boolean variable 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: A::second = A::second || b;
+ A::second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean variable 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: A::second = A::second && b;
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp
new file mode 100644
index 0000000000000..cc0fee5fd54a7
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp
@@ -0,0 +1,143 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+struct A {
+ int first;
+ bool second;
+};
+
+void normal() {
+ A a {100, false};
+ int b = 200;
+
+ a.first | b;
+ a.first & b;
+ a.first |= b;
+ a.first &= b;
+}
+
+void bad() {
+ A a {-1, true};
+ bool b = false;
+
+ a.second | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a.second || b;
+ a.second & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a.second && b;
+ a.second |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a.second = a.second || b;
+ a.second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a.second = a.second && b;
+}
+
+void bad_two_lines() {
+ A a {-1, true};
+ bool b = false;
+
+ a.
+ second | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: second || b;
+ a.
+ second & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: second && b;
+ a.
+ second |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: second = a.second || b;
+ a
+ .
+ second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: second = a.second && b;
+ a
+ .second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: .second = a.second && b;
+}
+
+void bad_side_effects_volatile() {
+ volatile A a {-1, true};
+ bool b = false;
+
+ a.second | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a.second & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a.second |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a.second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+struct VolatileA {
+ volatile bool second;
+};
+
+void bad_side_effects_volatile2() {
+ VolatileA a {true};
+ bool b = false;
+
+ a.second | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a.second & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a.second |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a.second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
+void bad_arrow() {
+ A a {-1, true};
+ auto* pa = &a;
+ bool b = false;
+
+ pa->second | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: pa->second || b;
+ pa->second & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: pa->second && b;
+ pa->second |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: pa->second = pa->second || b;
+ pa->second &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: pa->second = pa->second && b;
+}
+
+struct B {
+ bool& access();
+};
+
+void bad_no_fixit() {
+ B b;
+ bool c = false;
+ b.access() |= c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ b.access() &= c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ auto* pb = &b;
+ pb->access() |= c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ pb->access() &= c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
>From cb9d520d86d8c707c87e308c2fcc7b65aebe408b Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 21:46:08 +0300
Subject: [PATCH 12/49] Simplify the warning message
---
.../misc/BoolBitwiseOperationCheck.cpp | 16 +------
.../checks/misc/bool-bitwise-operation.rst | 6 +--
...-operation-change-possible-side-effect.cpp | 24 +++++-----
.../bool-bitwise-operation-ignore-macros.cpp | 2 +-
.../bool-bitwise-operation-nontraditional.cpp | 48 +++++++++----------
...eration-not-only-bool-operand-compound.cpp | 4 +-
.../bool-bitwise-operation-static-members.cpp | 4 +-
.../bool-bitwise-operation-struct-members.cpp | 22 ++++-----
.../checkers/misc/bool-bitwise-operation.c | 4 +-
.../checkers/misc/bool-bitwise-operation.cpp | 48 +++++++++----------
10 files changed, 83 insertions(+), 95 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 65e936e054b72..402f6baac5e57 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -55,17 +55,6 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
return false;
}
-static const NamedDecl *
-getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) {
- if (BO->isCompoundAssignmentOp()) {
- if (const auto *DeclRefLHS = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreImpCasts()))
- return DeclRefLHS->getDecl();
- else if (const auto *MemberLHS = dyn_cast<MemberExpr>(BO->getLHS()->IgnoreImpCasts()))
- return MemberLHS->getMemberDecl();
- }
- return nullptr;
-}
-
constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
OperatorsTransformation{{{"|", "||"},
{"|=", "||"},
@@ -169,10 +158,9 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM, clang::ASTContext &Ctx) {
auto DiagEmitter = [BinOp, this] {
- const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign(BinOp);
return diag(BinOp->getOperatorLoc(),
- "use logical operator '%0' for boolean %select{%select{member|variable}2 %3|semantics}1 instead of bitwise operator '%4'")
- << translate(BinOp->getOpcodeStr()) << (ND == nullptr) << (!isa<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts())) << ND
+ "use logical operator '%0' for boolean semantics instead of bitwise operator '%1'")
+ << translate(BinOp->getOpcodeStr())
<< BinOp->getOpcodeStr();
};
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
index 3682a74a5119d..e70ac82779644 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -13,9 +13,9 @@ to implicit integer conversions and missed short-circuit evaluation.
.. code-block:: c++
bool invalid = false;
- invalid |= x > limit.x; // warning: use logical operator '||' for boolean variable 'invalid' instead of bitwise operator '|='
- invalid |= y > limit.y; // warning: use logical operator '||' for boolean variable 'invalid' instead of bitwise operator '|='
- invalid |= z > limit.z; // warning: use logical operator '||' for boolean variable 'invalid' instead of bitwise operator '|='
+ invalid |= x > limit.x; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
+ invalid |= y > limit.y; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
+ invalid |= z > limit.z; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
if (invalid) {
// error handling
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
index d58f3ecd836fd..a51220be391bc 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
@@ -16,29 +16,29 @@ void bad_possible_side_effects() {
// CHECK-FIXES: a && function_with_possible_side_effects();
a |= function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || function_with_possible_side_effects();
a &= function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && function_with_possible_side_effects();
bool c = true;
a &= function_with_possible_side_effects() && c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && function_with_possible_side_effects() && c;
a &= b && function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && b && function_with_possible_side_effects();
a |= function_with_possible_side_effects() || c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || function_with_possible_side_effects() || c;
a |= b || function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || b || function_with_possible_side_effects();
}
@@ -55,28 +55,28 @@ void bad_definitely_side_effects() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= (acc++, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a &= (acc++, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
bool c = true;
a &= (acc++, b) && c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a &= b && (acc++, c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= (acc++, b) || c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= b || (acc++, c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
index 43faddcc3beea..d2b742cf207d1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
@@ -48,6 +48,6 @@ void bad_in_macro() {
// insert ` = a`- GOOD
b &= CAT(a, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'b' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = b && CAT(a, b);
}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 314f2087dcf3a..974ebe1f75053 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -21,10 +21,10 @@ bool bad() noexcept __attribute__((pure)) {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and b;
a or_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a or b;
a and_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a and b;
return true;
@@ -48,10 +48,10 @@ bool bad_typedef() {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a and b;
a or_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a or b;
a and_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a and b;
return true;
}
@@ -77,11 +77,11 @@ void bad_side_effects() {
// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() and a;
a or_eq function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a and_eq function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// count of evaluation with side effect remains the same, so the fixit will be provided
@@ -106,19 +106,19 @@ void bad_side_effects() {
// but here the count of evaluation migh be changed - no fix must be provided
a and_eq function_with_possible_side_effects() and c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a and_eq b and function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a or_eq function_with_possible_side_effects() or c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a or_eq b or function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
@@ -135,10 +135,10 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a or_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a and_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
(a bitor c) bitor b;
@@ -258,23 +258,23 @@ void bad_with_priors_already_braced() {
void bad_with_priors_compound() {
bool a = false, b = true, c = true;
a and_eq b or c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a and (b or c);
a or_eq b or c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a or b or c;
a and_eq b and c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a and b and c;
a or_eq b and c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a or b and c;
}
void bad_with_priors_compound_already_braced() {
bool a = false, b = true, c = true;
a and_eq (b or c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a and (b or c);
}
@@ -308,10 +308,10 @@ void bad_in_macro() {
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
IDENT(a or_eq) b;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a IDENT(and_eq b);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// change operator - GOOD
@@ -349,12 +349,12 @@ void bad_in_macro() {
bool ab = false;
// insert ` = a` - BAD
CAT(a, b) and_eq b;
- // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean variable 'ab' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// insert ` = a`- GOOD
b and_eq CAT(a, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'b' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = b and CAT(a, b);
}
@@ -368,11 +368,11 @@ void bad_in_macro_fixit() {
a MY_AND b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
a MY_OR_ASSIGN b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
a MY_AND_ASSIGN b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
IDENT(a and_eq b);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
}
template<typename T>
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
index 2369da53d26ef..19d39bfad6fe6 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand-compound.cpp
@@ -11,10 +11,10 @@ void general(unsigned flags, bool value) {
void assign_to_boolean(unsigned flags, bool value) {
value |= flags << 1;
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean variable 'value' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: value = value || flags << 1;
value |= (flags << 1) | (flags << 2);
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean variable 'value' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-2]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: value = value || (flags << 1) || (flags << 2);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp
index 1ba4108c4c9c6..90ede4115a43f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-static-members.cpp
@@ -27,9 +27,9 @@ void bad() {
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: A::second && b;
A::second |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '||' for boolean variable 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: A::second = A::second || b;
A::second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean variable 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: A::second = A::second && b;
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp
index cc0fee5fd54a7..464a0723d52f0 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-struct-members.cpp
@@ -26,10 +26,10 @@ void bad() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a.second && b;
a.second |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a.second = a.second || b;
a.second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a.second = a.second && b;
}
@@ -47,16 +47,16 @@ void bad_two_lines() {
// CHECK-FIXES: second && b;
a.
second |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: second = a.second || b;
a
.
second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: second = a.second && b;
a
.second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: .second = a.second && b;
}
@@ -71,10 +71,10 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a.second |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a.second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
@@ -93,10 +93,10 @@ void bad_side_effects_volatile2() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a.second |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a.second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
@@ -112,10 +112,10 @@ void bad_arrow() {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: pa->second && b;
pa->second |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '||' for boolean member 'second' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: pa->second = pa->second || b;
pa->second &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '&&' for boolean member 'second' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: pa->second = pa->second && b;
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
index 04c831ab63dd0..0df4b9c4ed680 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
@@ -18,9 +18,9 @@ void bad() {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b;
a |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || b;
a &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && b;
}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 5c2eb5d065514..07bc14c204004 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -21,10 +21,10 @@ bool bad() noexcept __attribute__((pure)) {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b;
a |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || b;
a &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && b;
return true;
@@ -48,10 +48,10 @@ bool bad_typedef() {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a && b;
a |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || b;
a &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && b;
return true;
}
@@ -77,11 +77,11 @@ void bad_side_effects() {
// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: function_with_possible_side_effects() && a;
a |= function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a &= function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// count of evaluation with side effect remains the same, so the fixit will be provided
@@ -106,19 +106,19 @@ void bad_side_effects() {
// but here the count of evaluation migh be changed - no fix must be provided
a &= function_with_possible_side_effects() && c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a &= b && function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= function_with_possible_side_effects() || c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= b || function_with_possible_side_effects();
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
@@ -135,10 +135,10 @@ void bad_side_effects_volatile() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a |= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
(a | c) | b;
@@ -256,23 +256,23 @@ void bad_with_priors_already_braced() {
void bad_with_priors_compound() {
bool a = false, b = true, c = true;
a &= b || c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && (b || c);
a |= b || c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || b || c;
a &= b && c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && b && c;
a |= b && c;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a || b && c;
}
void bad_with_priors_compound_already_braced() {
bool a = false, b = true, c = true;
a &= (b || c);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && (b || c);
}
@@ -306,10 +306,10 @@ void bad_in_macro() {
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
IDENT(a |=) b;
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
a IDENT(&= b);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// change operator - GOOD
@@ -347,12 +347,12 @@ void bad_in_macro() {
bool ab = false;
// insert ` = a` - BAD
CAT(a, b) &= b;
- // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean variable 'ab' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
// insert ` = a`- GOOD
b &= CAT(a, b);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'b' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = b && CAT(a, b);
}
@@ -366,11 +366,11 @@ void bad_in_macro_fixit() {
a MY_AND b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
a MY_OR_ASSIGN b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean variable 'a' instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
a MY_AND_ASSIGN b;
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
IDENT(a &= b);
- // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean variable 'a' instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
}
template<typename T>
>From 6457ade991c847945d0f711e00eb7382450be070 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 21:50:54 +0300
Subject: [PATCH 13/49] format
---
.../misc/BoolBitwiseOperationCheck.cpp | 78 ++++++++++---------
.../misc/BoolBitwiseOperationCheck.h | 2 +-
2 files changed, 41 insertions(+), 39 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 402f6baac5e57..748bf889a19e2 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -75,44 +75,44 @@ static llvm::StringRef translate(llvm::StringRef Value) {
}
static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
- std::optional<bool> &rootAssignsToBoolean) {
+ std::optional<bool> &RootAssignsToBoolean) {
if (!BinOp)
return false;
for (const auto &[Bitwise, _] : OperatorsTransformation) {
if (BinOp->getOpcodeStr() == Bitwise) {
- bool lhsBoolean = BinOp->getLHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
- bool rhsBoolean = BinOp->getRHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
+ bool IsBooleanLHS = BinOp->getLHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ bool IsBooleanRHS = BinOp->getRHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
for (int i = 0; i < 2; ++i) {
- if (lhsBoolean && rhsBoolean) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(false);
+ if (IsBooleanLHS && IsBooleanRHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
return true;
}
if (assignsToBoolean(BinOp, AC) ||
- rootAssignsToBoolean.value_or(false)) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
+ RootAssignsToBoolean.value_or(false)) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
return true;
}
- if (BinOp->isCompoundAssignmentOp() && lhsBoolean) {
- rootAssignsToBoolean = rootAssignsToBoolean.value_or(true);
+ if (BinOp->isCompoundAssignmentOp() && IsBooleanLHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
return true;
}
std::optional<bool> DummyFlag = false;
- lhsBoolean =
- lhsBoolean ||
+ IsBooleanLHS =
+ IsBooleanLHS ||
isBooleanBitwise(dyn_cast<BinaryOperator>(
BinOp->getLHS()->IgnoreParenImpCasts()),
AC, DummyFlag);
- rhsBoolean =
- rhsBoolean ||
+ IsBooleanRHS =
+ IsBooleanRHS ||
isBooleanBitwise(dyn_cast<BinaryOperator>(
BinOp->getRHS()->IgnoreParenImpCasts()),
AC, DummyFlag);
@@ -122,12 +122,14 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
return false;
}
-static const Expr* getValidCompoundsLHS(const BinaryOperator* BinOp) {
+static const Expr *getValidCompoundsLHS(const BinaryOperator *BinOp) {
assert(BinOp->isCompoundAssignmentOp());
-
- if (const auto *DeclRefLHS = dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts()))
+
+ if (const auto *DeclRefLHS =
+ dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts()))
return DeclRefLHS;
- else if (const auto *MemberLHS = dyn_cast<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts()))
+ else if (const auto *MemberLHS =
+ dyn_cast<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts()))
return MemberLHS;
return nullptr;
@@ -159,9 +161,9 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
const clang::SourceManager &SM, clang::ASTContext &Ctx) {
auto DiagEmitter = [BinOp, this] {
return diag(BinOp->getOperatorLoc(),
- "use logical operator '%0' for boolean semantics instead of bitwise operator '%1'")
- << translate(BinOp->getOpcodeStr())
- << BinOp->getOpcodeStr();
+ "use logical operator '%0' for boolean semantics instead of "
+ "bitwise operator '%1'")
+ << translate(BinOp->getOpcodeStr()) << BinOp->getOpcodeStr();
};
const bool HasVolatileOperand = llvm::any_of(
@@ -211,10 +213,10 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
if (InsertLoc.isInvalid() || InsertLoc.isMacroID())
return static_cast<void>(IgnoreMacros || DiagEmitter());
auto SourceText = static_cast<std::string>(Lexer::getSourceText(
- CharSourceRange::getTokenRange(LHS->getSourceRange()),
- SM, Ctx.getLangOpts()
- ));
- llvm::erase_if(SourceText, [](unsigned char ch) { return std::isspace(ch); });
+ CharSourceRange::getTokenRange(LHS->getSourceRange()), SM,
+ Ctx.getLangOpts()));
+ llvm::erase_if(SourceText,
+ [](unsigned char ch) { return std::isspace(ch); });
InsertEqual = FixItHint::CreateInsertion(InsertLoc, " = " + SourceText);
}
@@ -264,27 +266,27 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
void BoolBitwiseOperationCheck::visitBinaryTreesNode(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM, clang::ASTContext &Ctx,
- std::optional<bool> &rootAssignsToBoolean) {
+ std::optional<bool> &RootAssignsToBoolean) {
if (!BinOp)
return;
- if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean))
+ if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean))
emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx);
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp,
- SM, Ctx, rootAssignsToBoolean);
+ SM, Ctx, RootAssignsToBoolean);
visitBinaryTreesNode(
dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp,
- SM, Ctx, rootAssignsToBoolean);
+ SM, Ctx, RootAssignsToBoolean);
}
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *binOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
- std::optional<bool> rootAssignsToBoolean = std::nullopt;
- visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx, rootAssignsToBoolean);
+ std::optional<bool> RootAssignsToBoolean = std::nullopt;
+ visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx, RootAssignsToBoolean);
}
} // namespace clang::tidy::misc
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index a04188027d3c2..2787b1a1543ee 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -40,7 +40,7 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM,
clang::ASTContext &Ctx,
- std::optional<bool>& rootAssignsToBoolean);
+ std::optional<bool> &rootAssignsToBoolean);
private:
bool StrictMode;
>From 7c6552f01b2c194a2fd5114da1d3ac5b4245470d Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 8 Nov 2025 22:03:08 +0300
Subject: [PATCH 14/49] fix list.rst
---
clang-tools-extra/docs/clang-tidy/checks/list.rst | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index d1344d4c47f8c..865c9cb6e5d48 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -174,9 +174,7 @@ Clang-Tidy Checks
:doc:`bugprone-use-after-move <bugprone/use-after-move>`,
:doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes"
:doc:`cert-dcl58-cpp <cert/dcl58-cpp>`,
- :doc:`cert-env33-c <cert/env33-c>`,
:doc:`cert-err33-c <cert/err33-c>`,
- :doc:`cert-err52-cpp <cert/err52-cpp>`,
:doc:`cert-err60-cpp <cert/err60-cpp>`,
:doc:`cert-flp30-c <cert/flp30-c>`,
:doc:`cert-mem57-cpp <cert/mem57-cpp>`,
@@ -375,7 +373,7 @@ Clang-Tidy Checks
:doc:`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`, "Yes"
:doc:`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>`,
- :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
+ :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`readability-const-return-type <readability/const-return-type>`, "Yes"
:doc:`readability-container-contains <readability/container-contains>`, "Yes"
:doc:`readability-container-data-pointer <readability/container-data-pointer>`, "Yes"
@@ -445,7 +443,9 @@ Check aliases
:doc:`cert-dcl54-cpp <cert/dcl54-cpp>`, :doc:`misc-new-delete-overloads <misc/new-delete-overloads>`,
:doc:`cert-dcl59-cpp <cert/dcl59-cpp>`, :doc:`google-build-namespaces <google/build-namespaces>`,
:doc:`cert-err09-cpp <cert/err09-cpp>`, :doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`,
+ :doc:`cert-env33-c <cert/env33-c>`, :doc:`bugprone-command-processor <bugprone/command-processor>`,
:doc:`cert-err34-c <cert/err34-c>`, :doc:`bugprone-unchecked-string-to-number-conversion <bugprone/unchecked-string-to-number-conversion>`,
+ :doc:`cert-err52-cpp <cert/err52-cpp>`, :doc:`modernize-avoid-setjmp-longjmp <modernize/avoid-setjmp-longjmp>`,
:doc:`cert-err58-cpp <cert/err58-cpp>`, :doc:`bugprone-throwing-static-initialization <bugprone/throwing-static-initialization>`,
:doc:`cert-err61-cpp <cert/err61-cpp>`, :doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`,
:doc:`cert-exp42-c <cert/exp42-c>`, :doc:`bugprone-suspicious-memory-comparison <bugprone/suspicious-memory-comparison>`,
@@ -572,12 +572,12 @@ Check aliases
:doc:`cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines/non-private-member-variables-in-classes>`, :doc:`misc-non-private-member-variables-in-classes <misc/non-private-member-variables-in-classes>`,
:doc:`cppcoreguidelines-use-default-member-init <cppcoreguidelines/use-default-member-init>`, :doc:`modernize-use-default-member-init <modernize/use-default-member-init>`, "Yes"
:doc:`fuchsia-header-anon-namespaces <fuchsia/header-anon-namespaces>`, :doc:`google-build-namespaces <google/build-namespaces>`,
- :doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
+ :doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`google-readability-function-size <google/readability-function-size>`, :doc:`readability-function-size <readability/function-size>`,
:doc:`google-readability-namespace-comments <google/readability-namespace-comments>`, :doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`hicpp-avoid-c-arrays <hicpp/avoid-c-arrays>`, :doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`,
:doc:`hicpp-avoid-goto <hicpp/avoid-goto>`, :doc:`cppcoreguidelines-avoid-goto <cppcoreguidelines/avoid-goto>`,
- :doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`,
+ :doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`hicpp-deprecated-headers <hicpp/deprecated-headers>`, :doc:`modernize-deprecated-headers <modernize/deprecated-headers>`, "Yes"
:doc:`hicpp-explicit-conversions <hicpp/explicit-conversions>`, :doc:`google-explicit-constructor <google/explicit-constructor>`, "Yes"
:doc:`hicpp-function-size <hicpp/function-size>`, :doc:`readability-function-size <readability/function-size>`,
@@ -602,4 +602,4 @@ Check aliases
:doc:`hicpp-use-override <hicpp/use-override>`, :doc:`modernize-use-override <modernize/use-override>`, "Yes"
:doc:`hicpp-vararg <hicpp/vararg>`, :doc:`cppcoreguidelines-pro-type-vararg <cppcoreguidelines/pro-type-vararg>`,
:doc:`llvm-else-after-return <llvm/else-after-return>`, :doc:`readability-else-after-return <readability/else-after-return>`, "Yes"
- :doc:`llvm-qualified-auto <llvm/qualified-auto>`, :doc:`readability-qualified-auto <readability/qualified-auto>`, "Yes"
+ :doc:`llvm-qualified-auto <llvm/qualified-auto>`, :doc:`readability-qualified-auto <readability/qualified-auto>`, "Yes"
\ No newline at end of file
>From 2aaa9285f51bc45135b901fd68c0f1c508183d18 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sun, 9 Nov 2025 02:02:54 +0300
Subject: [PATCH 15/49] Optimize
---
.../misc/BoolBitwiseOperationCheck.cpp | 37 ++++++++++++-------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 748bf889a19e2..60d769e7b9e7d 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -74,6 +74,24 @@ static llvm::StringRef translate(llvm::StringRef Value) {
return {};
}
+static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
+ std::optional<bool> &RootAssignsToBoolean);
+
+static bool recheckIsBooleanDeeply(const BinaryOperator *BinOp, ASTContext *AC,
+ bool &IsBooleanLHS, bool &IsBooleanRHS) {
+ std::optional<bool> DummyFlag = false;
+ IsBooleanLHS = IsBooleanLHS ||
+ isBooleanBitwise(dyn_cast<BinaryOperator>(
+ BinOp->getLHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+ IsBooleanRHS = IsBooleanRHS ||
+ isBooleanBitwise(dyn_cast<BinaryOperator>(
+ BinOp->getRHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+ return true; // just a formal bool for possibility to be invoked from
+ // expression
+}
+
static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
std::optional<bool> &RootAssignsToBoolean) {
if (!BinOp)
@@ -91,7 +109,9 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
->getType()
.getDesugaredType(*AC)
->isBooleanType();
- for (int i = 0; i < 2; ++i) {
+ for (int i = 0; i < 2;
+ !i++ &&
+ recheckIsBooleanDeeply(BinOp, AC, IsBooleanLHS, IsBooleanRHS)) {
if (IsBooleanLHS && IsBooleanRHS) {
RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
return true;
@@ -105,24 +125,13 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
return true;
}
- std::optional<bool> DummyFlag = false;
- IsBooleanLHS =
- IsBooleanLHS ||
- isBooleanBitwise(dyn_cast<BinaryOperator>(
- BinOp->getLHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
- IsBooleanRHS =
- IsBooleanRHS ||
- isBooleanBitwise(dyn_cast<BinaryOperator>(
- BinOp->getRHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
}
}
}
return false;
}
-static const Expr *getValidCompoundsLHS(const BinaryOperator *BinOp) {
+static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
assert(BinOp->isCompoundAssignmentOp());
if (const auto *DeclRefLHS =
@@ -202,7 +211,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
FixItHint InsertEqual;
if (BinOp->isCompoundAssignmentOp()) {
- const auto *LHS = getValidCompoundsLHS(BinOp);
+ const auto *LHS = getAcceptableCompoundsLHS(BinOp);
if (!LHS)
return static_cast<void>(DiagEmitter());
const SourceLocation LocLHS = LHS->getEndLoc();
>From 75a5399deac0599ce9da27a3dadbbee3d7d4f4aa Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sun, 9 Nov 2025 02:35:11 +0300
Subject: [PATCH 16/49] Fix flags case
---
.../misc/BoolBitwiseOperationCheck.cpp | 63 +++++++++----------
.../misc/bool-bitwise-operation-flags.cpp | 9 +++
2 files changed, 38 insertions(+), 34 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-flags.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 60d769e7b9e7d..6ba43af96f8a8 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -74,24 +74,6 @@ static llvm::StringRef translate(llvm::StringRef Value) {
return {};
}
-static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
- std::optional<bool> &RootAssignsToBoolean);
-
-static bool recheckIsBooleanDeeply(const BinaryOperator *BinOp, ASTContext *AC,
- bool &IsBooleanLHS, bool &IsBooleanRHS) {
- std::optional<bool> DummyFlag = false;
- IsBooleanLHS = IsBooleanLHS ||
- isBooleanBitwise(dyn_cast<BinaryOperator>(
- BinOp->getLHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
- IsBooleanRHS = IsBooleanRHS ||
- isBooleanBitwise(dyn_cast<BinaryOperator>(
- BinOp->getRHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
- return true; // just a formal bool for possibility to be invoked from
- // expression
-}
-
static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
std::optional<bool> &RootAssignsToBoolean) {
if (!BinOp)
@@ -109,22 +91,35 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
->getType()
.getDesugaredType(*AC)
->isBooleanType();
- for (int i = 0; i < 2;
- !i++ &&
- recheckIsBooleanDeeply(BinOp, AC, IsBooleanLHS, IsBooleanRHS)) {
- if (IsBooleanLHS && IsBooleanRHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
- return true;
- }
- if (assignsToBoolean(BinOp, AC) ||
- RootAssignsToBoolean.value_or(false)) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
- return true;
- }
- if (BinOp->isCompoundAssignmentOp() && IsBooleanLHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
- return true;
- }
+ if (IsBooleanLHS && IsBooleanRHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
+ return true;
+ }
+ if (((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, AC)) ||
+ RootAssignsToBoolean.value_or(false)) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
+ return true;
+ }
+ if (BinOp->isCompoundAssignmentOp() && IsBooleanLHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
+ return true;
+ }
+
+ std::optional<bool> DummyFlag = false;
+ IsBooleanLHS =
+ IsBooleanLHS ||
+ isBooleanBitwise(
+ dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+ IsBooleanRHS =
+ IsBooleanRHS ||
+ isBooleanBitwise(
+ dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+
+ if (IsBooleanLHS && IsBooleanRHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
+ return true;
}
}
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-flags.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-flags.cpp
new file mode 100644
index 0000000000000..a7b6af0413484
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-flags.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t
+
+bool normal() {
+ unsigned flags = 100;
+ if (flags & 0xFFFFFFF8) {
+
+ }
+ return flags & 0x20;
+}
>From c01dfbebebd201c9b4bde2c885733f80ab911390 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Wed, 12 Nov 2025 20:23:50 +0300
Subject: [PATCH 17/49] simplify
---
.../misc/BoolBitwiseOperationCheck.cpp | 11 +---------
...itwise-operation-not-only-bool-operand.cpp | 20 ++-----------------
2 files changed, 3 insertions(+), 28 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 6ba43af96f8a8..a19e759ea5263 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -35,16 +35,7 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
auto Parents = AC->getParents(*BinOp);
for (const auto &Parent : Parents) {
- const auto *ParentNoParen = ignoreParensTowardsTheRoot(&Parent, AC);
- // Special handling for `template<bool bb=true|1>` cases
- if (const auto *D = ParentNoParen->get<Decl>()) {
- if (const auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- if (NTTPD->getType().getDesugaredType(*AC)->isBooleanType())
- return true;
- }
- }
-
- if (const auto *S = ParentNoParen->get<Stmt>()) {
+ if (const auto *S = ignoreParensTowardsTheRoot(&Parent, AC)->get<Stmt>()) {
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(S)) {
if (ICE->getType().getDesugaredType(*AC)->isBooleanType())
return true;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index e0cd992fa78a4..f93297a42f686 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -11,9 +11,8 @@ void general(unsigned flags, bool value) {
void take(bool value) {}
-template<bool bb = true | 1>
-// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
-// CHECK-FIXES: template<bool bb = true || 1>
+// FIXME: implement `template<bool bb=true|1>` cases
+
void assign_to_boolean(unsigned flags, bool value) {
struct A { bool a = true | 1; };
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -50,9 +49,6 @@ void assign_to_boolean(unsigned flags, bool value) {
// CHECK-FIXES: result = (flags << 1) || (flags << 2) || (flags << 4) || value;
}
-template<bool bb = (true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
-// CHECK-FIXES: template<bool bb = (true || 1)>
void assign_to_boolean_parens(unsigned flags, bool value) {
struct A { bool a = (true | 1); };
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -89,9 +85,6 @@ void assign_to_boolean_parens(unsigned flags, bool value) {
// CHECK-FIXES: result = ((flags << 1) || (flags << 2) || (flags << 4) || value);
}
-template<bool bb = ((true | 1))>
-// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
-// CHECK-FIXES: template<bool bb = ((true || 1))>
void assign_to_boolean_parens2(unsigned flags, bool value) {
struct A { bool a = ((true | 1)); };
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -129,9 +122,6 @@ void assign_to_boolean_parens2(unsigned flags, bool value) {
}
// functional cast
-template<bool bb = bool(true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
-// CHECK-FIXES: template<bool bb = bool(true || 1)>
void assign_to_boolean_fcast(unsigned flags, bool value) {
struct A { bool a = bool(true | 1); };
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -169,9 +159,6 @@ void assign_to_boolean_fcast(unsigned flags, bool value) {
}
// C-style cast
-template<bool bb = (bool)(true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
-// CHECK-FIXES: template<bool bb = (bool)(true || 1)>
void assign_to_boolean_ccast(unsigned flags, bool value) {
struct A { bool a = (bool)(true | 1); };
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
@@ -209,9 +196,6 @@ void assign_to_boolean_ccast(unsigned flags, bool value) {
}
// static_cast
-template<bool bb = static_cast<bool>(true | 1)>
-// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
-// CHECK-FIXES: template<bool bb = static_cast<bool>(true || 1)>
void assign_to_boolean_scast(unsigned flags, bool value) {
struct A { bool a = static_cast<bool>(true | 1); };
// CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
>From af75a05c0fe16ea800aa3baba3afdb72c029281d Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Wed, 12 Nov 2025 20:55:49 +0300
Subject: [PATCH 18/49] lint
---
.../misc/BoolBitwiseOperationCheck.cpp | 72 ++++++++++++-------
.../misc/BoolBitwiseOperationCheck.h | 5 +-
2 files changed, 48 insertions(+), 29 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index a19e759ea5263..043893f904d6c 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -123,8 +123,8 @@ static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
if (const auto *DeclRefLHS =
dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts()))
return DeclRefLHS;
- else if (const auto *MemberLHS =
- dyn_cast<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts()))
+ if (const auto *MemberLHS =
+ dyn_cast<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts()))
return MemberLHS;
return nullptr;
@@ -168,50 +168,68 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
.getDesugaredType(Ctx)
.isVolatileQualified();
});
- if (HasVolatileOperand)
- return static_cast<void>(DiagEmitter());
+ if (HasVolatileOperand) {
+ DiagEmitter();
+ return;
+ }
const bool HasSideEffects = BinOp->getRHS()->HasSideEffects(
Ctx, /*IncludePossibleEffects=*/!StrictMode);
- if (HasSideEffects)
- return static_cast<void>(DiagEmitter());
+ if (HasSideEffects) {
+ DiagEmitter();
+ return;
+ }
SourceLocation Loc = BinOp->getOperatorLoc();
- if (Loc.isInvalid() || Loc.isMacroID())
- return static_cast<void>(IgnoreMacros || DiagEmitter());
+ if (Loc.isInvalid() || Loc.isMacroID()) {
+ IgnoreMacros || DiagEmitter();
+ return;
+ }
Loc = SM.getSpellingLoc(Loc);
- if (Loc.isInvalid() || Loc.isMacroID())
- return static_cast<void>(IgnoreMacros || DiagEmitter());
+ if (Loc.isInvalid() || Loc.isMacroID()) {
+ IgnoreMacros || DiagEmitter();
+ return;
+ }
const CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc);
- if (TokenRange.isInvalid())
- return static_cast<void>(IgnoreMacros || DiagEmitter());
+ if (TokenRange.isInvalid()) {
+ IgnoreMacros || DiagEmitter();
+ return;
+ }
const StringRef FixSpelling =
translate(Lexer::getSourceText(TokenRange, SM, Ctx.getLangOpts()));
- if (FixSpelling.empty())
- return static_cast<void>(DiagEmitter());
+ if (FixSpelling.empty()) {
+ DiagEmitter();
+ return;
+ }
FixItHint InsertEqual;
if (BinOp->isCompoundAssignmentOp()) {
const auto *LHS = getAcceptableCompoundsLHS(BinOp);
- if (!LHS)
- return static_cast<void>(DiagEmitter());
+ if (!LHS) {
+ DiagEmitter();
+ return;
+ }
const SourceLocation LocLHS = LHS->getEndLoc();
- if (LocLHS.isInvalid() || LocLHS.isMacroID())
- return static_cast<void>(IgnoreMacros || DiagEmitter());
+ if (LocLHS.isInvalid() || LocLHS.isMacroID()) {
+ IgnoreMacros || DiagEmitter();
+ return;
+ }
const SourceLocation InsertLoc =
clang::Lexer::getLocForEndOfToken(LocLHS, 0, SM, Ctx.getLangOpts());
- if (InsertLoc.isInvalid() || InsertLoc.isMacroID())
- return static_cast<void>(IgnoreMacros || DiagEmitter());
+ if (InsertLoc.isInvalid() || InsertLoc.isMacroID()) {
+ IgnoreMacros || DiagEmitter();
+ return;
+ }
auto SourceText = static_cast<std::string>(Lexer::getSourceText(
CharSourceRange::getTokenRange(LHS->getSourceRange()), SM,
Ctx.getLangOpts()));
llvm::erase_if(SourceText,
- [](unsigned char ch) { return std::isspace(ch); });
+ [](unsigned char Ch) { return std::isspace(Ch); });
InsertEqual = FixItHint::CreateInsertion(InsertLoc, " = " + SourceText);
}
@@ -238,7 +256,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
} else if (BinOp->getOpcode() == BO_AndAssign && RHSOpcode == BO_LOr)
SurroundedExpr = RHS;
- if (SurroundedExpr && isa<ParenExpr>(SurroundedExpr))
+ if (isa_and_nonnull<ParenExpr>(SurroundedExpr))
SurroundedExpr = nullptr;
FixItHint InsertBrace1;
@@ -248,8 +266,10 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
const SourceLocation InsertSecondLoc = clang::Lexer::getLocForEndOfToken(
SurroundedExpr->getEndLoc(), 0, SM, Ctx.getLangOpts());
if (InsertFirstLoc.isInvalid() || InsertFirstLoc.isMacroID() ||
- InsertSecondLoc.isInvalid() || InsertSecondLoc.isMacroID())
- return static_cast<void>(IgnoreMacros || DiagEmitter());
+ InsertSecondLoc.isInvalid() || InsertSecondLoc.isMacroID()) {
+ IgnoreMacros || DiagEmitter();
+ return;
+ }
InsertBrace1 = FixItHint::CreateInsertion(InsertFirstLoc, "(");
InsertBrace2 = FixItHint::CreateInsertion(InsertSecondLoc, ")");
}
@@ -277,11 +297,11 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode(
}
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *binOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
+ const auto *BinOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
std::optional<bool> RootAssignsToBoolean = std::nullopt;
- visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx, RootAssignsToBoolean);
+ visitBinaryTreesNode(BinOpRoot, nullptr, SM, Ctx, RootAssignsToBoolean);
}
} // namespace clang::tidy::misc
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index 2787b1a1543ee..017f1053423a2 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -22,7 +22,7 @@ namespace clang::tidy::misc {
class BoolBitwiseOperationCheck : public ClangTidyCheck {
public:
BoolBitwiseOperationCheck(StringRef Name, ClangTidyContext *Context);
- void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
@@ -40,9 +40,8 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM,
clang::ASTContext &Ctx,
- std::optional<bool> &rootAssignsToBoolean);
+ std::optional<bool> &RootAssignsToBoolean);
-private:
bool StrictMode;
bool IgnoreMacros;
};
>From aaf2612e509e58179b7efa194f852215b4fefca6 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Wed, 12 Nov 2025 21:16:18 +0300
Subject: [PATCH 19/49] Actualize docs
---
.../misc/BoolBitwiseOperationCheck.cpp | 6 ++---
.../misc/BoolBitwiseOperationCheck.h | 2 +-
.../checks/misc/bool-bitwise-operation.rst | 25 +++++++++++++++----
...-operation-change-possible-side-effect.cpp | 2 +-
4 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 043893f904d6c..1507d51320c7c 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -133,12 +133,12 @@ static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
- StrictMode(Options.get("StrictMode", false)),
+ UnsafeMode(Options.get("UnsafeMode", false)),
IgnoreMacros(Options.get("IgnoreMacros", false)) {}
void BoolBitwiseOperationCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
- Options.store(Opts, "StrictMode", StrictMode);
+ Options.store(Opts, "UnsafeMode", UnsafeMode);
Options.store(Opts, "IgnoreMacros", IgnoreMacros);
}
@@ -174,7 +174,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
}
const bool HasSideEffects = BinOp->getRHS()->HasSideEffects(
- Ctx, /*IncludePossibleEffects=*/!StrictMode);
+ Ctx, /*IncludePossibleEffects=*/!UnsafeMode);
if (HasSideEffects) {
DiagEmitter();
return;
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index 017f1053423a2..082e4b48c27e8 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -42,7 +42,7 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
clang::ASTContext &Ctx,
std::optional<bool> &RootAssignsToBoolean);
- bool StrictMode;
+ bool UnsafeMode;
bool IgnoreMacros;
};
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
index e70ac82779644..480f92452f9c4 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -14,8 +14,17 @@ to implicit integer conversions and missed short-circuit evaluation.
bool invalid = false;
invalid |= x > limit.x; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
+ // 400 | invalid |= x > limit.x;
+ // | ^~
+ // | = invalid ||
invalid |= y > limit.y; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
+ // 401 | invalid |= y > limit.y;
+ // | ^~
+ // | = invalid ||
invalid |= z > limit.z; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
+ // 402 | invalid |= z > limit.z;
+ // | ^~
+ // | = invalid ||
if (invalid) {
// error handling
}
@@ -33,24 +42,30 @@ instead of using the ``|=`` operator:
// error handling
}
+It is not always a safe transformation though. The following case will warn
+without fix-it to preserve the semantics.
+
+.. code-block:: c++
+
+ volatile bool invalid = false;
+ invalid |= x > limit.x; // warning: use logical operator '||' for boolean semantics instead of bitwise operator '|='
+
Limitations
-----------
-* Bitwise operators inside templates aren't matched.
+* Bitwise operators inside templates aren't guaranteed to match.
.. code-block:: c++
template <typename X>
void f(X a, X b) {
- a | b;
+ a | b; // the warning may not be emited
}
- // even 'f(true, false)' (or similar) won't trigger the warning.
-
Options
-------
-.. option:: StrictMode
+.. option:: UnsafeMode
Enabling this option promotes more fix-it hints even when they might
change evaluation order or skip side effects. Default value is `false`.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
index a51220be391bc..ee700763136c7 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
@@ -1,6 +1,6 @@
// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t \
// RUN: -config="{CheckOptions: { \
-// RUN: misc-bool-bitwise-operation.StrictMode: true }}"
+// RUN: misc-bool-bitwise-operation.UnsafeMode: true }}"
bool function_with_possible_side_effects();
>From 96dc087ce530224c0284972cfb642efffe0a66fd Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 14 Nov 2025 01:11:55 +0300
Subject: [PATCH 20/49] review from EugeneZelenko
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 2 +-
.../clang-tidy/misc/BoolBitwiseOperationCheck.h | 6 +++---
.../test/clang-tidy/checkers/misc/bool-bitwise-operation.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 1507d51320c7c..8d1bc2f18065a 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -1,4 +1,4 @@
-//===--- BoolBitwiseOperationCheck.cpp - clang-tidy -----------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index 082e4b48c27e8..3725e0b54ebc5 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -1,4 +1,4 @@
-//===--- BoolBitwiseOperationCheck.h - clang-tidy ---------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -18,7 +18,7 @@ namespace clang::tidy::misc {
/// ``&&`` and ``||`` would be more appropriate.
///
/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc/bool-bitwise-operation.html
+/// https://clang.llvm.org/extra/clang-tidy/checks/misc/bool-bitwise-operation.html
class BoolBitwiseOperationCheck : public ClangTidyCheck {
public:
BoolBitwiseOperationCheck(StringRef Name, ClangTidyContext *Context);
@@ -48,4 +48,4 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
} // namespace clang::tidy::misc
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLBITWISEOPERATIONCHECK_H
\ No newline at end of file
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLBITWISEOPERATIONCHECK_H
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
index 0df4b9c4ed680..ebafc19dca605 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.c
@@ -23,4 +23,4 @@ void bad() {
a &= b;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: a = a && b;
-}
\ No newline at end of file
+}
>From 123aa6385de4d88d5bde4f6d526932df31a43519 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 14 Nov 2025 01:16:26 +0300
Subject: [PATCH 21/49] more newlines
---
clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 2 +-
.../misc/bool-bitwise-operation-change-possible-side-effect.cpp | 2 +-
.../checkers/misc/bool-bitwise-operation-ignore-macros.cpp | 2 +-
.../checkers/misc/bool-bitwise-operation-nontraditional.cpp | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 8d1bc2f18065a..f483888a82bb6 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -304,4 +304,4 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
visitBinaryTreesNode(BinOpRoot, nullptr, SM, Ctx, RootAssignsToBoolean);
}
-} // namespace clang::tidy::misc
\ No newline at end of file
+} // namespace clang::tidy::misc
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
index ee700763136c7..a39131ec54a8e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-change-possible-side-effect.cpp
@@ -79,4 +79,4 @@ void bad_definitely_side_effects() {
a |= b || (acc++, c);
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
-}
\ No newline at end of file
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
index d2b742cf207d1..9980e65fddeaa 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-ignore-macros.cpp
@@ -50,4 +50,4 @@ void bad_in_macro() {
b &= CAT(a, b);
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
// CHECK-FIXES: b = b && CAT(a, b);
-}
\ No newline at end of file
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 974ebe1f75053..69b090479bad4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -408,4 +408,4 @@ int bad_in_template_lamnda_captured(T a, T b) {
return 0;
}
-int dummy = bad_in_template(true, false) + bad_in_template_lamnda_captured(false, true);
\ No newline at end of file
+int dummy = bad_in_template(true, false) + bad_in_template_lamnda_captured(false, true);
>From aff7d536b036ec307cc7b8e6b4957ce8ba814b45 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 14 Nov 2025 02:00:42 +0300
Subject: [PATCH 22/49] review from localspook
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 10 +++++-----
clang-tools-extra/docs/clang-tidy/checks/list.rst | 2 +-
.../clang-tidy/checks/misc/bool-bitwise-operation.rst | 11 +++++------
.../misc/bool-bitwise-operation-nontraditional.cpp | 4 ++--
.../checkers/misc/bool-bitwise-operation.cpp | 4 ++--
5 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index f483888a82bb6..4a83db09e4a88 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -22,9 +22,9 @@ static const DynTypedNode *ignoreParensTowardsTheRoot(const DynTypedNode *N,
if (const auto *S = N->get<Stmt>()) {
if (isa<ParenExpr>(S)) {
auto Parents = AC->getParents(*S);
- for (const auto &Parent : Parents) {
- return ignoreParensTowardsTheRoot(&Parent, AC);
- }
+ // FIXME: do we need to consider all `Parents` ?
+ if (!Parents.empty())
+ return ignoreParensTowardsTheRoot(&Parents[0], AC);
}
}
return N;
@@ -46,7 +46,7 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
return false;
}
-constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
+static constexpr std::array<std::pair<StringRef, StringRef>, 8U>
OperatorsTransformation{{{"|", "||"},
{"|=", "||"},
{"&", "&&"},
@@ -56,7 +56,7 @@ constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
{"bitor", "or"},
{"or_eq", "or"}}};
-static llvm::StringRef translate(llvm::StringRef Value) {
+static StringRef translate(StringRef Value) {
for (const auto &[Bitwise, Logical] : OperatorsTransformation) {
if (Value == Bitwise)
return Logical;
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 3e14aee287d64..a1b7ab5eeb90f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -609,4 +609,4 @@ Check aliases
:doc:`hicpp-use-override <hicpp/use-override>`, :doc:`modernize-use-override <modernize/use-override>`, "Yes"
:doc:`hicpp-vararg <hicpp/vararg>`, :doc:`cppcoreguidelines-pro-type-vararg <cppcoreguidelines/pro-type-vararg>`,
:doc:`llvm-else-after-return <llvm/else-after-return>`, :doc:`readability-else-after-return <readability/else-after-return>`, "Yes"
- :doc:`llvm-qualified-auto <llvm/qualified-auto>`, :doc:`readability-qualified-auto <readability/qualified-auto>`, "Yes"
\ No newline at end of file
+ :doc:`llvm-qualified-auto <llvm/qualified-auto>`, :doc:`readability-qualified-auto <readability/qualified-auto>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
index 480f92452f9c4..5dd8ff6d68374 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -59,7 +59,7 @@ Limitations
template <typename X>
void f(X a, X b) {
- a | b; // the warning may not be emited
+ a | b; // the warning may not be emitted
}
Options
@@ -67,11 +67,10 @@ Options
.. option:: UnsafeMode
- Enabling this option promotes more fix-it hints even when they might
- change evaluation order or skip side effects. Default value is `false`.
+ Promotes more fix-it hints even when they might change evaluation order or
+ skip side effects. Default value is `false`.
.. option:: IgnoreMacros
- This option disables the warning if a macro inside the expression body
- prevents replacing a bitwise operator with a logical one. Default value
- is `false`.
\ No newline at end of file
+ Don't warn if a macro inside the expression body prevents replacing a
+ bitwise operator with a logical one. Default value is `false`.
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 69b090479bad4..c6a8a7810c93b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -396,7 +396,7 @@ int bad_in_template(T a, T b) {
}
template<typename T>
-int bad_in_template_lamnda_captured(T a, T b) {
+int bad_in_template_lambda_captured(T a, T b) {
[=] mutable {
bool c = false;
// FIXME: at least warning should be provided in these cases
@@ -408,4 +408,4 @@ int bad_in_template_lamnda_captured(T a, T b) {
return 0;
}
-int dummy = bad_in_template(true, false) + bad_in_template_lamnda_captured(false, true);
+int dummy = bad_in_template(true, false) + bad_in_template_lambda_captured(false, true);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 07bc14c204004..519ba32b9f3c1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -394,7 +394,7 @@ int bad_in_template(T a, T b) {
}
template<typename T>
-int bad_in_template_lamnda_captured(T a, T b) {
+int bad_in_template_lambda_captured(T a, T b) {
[=] mutable {
bool c = false;
// FIXME: at least warning should be provided in these cases
@@ -406,4 +406,4 @@ int bad_in_template_lamnda_captured(T a, T b) {
return 0;
}
-int dummy = bad_in_template(true, false) + bad_in_template_lamnda_captured(false, true);
\ No newline at end of file
+int dummy = bad_in_template(true, false) + bad_in_template_lambda_captured(false, true);
\ No newline at end of file
>From 52066b75927ab622d1e50115a2b57366891a96bc Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 14 Nov 2025 02:07:21 +0300
Subject: [PATCH 23/49] review
---
.../docs/clang-tidy/checks/misc/bool-bitwise-operation.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
index 5dd8ff6d68374..f7f03575ae126 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -67,7 +67,7 @@ Options
.. option:: UnsafeMode
- Promotes more fix-it hints even when they might change evaluation order or
+ Provide more fix-it hints even when they might change evaluation order or
skip side effects. Default value is `false`.
.. option:: IgnoreMacros
>From a4c4487a22b39e2e2d0733491d7b5dbc9605c758 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 14 Nov 2025 02:12:15 +0300
Subject: [PATCH 24/49] more newlines
---
.../test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 519ba32b9f3c1..6487026b07583 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -406,4 +406,4 @@ int bad_in_template_lambda_captured(T a, T b) {
return 0;
}
-int dummy = bad_in_template(true, false) + bad_in_template_lambda_captured(false, true);
\ No newline at end of file
+int dummy = bad_in_template(true, false) + bad_in_template_lambda_captured(false, true);
>From 7c069dace162958d941200de5d0fbc5e1bf8a920 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 14 Nov 2025 20:04:45 +0300
Subject: [PATCH 25/49] any_of
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 4a83db09e4a88..5d1b7d86f6c51 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -34,16 +34,11 @@ static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
TraversalKindScope RAII(*AC, TK_AsIs);
auto Parents = AC->getParents(*BinOp);
- for (const auto &Parent : Parents) {
- if (const auto *S = ignoreParensTowardsTheRoot(&Parent, AC)->get<Stmt>()) {
- if (const auto *ICE = dyn_cast<ImplicitCastExpr>(S)) {
- if (ICE->getType().getDesugaredType(*AC)->isBooleanType())
- return true;
- }
- }
- }
-
- return false;
+ return llvm::any_of(Parents, [&](const DynTypedNode &Parent) {
+ const auto *S = ignoreParensTowardsTheRoot(&Parent, AC)->get<Stmt>();
+ const auto *ICE = dyn_cast_if_present<ImplicitCastExpr>(S);
+ return ICE ? ICE->getType().getDesugaredType(*AC)->isBooleanType() : false;
+ });
}
static constexpr std::array<std::pair<StringRef, StringRef>, 8U>
>From 4e7cdc4f1073d0e70f3ca533f1f1c9a35a3cf617 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Thu, 20 Nov 2025 21:29:42 +0300
Subject: [PATCH 26/49] review
---
.../misc/BoolBitwiseOperationCheck.cpp | 108 ++++++++----------
1 file changed, 49 insertions(+), 59 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 5d1b7d86f6c51..fe3bac73b7c90 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -19,13 +19,11 @@ namespace clang::tidy::misc {
static const DynTypedNode *ignoreParensTowardsTheRoot(const DynTypedNode *N,
ASTContext *AC) {
- if (const auto *S = N->get<Stmt>()) {
- if (isa<ParenExpr>(S)) {
- auto Parents = AC->getParents(*S);
- // FIXME: do we need to consider all `Parents` ?
- if (!Parents.empty())
- return ignoreParensTowardsTheRoot(&Parents[0], AC);
- }
+ if (const auto *S = N->get<Stmt>(); isa_and_nonnull<ParenExpr>(S)) {
+ auto Parents = AC->getParents(*S);
+ // FIXME: do we need to consider all `Parents` ?
+ if (!Parents.empty())
+ return ignoreParensTowardsTheRoot(&Parents[0], AC);
}
return N;
}
@@ -65,64 +63,56 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
if (!BinOp)
return false;
- for (const auto &[Bitwise, _] : OperatorsTransformation) {
- if (BinOp->getOpcodeStr() == Bitwise) {
- bool IsBooleanLHS = BinOp->getLHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
- bool IsBooleanRHS = BinOp->getRHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
- if (IsBooleanLHS && IsBooleanRHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
- return true;
- }
- if (((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, AC)) ||
- RootAssignsToBoolean.value_or(false)) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
- return true;
- }
- if (BinOp->isCompoundAssignmentOp() && IsBooleanLHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
- return true;
- }
-
- std::optional<bool> DummyFlag = false;
- IsBooleanLHS =
- IsBooleanLHS ||
- isBooleanBitwise(
- dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
- IsBooleanRHS =
- IsBooleanRHS ||
- isBooleanBitwise(
- dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
-
- if (IsBooleanLHS && IsBooleanRHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
- return true;
- }
- }
+ if (!llvm::is_contained(llvm::make_first_range(OperatorsTransformation), BinOp->getOpcodeStr()))
+ return false;
+
+ bool IsBooleanLHS = BinOp->getLHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ bool IsBooleanRHS = BinOp->getRHS()
+ ->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ if (IsBooleanLHS && IsBooleanRHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
+ return true;
+ }
+ if (((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, AC)) ||
+ RootAssignsToBoolean.value_or(false)) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
+ return true;
+ }
+ if (BinOp->isCompoundAssignmentOp() && IsBooleanLHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
+ return true;
+ }
+
+ std::optional<bool> DummyFlag = false;
+ IsBooleanLHS =
+ IsBooleanLHS ||
+ isBooleanBitwise(
+ dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+ IsBooleanRHS =
+ IsBooleanRHS ||
+ isBooleanBitwise(
+ dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+
+ if (IsBooleanLHS && IsBooleanRHS) {
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
+ return true;
}
return false;
}
static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
assert(BinOp->isCompoundAssignmentOp());
-
- if (const auto *DeclRefLHS =
- dyn_cast<DeclRefExpr>(BinOp->getLHS()->IgnoreImpCasts()))
- return DeclRefLHS;
- if (const auto *MemberLHS =
- dyn_cast<MemberExpr>(BinOp->getLHS()->IgnoreImpCasts()))
- return MemberLHS;
-
- return nullptr;
+ const Expr *LHS = BinOp->getLHS()->IgnoreImpCasts();
+ return isa<DeclRefExpr, MemberExpr>(LHS) ? LHS : nullptr;
}
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
>From b3af19666ca724858cd314affbde3ff38105eda5 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Thu, 20 Nov 2025 21:41:10 +0300
Subject: [PATCH 27/49] format
---
.../misc/BoolBitwiseOperationCheck.cpp | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index fe3bac73b7c90..4fe8460d01eec 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -63,7 +63,8 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
if (!BinOp)
return false;
- if (!llvm::is_contained(llvm::make_first_range(OperatorsTransformation), BinOp->getOpcodeStr()))
+ if (!llvm::is_contained(llvm::make_first_range(OperatorsTransformation),
+ BinOp->getOpcodeStr()))
return false;
bool IsBooleanLHS = BinOp->getLHS()
@@ -91,16 +92,14 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
}
std::optional<bool> DummyFlag = false;
- IsBooleanLHS =
- IsBooleanLHS ||
- isBooleanBitwise(
- dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
- IsBooleanRHS =
- IsBooleanRHS ||
- isBooleanBitwise(
- dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
+ IsBooleanLHS = IsBooleanLHS ||
+ isBooleanBitwise(dyn_cast<BinaryOperator>(
+ BinOp->getLHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
+ IsBooleanRHS = IsBooleanRHS ||
+ isBooleanBitwise(dyn_cast<BinaryOperator>(
+ BinOp->getRHS()->IgnoreParenImpCasts()),
+ AC, DummyFlag);
if (IsBooleanLHS && IsBooleanRHS) {
RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
>From d0a3b18b2d8645aa38ba06e5cabc243ece4c25fc Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 22 Nov 2025 00:15:00 +0300
Subject: [PATCH 28/49] review
---
.../misc/BoolBitwiseOperationCheck.cpp | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 4fe8460d01eec..7b1a70cfb3885 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -67,16 +67,15 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
BinOp->getOpcodeStr()))
return false;
- bool IsBooleanLHS = BinOp->getLHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
- bool IsBooleanRHS = BinOp->getRHS()
- ->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
+ const auto isBooleanType = [&AC](const Expr *expr) -> bool {
+ return expr->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType();
+ };
+
+ bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
+ bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
if (IsBooleanLHS && IsBooleanRHS) {
RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
return true;
>From e33511632a9dcaedbbaf14499624cfc2e6bb1f72 Mon Sep 17 00:00:00 2001
From: Denis Mikhailov <denismikhaylov38 at gmail.com>
Date: Sat, 22 Nov 2025 00:53:02 +0300
Subject: [PATCH 29/49] Update BoolBitwiseOperationCheck.cpp
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 7b1a70cfb3885..2771f81e97283 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -29,7 +29,7 @@ static const DynTypedNode *ignoreParensTowardsTheRoot(const DynTypedNode *N,
}
static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
- TraversalKindScope RAII(*AC, TK_AsIs);
+ const TraversalKindScope RAII(*AC, TK_AsIs);
auto Parents = AC->getParents(*BinOp);
return llvm::any_of(Parents, [&](const DynTypedNode &Parent) {
@@ -67,15 +67,15 @@ static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
BinOp->getOpcodeStr()))
return false;
- const auto isBooleanType = [&AC](const Expr *expr) -> bool {
- return expr->IgnoreImpCasts()
+ const auto IsBooleanType = [&AC](const Expr *Expr) -> bool {
+ return Expr->IgnoreImpCasts()
->getType()
.getDesugaredType(*AC)
->isBooleanType();
};
- bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
- bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
+ bool IsBooleanLHS = IsBooleanType(BinOp->getLHS());
+ bool IsBooleanRHS = IsBooleanType(BinOp->getRHS());
if (IsBooleanLHS && IsBooleanRHS) {
RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
return true;
>From 6e09d72a7100ebfe5226b7a589aca7b316bb7a29 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sun, 28 Dec 2025 05:47:44 +0300
Subject: [PATCH 30/49] reimplement to use DynamicRecursiveASTVisitor
---
.../misc/BoolBitwiseOperationCheck.cpp | 74 +++++++++++++++----
.../misc/BoolBitwiseOperationCheck.h | 7 +-
2 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 2771f81e97283..e8b096754890d 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -7,11 +7,13 @@
//===----------------------------------------------------------------------===//
#include "BoolBitwiseOperationCheck.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include <array>
#include <optional>
#include <utility>
+#include <vector>
using namespace clang::ast_matchers;
@@ -261,30 +263,70 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
<< InsertBrace2;
}
-void BoolBitwiseOperationCheck::visitBinaryTreesNode(
- const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
- const clang::SourceManager &SM, clang::ASTContext &Ctx,
- std::optional<bool> &RootAssignsToBoolean) {
- if (!BinOp)
- return;
+namespace {
+class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
+ clang::tidy::misc::BoolBitwiseOperationCheck &Check;
+ const clang::SourceManager &SM;
+ clang::ASTContext &Ctx;
+ std::optional<bool> &RootAssignsToBoolean;
+ // Stack to track parent binary operators during traversal
+ std::vector<const clang::BinaryOperator *> ParentStack;
+
+public:
+ BinaryOperatorVisitor(clang::tidy::misc::BoolBitwiseOperationCheck &Check,
+ const clang::SourceManager &SM,
+ clang::ASTContext &Ctx,
+ std::optional<bool> &RootAssignsToBoolean)
+ : Check(Check), SM(SM), Ctx(Ctx),
+ RootAssignsToBoolean(RootAssignsToBoolean) {}
+
+ bool TraverseBinaryOperator(clang::BinaryOperator *BinOp) override {
+ if (!BinOp)
+ return true;
+
+ // Check if this BinOp is a direct child of the parent in the stack.
+ // If not, we skip processing it (don't add to stack).
+ if (!ParentStack.empty() && !(ParentStack.back()->getLHS()->IgnoreParenImpCasts() == BinOp || ParentStack.back()->getRHS()->IgnoreParenImpCasts() == BinOp)) {
+ return true;
+ }
- if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean))
- emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx);
+ // Push current binary operator as parent for children
+ ParentStack.push_back(BinOp);
+ // Traverse children
+ bool Result = clang::DynamicRecursiveASTVisitor::TraverseBinaryOperator(BinOp);
+ // Pop after traversal
+ ParentStack.pop_back();
+ return Result;
+ }
- visitBinaryTreesNode(
- dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp,
- SM, Ctx, RootAssignsToBoolean);
- visitBinaryTreesNode(
- dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp,
- SM, Ctx, RootAssignsToBoolean);
-}
+ bool VisitBinaryOperator(clang::BinaryOperator *BinOp) override {
+ if (!BinOp)
+ return true;
+
+ const clang::BinaryOperator *ParentBinOp =
+ ParentStack.size() < 2 ? nullptr : ParentStack[ParentStack.size() - 2];
+
+ if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean))
+ Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM,
+ Ctx);
+
+ return true;
+ }
+};
+} // namespace
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
+ if (!BinOpRoot)
+ return;
+
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
std::optional<bool> RootAssignsToBoolean = std::nullopt;
- visitBinaryTreesNode(BinOpRoot, nullptr, SM, Ctx, RootAssignsToBoolean);
+
+ BinaryOperatorVisitor Visitor(*this, SM, Ctx, RootAssignsToBoolean);
+ // TraverseStmt requires non-const pointer, but we're only reading
+ Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
}
} // namespace clang::tidy::misc
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index 3725e0b54ebc5..4a3b36a12302b 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -32,16 +32,11 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
return TK_IgnoreUnlessSpelledInSource;
}
-private:
void emitWarningAndChangeOperatorsIfPossible(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
const clang::SourceManager &SM, clang::ASTContext &Ctx);
- void visitBinaryTreesNode(const BinaryOperator *BinOp,
- const BinaryOperator *ParentBinOp,
- const clang::SourceManager &SM,
- clang::ASTContext &Ctx,
- std::optional<bool> &RootAssignsToBoolean);
+private:
bool UnsafeMode;
bool IgnoreMacros;
};
>From 754514f99c5849b8b8f8dbcb73688ef43373c6aa Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Mon, 29 Dec 2025 05:59:44 +0300
Subject: [PATCH 31/49] Simplify isBooleanBitwise
---
.../misc/BoolBitwiseOperationCheck.cpp | 90 +++++++++++++------
1 file changed, 61 insertions(+), 29 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index e8b096754890d..c89a956c184dd 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -60,52 +60,82 @@ static StringRef translate(StringRef Value) {
return {};
}
+static bool isBitwiseOperation(StringRef Value) {
+ return llvm::is_contained(llvm::make_first_range(OperatorsTransformation),
+ Value);
+}
+
+/// Checks if a binary operator is a bitwise operation that should be treated
+/// as a boolean operation (i.e., should use logical operators instead).
+///
+/// This function determines whether a bitwise operation (|, &, |=, &=, etc.)
+/// is being used in a boolean context, which typically indicates the case where
+/// logical operators (||, &&) should have been used instead.
+///
+/// \param BinOp The binary operator to check. Must not be null.
+/// \param AC The AST context for type checking and parent traversal.
+/// \param RootAssignsToBoolean An output parameter that tracks whether the
+/// root binary operator in the expression tree assigns to a boolean
+/// type. This is used to propagate the assignment context through
+/// nested binary operations. The value is set to true if any operation
+/// in the chain assigns to boolean, false if both operands are boolean
+/// but no assignment occurs, and remains unset if the operation is not
+/// boolean bitwise.
+///
+/// \returns true if the operation is a bitwise operation used in a boolean
+/// context (both operands are boolean, or it assigns to boolean),
+/// false otherwise.
static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
std::optional<bool> &RootAssignsToBoolean) {
if (!BinOp)
return false;
- if (!llvm::is_contained(llvm::make_first_range(OperatorsTransformation),
- BinOp->getOpcodeStr()))
+ if (!isBitwiseOperation(BinOp->getOpcodeStr()))
return false;
+ // Lambda to check if an expression is boolean type, either directly or
+ // recursively through nested binary operators. This handles cases like
+ // `(a | b) & c` where the LHS is itself a boolean bitwise operation.
const auto IsBooleanType = [&AC](const Expr *Expr) -> bool {
- return Expr->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType();
+ if (Expr->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(*AC)
+ ->isBooleanType())
+ return true;
+ std::optional<bool> DummyFlag = false;
+ return isBooleanBitwise(dyn_cast<BinaryOperator>(
+ Expr->IgnoreParenImpCasts()),
+ AC, DummyFlag);
};
- bool IsBooleanLHS = IsBooleanType(BinOp->getLHS());
- bool IsBooleanRHS = IsBooleanType(BinOp->getRHS());
+ const bool IsBooleanLHS = IsBooleanType(BinOp->getLHS());
+ const bool IsBooleanRHS = IsBooleanType(BinOp->getRHS());
+
+ // If both operands are boolean, this is definitely a boolean bitwise
+ // operation. Preserve the existing RootAssignsToBoolean value if set,
+ // otherwise set it to false (no assignment context).
if (IsBooleanLHS && IsBooleanRHS) {
RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
return true;
}
- if (((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, AC)) ||
- RootAssignsToBoolean.value_or(false)) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
- return true;
- }
- if (BinOp->isCompoundAssignmentOp() && IsBooleanLHS) {
+
+ // Check if this operation assigns to a boolean type. This includes:
+ // 1. Operations where at least one operand is boolean and the result is
+ // assigned to boolean (e.g., `bool x = a | b` where a is int and b is boolean)
+ // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where y is int and x is boolean)
+ const bool IsRelevantAssignmentToBoolean =
+ ((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, AC)) ||
+ (BinOp->isCompoundAssignmentOp() && IsBooleanLHS);
+
+ // If this operation assigns to boolean, or if we've already determined that
+ // the root assigns to boolean (from a nested operation), then this is a
+ // boolean bitwise operation. Set RootAssignsToBoolean to true to propagate
+ // this information up the call stack.
+ if (IsRelevantAssignmentToBoolean || RootAssignsToBoolean.value_or(false)) {
RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
return true;
}
- std::optional<bool> DummyFlag = false;
- IsBooleanLHS = IsBooleanLHS ||
- isBooleanBitwise(dyn_cast<BinaryOperator>(
- BinOp->getLHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
- IsBooleanRHS = IsBooleanRHS ||
- isBooleanBitwise(dyn_cast<BinaryOperator>(
- BinOp->getRHS()->IgnoreParenImpCasts()),
- AC, DummyFlag);
-
- if (IsBooleanLHS && IsBooleanRHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
- return true;
- }
return false;
}
@@ -306,9 +336,11 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
const clang::BinaryOperator *ParentBinOp =
ParentStack.size() < 2 ? nullptr : ParentStack[ParentStack.size() - 2];
- if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean))
+ if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean)) {
+ assert(RootAssignsToBoolean.has_value());
Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM,
Ctx);
+ }
return true;
}
>From 461da1bbb1572832a60327333343a836689291b0 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Mon, 29 Dec 2025 21:07:46 +0300
Subject: [PATCH 32/49] refactoring
---
.../misc/BoolBitwiseOperationCheck.cpp | 207 ++++++++++--------
1 file changed, 114 insertions(+), 93 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index c89a956c184dd..f3292989ecefc 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -65,80 +65,6 @@ static bool isBitwiseOperation(StringRef Value) {
Value);
}
-/// Checks if a binary operator is a bitwise operation that should be treated
-/// as a boolean operation (i.e., should use logical operators instead).
-///
-/// This function determines whether a bitwise operation (|, &, |=, &=, etc.)
-/// is being used in a boolean context, which typically indicates the case where
-/// logical operators (||, &&) should have been used instead.
-///
-/// \param BinOp The binary operator to check. Must not be null.
-/// \param AC The AST context for type checking and parent traversal.
-/// \param RootAssignsToBoolean An output parameter that tracks whether the
-/// root binary operator in the expression tree assigns to a boolean
-/// type. This is used to propagate the assignment context through
-/// nested binary operations. The value is set to true if any operation
-/// in the chain assigns to boolean, false if both operands are boolean
-/// but no assignment occurs, and remains unset if the operation is not
-/// boolean bitwise.
-///
-/// \returns true if the operation is a bitwise operation used in a boolean
-/// context (both operands are boolean, or it assigns to boolean),
-/// false otherwise.
-static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC,
- std::optional<bool> &RootAssignsToBoolean) {
- if (!BinOp)
- return false;
-
- if (!isBitwiseOperation(BinOp->getOpcodeStr()))
- return false;
-
- // Lambda to check if an expression is boolean type, either directly or
- // recursively through nested binary operators. This handles cases like
- // `(a | b) & c` where the LHS is itself a boolean bitwise operation.
- const auto IsBooleanType = [&AC](const Expr *Expr) -> bool {
- if (Expr->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(*AC)
- ->isBooleanType())
- return true;
- std::optional<bool> DummyFlag = false;
- return isBooleanBitwise(dyn_cast<BinaryOperator>(
- Expr->IgnoreParenImpCasts()),
- AC, DummyFlag);
- };
-
- const bool IsBooleanLHS = IsBooleanType(BinOp->getLHS());
- const bool IsBooleanRHS = IsBooleanType(BinOp->getRHS());
-
- // If both operands are boolean, this is definitely a boolean bitwise
- // operation. Preserve the existing RootAssignsToBoolean value if set,
- // otherwise set it to false (no assignment context).
- if (IsBooleanLHS && IsBooleanRHS) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(false);
- return true;
- }
-
- // Check if this operation assigns to a boolean type. This includes:
- // 1. Operations where at least one operand is boolean and the result is
- // assigned to boolean (e.g., `bool x = a | b` where a is int and b is boolean)
- // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where y is int and x is boolean)
- const bool IsRelevantAssignmentToBoolean =
- ((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, AC)) ||
- (BinOp->isCompoundAssignmentOp() && IsBooleanLHS);
-
- // If this operation assigns to boolean, or if we've already determined that
- // the root assigns to boolean (from a nested operation), then this is a
- // boolean bitwise operation. Set RootAssignsToBoolean to true to propagate
- // this information up the call stack.
- if (IsRelevantAssignmentToBoolean || RootAssignsToBoolean.value_or(false)) {
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(true);
- return true;
- }
-
- return false;
-}
-
static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
assert(BinOp->isCompoundAssignmentOp());
const Expr *LHS = BinOp->getLHS()->IgnoreImpCasts();
@@ -298,34 +224,131 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
clang::tidy::misc::BoolBitwiseOperationCheck &Check;
const clang::SourceManager &SM;
clang::ASTContext &Ctx;
- std::optional<bool> &RootAssignsToBoolean;
+ /// Three-state boolean to track whether the root binary operator in the
+ /// expression tree assigns to a boolean type and one of operands is boolean.
+ /// This is used to propagate the assignment context through nested binary
+ /// operations.
+ std::optional<bool> RootAssignsToBoolean;
// Stack to track parent binary operators during traversal
std::vector<const clang::BinaryOperator *> ParentStack;
+ void setRootAssignsToBoolean(bool Value, bool IsRoot) {
+ if (!IsRoot)
+ return;
+ RootAssignsToBoolean = RootAssignsToBoolean.value_or(Value);
+ }
+
+ /// Checks if an expression is boolean type, either directly or recursively
+ /// through nested binary operators. This handles cases like `(a | b) & c`
+ /// where the LHS is itself a boolean bitwise operation.
+ ///
+ /// \param Expr The expression to check.
+ /// \returns true if the expression is boolean type or is a boolean bitwise
+ /// operation, false otherwise.
+ bool isBooleanType(const clang::Expr *Expr) {
+ if (Expr->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(Ctx)
+ ->isBooleanType())
+ return true;
+ return isBooleanBitwise(
+ dyn_cast<clang::BinaryOperator>(Expr->IgnoreParenImpCasts()),
+ /*IsRoot=*/false);
+ }
+
+ /// Checks if a binary operator is a bitwise operation that should be treated
+ /// as a boolean operation (i.e., should use logical operators instead).
+ ///
+ /// This function determines whether a bitwise operation (|, &, |=, &=, etc.)
+ /// is being used in a boolean context, which typically indicates the case
+ /// where logical operators (||, &&) should have been used instead.
+ ///
+ /// \param BinOp The binary operator to check. Must not be null.
+ /// \param RootAssignsToBoolean An output parameter that
+ ///
+ /// \returns true if the operation is a bitwise operation used in a boolean
+ /// context (both operands are boolean, or it assigns to boolean),
+ /// false otherwise.
+ bool isBooleanBitwise(const clang::BinaryOperator *BinOp,
+ bool IsRoot = true) {
+ if (!BinOp)
+ return false;
+
+ if (!isBitwiseOperation(BinOp->getOpcodeStr()))
+ return false;
+
+ assert(!IsRoot || RootAssignsToBoolean == std::nullopt);
+
+ // If we've already determined that the root assigns to boolean (from a
+ // nested operation), then this is a boolean bitwise operation.
+ if (RootAssignsToBoolean.value_or(false))
+ return true;
+
+ const bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
+ const bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
+
+ // If both operands are boolean, this is definitely a boolean bitwise
+ // operation. Preserve the existing RootAssignsToBoolean value if set,
+ // otherwise set it to false (no assignment context).
+ if (IsBooleanLHS && IsBooleanRHS) {
+ setRootAssignsToBoolean(false, IsRoot);
+ return true;
+ }
+
+ // Check if this operation assigns to a boolean type. This includes:
+ // 1. Operations where at least one operand is boolean and the result is
+ // assigned to boolean (e.g., `bool x = a | b` where a is int and b is
+ // boolean)
+ // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where y
+ // is int and x is boolean)
+ const bool IsRelevantAssignmentToBoolean =
+ ((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, &Ctx)) ||
+ (IsBooleanLHS && BinOp->isCompoundAssignmentOp());
+
+ // If this operation assigns to boolean, then this is a boolean bitwise
+ // operation. Set RootAssignsToBoolean to true to propagate this information
+ // up the call stack.
+ if (IsRelevantAssignmentToBoolean) {
+ setRootAssignsToBoolean(true, IsRoot);
+ return true;
+ }
+
+ return false;
+ }
+
+ /// Checks if BinOp is a direct child of the parent binary operator in the
+ /// stack (ignoring parentheses and implicit casts).
+ bool isDirectChildOfParent(const clang::BinaryOperator *BinOp) const {
+ if (ParentStack.empty())
+ return true;
+
+ const clang::BinaryOperator *Parent = ParentStack.back();
+ const std::array<const Expr *, 2> ParentOperands = {
+ Parent->getLHS(), Parent->getRHS()};
+
+ return llvm::any_of(ParentOperands, [&](const Expr *E) {
+ return E->IgnoreParenImpCasts() == BinOp;
+ });
+ }
+
public:
BinaryOperatorVisitor(clang::tidy::misc::BoolBitwiseOperationCheck &Check,
- const clang::SourceManager &SM,
- clang::ASTContext &Ctx,
- std::optional<bool> &RootAssignsToBoolean)
- : Check(Check), SM(SM), Ctx(Ctx),
- RootAssignsToBoolean(RootAssignsToBoolean) {}
+ const clang::SourceManager &SM, clang::ASTContext &Ctx)
+ : Check(Check), SM(SM), Ctx(Ctx) {}
bool TraverseBinaryOperator(clang::BinaryOperator *BinOp) override {
if (!BinOp)
return true;
- // Check if this BinOp is a direct child of the parent in the stack.
- // If not, we skip processing it (don't add to stack).
- if (!ParentStack.empty() && !(ParentStack.back()->getLHS()->IgnoreParenImpCasts() == BinOp || ParentStack.back()->getRHS()->IgnoreParenImpCasts() == BinOp)) {
+ if (!isDirectChildOfParent(BinOp))
return true;
- }
- // Push current binary operator as parent for children
+ // Track this binary operator as a parent for its children.
ParentStack.push_back(BinOp);
- // Traverse children
- bool Result = clang::DynamicRecursiveASTVisitor::TraverseBinaryOperator(BinOp);
- // Pop after traversal
+ const bool Result =
+ clang::DynamicRecursiveASTVisitor::TraverseBinaryOperator(BinOp);
ParentStack.pop_back();
+
return Result;
}
@@ -336,7 +359,7 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
const clang::BinaryOperator *ParentBinOp =
ParentStack.size() < 2 ? nullptr : ParentStack[ParentStack.size() - 2];
- if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean)) {
+ if (isBooleanBitwise(BinOp)) {
assert(RootAssignsToBoolean.has_value());
Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM,
Ctx);
@@ -349,14 +372,12 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
- if (!BinOpRoot)
- return;
+ assert(BinOpRoot);
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
- std::optional<bool> RootAssignsToBoolean = std::nullopt;
- BinaryOperatorVisitor Visitor(*this, SM, Ctx, RootAssignsToBoolean);
+ BinaryOperatorVisitor Visitor(*this, SM, Ctx);
// TraverseStmt requires non-const pointer, but we're only reading
Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
}
>From de69f76bf7f8044fe0c65bb960ca7c973a28dbc1 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Wed, 31 Dec 2025 00:11:08 +0300
Subject: [PATCH 33/49] get rid of RootAssignsToBoolean
---
.../misc/BoolBitwiseOperationCheck.cpp | 92 +++++++------------
...itwise-operation-not-only-bool-operand.cpp | 7 +-
2 files changed, 38 insertions(+), 61 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index f3292989ecefc..6ddd2e3f87fad 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -224,20 +224,9 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
clang::tidy::misc::BoolBitwiseOperationCheck &Check;
const clang::SourceManager &SM;
clang::ASTContext &Ctx;
- /// Three-state boolean to track whether the root binary operator in the
- /// expression tree assigns to a boolean type and one of operands is boolean.
- /// This is used to propagate the assignment context through nested binary
- /// operations.
- std::optional<bool> RootAssignsToBoolean;
// Stack to track parent binary operators during traversal
std::vector<const clang::BinaryOperator *> ParentStack;
- void setRootAssignsToBoolean(bool Value, bool IsRoot) {
- if (!IsRoot)
- return;
- RootAssignsToBoolean = RootAssignsToBoolean.value_or(Value);
- }
-
/// Checks if an expression is boolean type, either directly or recursively
/// through nested binary operators. This handles cases like `(a | b) & c`
/// where the LHS is itself a boolean bitwise operation.
@@ -256,6 +245,26 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
/*IsRoot=*/false);
}
+ /// Checks if BinOp is a direct child of the parent binary operator in the
+ /// stack (ignoring parentheses and implicit casts).
+ bool isDirectChildOfParent(const clang::BinaryOperator *BinOp) const {
+ if (ParentStack.empty())
+ return true;
+
+ const clang::BinaryOperator *Parent = ParentStack.back();
+ const std::array<const Expr *, 2> ParentOperands = {
+ Parent->getLHS(), Parent->getRHS()};
+
+ return llvm::any_of(ParentOperands, [&](const Expr *E) {
+ return E->IgnoreParenImpCasts() == BinOp;
+ });
+ }
+
+public:
+ BinaryOperatorVisitor(clang::tidy::misc::BoolBitwiseOperationCheck &Check,
+ const clang::SourceManager &SM, clang::ASTContext &Ctx)
+ : Check(Check), SM(SM), Ctx(Ctx) {}
+
/// Checks if a binary operator is a bitwise operation that should be treated
/// as a boolean operation (i.e., should use logical operators instead).
///
@@ -264,7 +273,6 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
/// where logical operators (||, &&) should have been used instead.
///
/// \param BinOp The binary operator to check. Must not be null.
- /// \param RootAssignsToBoolean An output parameter that
///
/// \returns true if the operation is a bitwise operation used in a boolean
/// context (both operands are boolean, or it assigns to boolean),
@@ -274,27 +282,9 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
if (!BinOp)
return false;
- if (!isBitwiseOperation(BinOp->getOpcodeStr()))
- return false;
-
- assert(!IsRoot || RootAssignsToBoolean == std::nullopt);
-
- // If we've already determined that the root assigns to boolean (from a
- // nested operation), then this is a boolean bitwise operation.
- if (RootAssignsToBoolean.value_or(false))
- return true;
-
const bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
const bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
- // If both operands are boolean, this is definitely a boolean bitwise
- // operation. Preserve the existing RootAssignsToBoolean value if set,
- // otherwise set it to false (no assignment context).
- if (IsBooleanLHS && IsBooleanRHS) {
- setRootAssignsToBoolean(false, IsRoot);
- return true;
- }
-
// Check if this operation assigns to a boolean type. This includes:
// 1. Operations where at least one operand is boolean and the result is
// assigned to boolean (e.g., `bool x = a | b` where a is int and b is
@@ -309,33 +299,15 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
// operation. Set RootAssignsToBoolean to true to propagate this information
// up the call stack.
if (IsRelevantAssignmentToBoolean) {
- setRootAssignsToBoolean(true, IsRoot);
return true;
}
- return false;
- }
-
- /// Checks if BinOp is a direct child of the parent binary operator in the
- /// stack (ignoring parentheses and implicit casts).
- bool isDirectChildOfParent(const clang::BinaryOperator *BinOp) const {
- if (ParentStack.empty())
- return true;
-
- const clang::BinaryOperator *Parent = ParentStack.back();
- const std::array<const Expr *, 2> ParentOperands = {
- Parent->getLHS(), Parent->getRHS()};
-
- return llvm::any_of(ParentOperands, [&](const Expr *E) {
- return E->IgnoreParenImpCasts() == BinOp;
- });
+ // If both operands are boolean, this is definitely a boolean bitwise
+ // operation. Preserve the existing RootAssignsToBoolean value if set,
+ // otherwise set it to false (no assignment context).
+ return (IsBooleanLHS && IsBooleanRHS);
}
-public:
- BinaryOperatorVisitor(clang::tidy::misc::BoolBitwiseOperationCheck &Check,
- const clang::SourceManager &SM, clang::ASTContext &Ctx)
- : Check(Check), SM(SM), Ctx(Ctx) {}
-
bool TraverseBinaryOperator(clang::BinaryOperator *BinOp) override {
if (!BinOp)
return true;
@@ -356,14 +328,14 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
if (!BinOp)
return true;
+ if (!isBitwiseOperation(BinOp->getOpcodeStr()))
+ return true;
+
const clang::BinaryOperator *ParentBinOp =
ParentStack.size() < 2 ? nullptr : ParentStack[ParentStack.size() - 2];
- if (isBooleanBitwise(BinOp)) {
- assert(RootAssignsToBoolean.has_value());
- Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM,
- Ctx);
- }
+ Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM,
+ Ctx);
return true;
}
@@ -378,8 +350,10 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
ASTContext &Ctx = *Result.Context;
BinaryOperatorVisitor Visitor(*this, SM, Ctx);
- // TraverseStmt requires non-const pointer, but we're only reading
- Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
+ if (Visitor.isBooleanBitwise(BinOpRoot)) {
+ // TraverseStmt requires non-const pointer, but we're only reading
+ Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
+ }
}
} // namespace clang::tidy::misc
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index f93297a42f686..c3b6744c1cb14 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -2,15 +2,18 @@
// The case is taken from the real code in clang/lib/APINotes/APINotesWriter.cpp
+void take(bool value) {}
+void take_int(int value) {}
+
void general(unsigned flags, bool value) {
(flags << 1) | value;
flags = (flags << 1) | value;
flags = (flags << 1) | (flags << 2) | value;
flags = (flags << 1) | (flags << 2) | (flags << 4) | value;
+ take_int((flags << 1) | value);
+ take_int((flags << 1) | (flags << 2) | value);
}
-void take(bool value) {}
-
// FIXME: implement `template<bool bb=true|1>` cases
void assign_to_boolean(unsigned flags, bool value) {
>From dee0b3681832c0924def7ef1b8f4a867b666b3b8 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Mon, 5 Jan 2026 00:52:38 +0300
Subject: [PATCH 34/49] narrow the matching
---
.../misc/BoolBitwiseOperationCheck.cpp | 26 +++++++++++--------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 6ddd2e3f87fad..663031be9c1a0 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -85,9 +85,10 @@ void BoolBitwiseOperationCheck::storeOptions(
void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- binaryOperator(unless(isExpansionInSystemHeader()),
- unless(hasParent(binaryOperator())) // ignoring parenExpr
- )
+ binaryOperator(unless(hasParent(binaryOperator(hasAnyOperatorName(
+ "|", "&", "|=", "&=")))), // ignoring parenExpr
+ hasAnyOperatorName("|", "&", "|=", "&="),
+ optionally(hasParent(binaryOperator().bind("p"))))
.bind("binOpRoot"),
this);
}
@@ -224,6 +225,7 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
clang::tidy::misc::BoolBitwiseOperationCheck &Check;
const clang::SourceManager &SM;
clang::ASTContext &Ctx;
+ const clang::BinaryOperator *const ParentRoot;
// Stack to track parent binary operators during traversal
std::vector<const clang::BinaryOperator *> ParentStack;
@@ -252,8 +254,8 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
return true;
const clang::BinaryOperator *Parent = ParentStack.back();
- const std::array<const Expr *, 2> ParentOperands = {
- Parent->getLHS(), Parent->getRHS()};
+ const std::array<const Expr *, 2> ParentOperands = {Parent->getLHS(),
+ Parent->getRHS()};
return llvm::any_of(ParentOperands, [&](const Expr *E) {
return E->IgnoreParenImpCasts() == BinOp;
@@ -262,8 +264,9 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
public:
BinaryOperatorVisitor(clang::tidy::misc::BoolBitwiseOperationCheck &Check,
- const clang::SourceManager &SM, clang::ASTContext &Ctx)
- : Check(Check), SM(SM), Ctx(Ctx) {}
+ const clang::SourceManager &SM, clang::ASTContext &Ctx,
+ const clang::BinaryOperator *ParentRoot)
+ : Check(Check), SM(SM), Ctx(Ctx), ParentRoot(ParentRoot) {}
/// Checks if a binary operator is a bitwise operation that should be treated
/// as a boolean operation (i.e., should use logical operators instead).
@@ -332,10 +335,10 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
return true;
const clang::BinaryOperator *ParentBinOp =
- ParentStack.size() < 2 ? nullptr : ParentStack[ParentStack.size() - 2];
+ ParentStack.size() < 2 ? ParentRoot
+ : ParentStack[ParentStack.size() - 2];
- Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM,
- Ctx);
+ Check.emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx);
return true;
}
@@ -344,12 +347,13 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
+ const auto *ParentRoot = Result.Nodes.getNodeAs<BinaryOperator>("p");
assert(BinOpRoot);
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
- BinaryOperatorVisitor Visitor(*this, SM, Ctx);
+ BinaryOperatorVisitor Visitor(*this, SM, Ctx, ParentRoot);
if (Visitor.isBooleanBitwise(BinOpRoot)) {
// TraverseStmt requires non-const pointer, but we're only reading
Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
>From f38960cb7661a6ec230d9fcb6f41216e69c634ca Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Mon, 5 Jan 2026 01:16:15 +0300
Subject: [PATCH 35/49] get rid of assignsToBoolean
---
.../misc/BoolBitwiseOperationCheck.cpp | 78 ++++++++-----------
.../misc/BoolBitwiseOperationCheck.h | 3 -
2 files changed, 33 insertions(+), 48 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 663031be9c1a0..138ec02406124 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -19,28 +19,6 @@ using namespace clang::ast_matchers;
namespace clang::tidy::misc {
-static const DynTypedNode *ignoreParensTowardsTheRoot(const DynTypedNode *N,
- ASTContext *AC) {
- if (const auto *S = N->get<Stmt>(); isa_and_nonnull<ParenExpr>(S)) {
- auto Parents = AC->getParents(*S);
- // FIXME: do we need to consider all `Parents` ?
- if (!Parents.empty())
- return ignoreParensTowardsTheRoot(&Parents[0], AC);
- }
- return N;
-}
-
-static bool assignsToBoolean(const BinaryOperator *BinOp, ASTContext *AC) {
- const TraversalKindScope RAII(*AC, TK_AsIs);
- auto Parents = AC->getParents(*BinOp);
-
- return llvm::any_of(Parents, [&](const DynTypedNode &Parent) {
- const auto *S = ignoreParensTowardsTheRoot(&Parent, AC)->get<Stmt>();
- const auto *ICE = dyn_cast_if_present<ImplicitCastExpr>(S);
- return ICE ? ICE->getType().getDesugaredType(*AC)->isBooleanType() : false;
- });
-}
-
static constexpr std::array<std::pair<StringRef, StringRef>, 8U>
OperatorsTransformation{{{"|", "||"},
{"|=", "||"},
@@ -84,13 +62,16 @@ void BoolBitwiseOperationCheck::storeOptions(
}
void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(
+ const auto BinOpRoot = traverse(
+ TK_IgnoreUnlessSpelledInSource,
binaryOperator(unless(hasParent(binaryOperator(hasAnyOperatorName(
"|", "&", "|=", "&=")))), // ignoring parenExpr
hasAnyOperatorName("|", "&", "|=", "&="),
optionally(hasParent(binaryOperator().bind("p"))))
- .bind("binOpRoot"),
- this);
+ .bind("binOpRoot"));
+ const auto BooleanICE =
+ implicitCastExpr(hasType(booleanType()), has(BinOpRoot)).bind("ice");
+ Finder->addMatcher(expr(anyOf(BooleanICE, BinOpRoot)), this);
}
void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
@@ -281,34 +262,39 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
/// context (both operands are boolean, or it assigns to boolean),
/// false otherwise.
bool isBooleanBitwise(const clang::BinaryOperator *BinOp,
- bool IsRoot = true) {
+ bool AssignsToBoolean, bool IsRoot = true) {
if (!BinOp)
return false;
const bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
const bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
- // Check if this operation assigns to a boolean type. This includes:
- // 1. Operations where at least one operand is boolean and the result is
- // assigned to boolean (e.g., `bool x = a | b` where a is int and b is
- // boolean)
- // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where y
- // is int and x is boolean)
- const bool IsRelevantAssignmentToBoolean =
- ((IsBooleanLHS || IsBooleanRHS) && assignsToBoolean(BinOp, &Ctx)) ||
- (IsBooleanLHS && BinOp->isCompoundAssignmentOp());
-
- // If this operation assigns to boolean, then this is a boolean bitwise
- // operation. Set RootAssignsToBoolean to true to propagate this information
- // up the call stack.
- if (IsRelevantAssignmentToBoolean) {
- return true;
- }
-
// If both operands are boolean, this is definitely a boolean bitwise
// operation. Preserve the existing RootAssignsToBoolean value if set,
// otherwise set it to false (no assignment context).
- return (IsBooleanLHS && IsBooleanRHS);
+ if (IsBooleanLHS && IsBooleanRHS)
+ return true;
+
+ if (IsRoot) {
+ // Check if this operation assigns to a boolean type. This includes:
+ // 1. Operations where at least one operand is boolean and the result is
+ // assigned to boolean (e.g., `bool x = a | b` where a is int and b is
+ // boolean)
+ // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where
+ // y is int and x is boolean)
+ const bool IsRelevantAssignmentToBoolean =
+ ((IsBooleanLHS || IsBooleanRHS) && AssignsToBoolean) ||
+ (IsBooleanLHS && BinOp->isCompoundAssignmentOp());
+
+ // If this operation assigns to boolean, then this is a boolean bitwise
+ // operation. Set RootAssignsToBoolean to true to propagate this
+ // information up the call stack.
+ if (IsRelevantAssignmentToBoolean) {
+ return true;
+ }
+ }
+
+ return false;
}
bool TraverseBinaryOperator(clang::BinaryOperator *BinOp) override {
@@ -348,13 +334,15 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
const auto *ParentRoot = Result.Nodes.getNodeAs<BinaryOperator>("p");
+ const bool AssignsToBoolean =
+ Result.Nodes.getMap().find("ice") != Result.Nodes.getMap().end();
assert(BinOpRoot);
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
BinaryOperatorVisitor Visitor(*this, SM, Ctx, ParentRoot);
- if (Visitor.isBooleanBitwise(BinOpRoot)) {
+ if (Visitor.isBooleanBitwise(BinOpRoot, AssignsToBoolean)) {
// TraverseStmt requires non-const pointer, but we're only reading
Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
}
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index 4a3b36a12302b..b3977a3d41824 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -28,9 +28,6 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus || LangOpts.C99;
}
- std::optional<TraversalKind> getCheckTraversalKind() const override {
- return TK_IgnoreUnlessSpelledInSource;
- }
void emitWarningAndChangeOperatorsIfPossible(
const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
>From 0d74db41a6fd3f820f9751d509b9a0925dfdbec8 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 16 Jan 2026 18:06:45 +0300
Subject: [PATCH 36/49] Fix for false positive
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 3 +++
.../misc/bool-bitwise-operation-nontraditional.cpp | 9 +++++++++
.../clang-tidy/checkers/misc/bool-bitwise-operation.cpp | 9 +++++++++
3 files changed, 21 insertions(+)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 138ec02406124..a81950204700a 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -266,6 +266,9 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
if (!BinOp)
return false;
+ if (!isBitwiseOperation(BinOp->getOpcodeStr()))
+ return false;
+
const bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
const bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index c6a8a7810c93b..4a0581b6f194a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -409,3 +409,12 @@ int bad_in_template_lambda_captured(T a, T b) {
}
int dummy = bad_in_template(true, false) + bad_in_template_lambda_captured(false, true);
+
+void test_bug_isBooleanBitwise_recursive_classification() {
+ bool a = true, b = false, c = true;
+ int i = 0;
+
+ bool result1 = (a + b) bitor i;
+
+ bool result2 = (a * b + c) bitor i;
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 6487026b07583..2c30de717d41e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -407,3 +407,12 @@ int bad_in_template_lambda_captured(T a, T b) {
}
int dummy = bad_in_template(true, false) + bad_in_template_lambda_captured(false, true);
+
+void test_bug_isBooleanBitwise_recursive_classification() {
+ bool a = true, b = false, c = true;
+ int i = 0;
+
+ bool result1 = (a + b) | i;
+
+ bool result2 = (a * b + c) | i;
+}
>From 09937d819bb1c047f410fb7c2d740316d889bcb5 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 16 Jan 2026 19:32:47 +0300
Subject: [PATCH 37/49] refactoring
---
.../misc/BoolBitwiseOperationCheck.cpp | 91 ++++++++++---------
1 file changed, 50 insertions(+), 41 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index a81950204700a..efacbace7ccf1 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -49,6 +49,33 @@ static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
return isa<DeclRefExpr, MemberExpr>(LHS) ? LHS : nullptr;
}
+/// Checks if all leaf nodes in an expression satisfy a given condition. This
+/// handles cases like `(a | b) & c` where we need to check that a, b, and c
+/// all satisfy the condition.
+///
+/// \param Expr The expression to check.
+/// \param Condition A function that checks if an expression satisfies the
+/// desired condition.
+/// \returns true if all leaf nodes satisfy the condition, false otherwise.
+template <typename F>
+static bool allLeavesSatisfy(const clang::Expr *Expr, const F& Condition) {
+ // For leaf nodes, check if the condition is satisfied
+ if (Condition(Expr))
+ return true;
+
+ Expr = Expr->IgnoreParenImpCasts();
+
+ // If it's a binary operator, recursively check both operands
+ if (const auto *BinOp = dyn_cast<clang::BinaryOperator>(Expr)) {
+ if (!isBitwiseOperation(BinOp->getOpcodeStr()))
+ return false;
+ return allLeavesSatisfy(BinOp->getLHS(), Condition) &&
+ allLeavesSatisfy(BinOp->getRHS(), Condition);
+ }
+
+ return false;
+}
+
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
@@ -210,24 +237,6 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
// Stack to track parent binary operators during traversal
std::vector<const clang::BinaryOperator *> ParentStack;
- /// Checks if an expression is boolean type, either directly or recursively
- /// through nested binary operators. This handles cases like `(a | b) & c`
- /// where the LHS is itself a boolean bitwise operation.
- ///
- /// \param Expr The expression to check.
- /// \returns true if the expression is boolean type or is a boolean bitwise
- /// operation, false otherwise.
- bool isBooleanType(const clang::Expr *Expr) {
- if (Expr->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(Ctx)
- ->isBooleanType())
- return true;
- return isBooleanBitwise(
- dyn_cast<clang::BinaryOperator>(Expr->IgnoreParenImpCasts()),
- /*IsRoot=*/false);
- }
-
/// Checks if BinOp is a direct child of the parent binary operator in the
/// stack (ignoring parentheses and implicit casts).
bool isDirectChildOfParent(const clang::BinaryOperator *BinOp) const {
@@ -262,15 +271,21 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
/// context (both operands are boolean, or it assigns to boolean),
/// false otherwise.
bool isBooleanBitwise(const clang::BinaryOperator *BinOp,
- bool AssignsToBoolean, bool IsRoot = true) {
+ bool AssignsToBoolean) {
if (!BinOp)
return false;
if (!isBitwiseOperation(BinOp->getOpcodeStr()))
return false;
- const bool IsBooleanLHS = isBooleanType(BinOp->getLHS());
- const bool IsBooleanRHS = isBooleanType(BinOp->getRHS());
+ auto IsBooleanType = [&](const clang::Expr *E) {
+ return E->IgnoreImpCasts()
+ ->getType()
+ .getDesugaredType(Ctx)
+ ->isBooleanType();
+ };
+ const bool IsBooleanLHS = allLeavesSatisfy(BinOp->getLHS(), IsBooleanType);
+ const bool IsBooleanRHS = allLeavesSatisfy(BinOp->getRHS(), IsBooleanType);
// If both operands are boolean, this is definitely a boolean bitwise
// operation. Preserve the existing RootAssignsToBoolean value if set,
@@ -278,26 +293,20 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
if (IsBooleanLHS && IsBooleanRHS)
return true;
- if (IsRoot) {
- // Check if this operation assigns to a boolean type. This includes:
- // 1. Operations where at least one operand is boolean and the result is
- // assigned to boolean (e.g., `bool x = a | b` where a is int and b is
- // boolean)
- // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where
- // y is int and x is boolean)
- const bool IsRelevantAssignmentToBoolean =
- ((IsBooleanLHS || IsBooleanRHS) && AssignsToBoolean) ||
- (IsBooleanLHS && BinOp->isCompoundAssignmentOp());
-
- // If this operation assigns to boolean, then this is a boolean bitwise
- // operation. Set RootAssignsToBoolean to true to propagate this
- // information up the call stack.
- if (IsRelevantAssignmentToBoolean) {
- return true;
- }
- }
-
- return false;
+ // Check if this operation assigns to a boolean type. This includes:
+ // 1. Operations where at least one operand is boolean and the result is
+ // assigned to boolean (e.g., `bool x = a | b` where a is int and b is
+ // boolean)
+ // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where
+ // y is int and x is boolean)
+ const bool IsRelevantAssignmentToBoolean =
+ ((IsBooleanLHS || IsBooleanRHS) && AssignsToBoolean) ||
+ (IsBooleanLHS && BinOp->isCompoundAssignmentOp());
+
+ // If this operation assigns to boolean, then this is a boolean bitwise
+ // operation. Set RootAssignsToBoolean to true to propagate this
+ // information up the call stack.
+ return IsRelevantAssignmentToBoolean;
}
bool TraverseBinaryOperator(clang::BinaryOperator *BinOp) override {
>From 32ee87266db9e540880bca9e180d3917a5fe75ce Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Fri, 16 Jan 2026 20:19:14 +0300
Subject: [PATCH 38/49] get ride of isBooleanBitwise function
---
.../misc/BoolBitwiseOperationCheck.cpp | 127 ++++++++----------
1 file changed, 56 insertions(+), 71 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index efacbace7ccf1..bc69853f271b2 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -49,16 +49,16 @@ static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
return isa<DeclRefExpr, MemberExpr>(LHS) ? LHS : nullptr;
}
-/// Checks if all leaf nodes in an expression satisfy a given condition. This
+/// Checks if all leaf nodes in an bitwise expression satisfy a given condition. This
/// handles cases like `(a | b) & c` where we need to check that a, b, and c
/// all satisfy the condition.
///
-/// \param Expr The expression to check.
-/// \param Condition A function that checks if an expression satisfies the
+/// \param Expr The bitwise expression to check.
+/// \param Condition A function that checks if an leaf node satisfies the
/// desired condition.
/// \returns true if all leaf nodes satisfy the condition, false otherwise.
template <typename F>
-static bool allLeavesSatisfy(const clang::Expr *Expr, const F& Condition) {
+static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr, const F& Condition) {
// For leaf nodes, check if the condition is satisfied
if (Condition(Expr))
return true;
@@ -69,13 +69,26 @@ static bool allLeavesSatisfy(const clang::Expr *Expr, const F& Condition) {
if (const auto *BinOp = dyn_cast<clang::BinaryOperator>(Expr)) {
if (!isBitwiseOperation(BinOp->getOpcodeStr()))
return false;
- return allLeavesSatisfy(BinOp->getLHS(), Condition) &&
- allLeavesSatisfy(BinOp->getRHS(), Condition);
+ return allLeavesOfBitwiseSatisfy(BinOp->getLHS(), Condition) &&
+ allLeavesOfBitwiseSatisfy(BinOp->getRHS(), Condition);
}
return false;
}
+/// Custom matcher that checks if all leaf nodes in an bitwise expression satisfy
+/// the given inner matcher condition. This uses allLeavesOfBitwiseSatisfy to recursively
+///
+/// Example usage:
+/// expr(hasAllLeavesOfBitwiseSatisfying(hasType(booleanType())))
+AST_MATCHER_P(Expr, hasAllLeavesOfBitwiseSatisfying,
+ ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+ auto Condition = [&](const clang::Expr *E) -> bool {
+ return InnerMatcher.matches(*E, Finder, Builder);
+ };
+ return allLeavesOfBitwiseSatisfy(&Node, Condition);
+}
+
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
@@ -89,16 +102,43 @@ void BoolBitwiseOperationCheck::storeOptions(
}
void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
- const auto BinOpRoot = traverse(
+ // Matcher for checking if all leaves in an expression are boolean type
+ auto BooleanLeaves = hasAllLeavesOfBitwiseSatisfying(hasType(booleanType()));
+
+ auto BitwiseOps = hasAnyOperatorName("|", "&", "|=", "&=");
+ auto CompoundBitwiseOps = hasAnyOperatorName("|=", "&=");
+ auto NotNestedInBitwise = unless(hasParent(binaryOperator(BitwiseOps)));
+ auto OptionalParent = optionally(hasParent(binaryOperator().bind("p")));
+
+ // Conditions that make it a boolean bitwise operation without ICE context:
+ // 1. Both LHS and RHS have all boolean leaves
+ // 2. LHS has boolean leaves AND it's a compound assignment
+ auto BothBoolean = allOf(hasLHS(BooleanLeaves), hasRHS(BooleanLeaves));
+ auto CompoundWithBoolLHS = allOf(hasLHS(BooleanLeaves), CompoundBitwiseOps);
+ auto NoContextNeeded = anyOf(BothBoolean, CompoundWithBoolLHS);
+
+ // At least one boolean operand (needs ICE context to be considered boolean
+ // bitwise)
+ auto AtLeastOneBoolean = anyOf(hasLHS(BooleanLeaves), hasRHS(BooleanLeaves));
+
+ // Matcher for binop that doesn't need ICE context
+ auto BinOpNoContext = traverse(
+ TK_IgnoreUnlessSpelledInSource,
+ binaryOperator(NotNestedInBitwise, BitwiseOps, OptionalParent,
+ NoContextNeeded)
+ .bind("binOpRoot"));
+
+ // Matcher for binop that needs ICE context (at least one boolean operand,
+ // but not already covered by NoContextNeeded)
+ auto BinOpNeedsContext = traverse(
TK_IgnoreUnlessSpelledInSource,
- binaryOperator(unless(hasParent(binaryOperator(hasAnyOperatorName(
- "|", "&", "|=", "&=")))), // ignoring parenExpr
- hasAnyOperatorName("|", "&", "|=", "&="),
- optionally(hasParent(binaryOperator().bind("p"))))
+ binaryOperator(NotNestedInBitwise, BitwiseOps, OptionalParent,
+ AtLeastOneBoolean, unless(NoContextNeeded))
.bind("binOpRoot"));
- const auto BooleanICE =
- implicitCastExpr(hasType(booleanType()), has(BinOpRoot)).bind("ice");
- Finder->addMatcher(expr(anyOf(BooleanICE, BinOpRoot)), this);
+ auto BooleanICE =
+ implicitCastExpr(hasType(booleanType()), has(BinOpNeedsContext));
+
+ Finder->addMatcher(expr(anyOf(BooleanICE, BinOpNoContext)), this);
}
void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
@@ -258,57 +298,6 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
const clang::BinaryOperator *ParentRoot)
: Check(Check), SM(SM), Ctx(Ctx), ParentRoot(ParentRoot) {}
- /// Checks if a binary operator is a bitwise operation that should be treated
- /// as a boolean operation (i.e., should use logical operators instead).
- ///
- /// This function determines whether a bitwise operation (|, &, |=, &=, etc.)
- /// is being used in a boolean context, which typically indicates the case
- /// where logical operators (||, &&) should have been used instead.
- ///
- /// \param BinOp The binary operator to check. Must not be null.
- ///
- /// \returns true if the operation is a bitwise operation used in a boolean
- /// context (both operands are boolean, or it assigns to boolean),
- /// false otherwise.
- bool isBooleanBitwise(const clang::BinaryOperator *BinOp,
- bool AssignsToBoolean) {
- if (!BinOp)
- return false;
-
- if (!isBitwiseOperation(BinOp->getOpcodeStr()))
- return false;
-
- auto IsBooleanType = [&](const clang::Expr *E) {
- return E->IgnoreImpCasts()
- ->getType()
- .getDesugaredType(Ctx)
- ->isBooleanType();
- };
- const bool IsBooleanLHS = allLeavesSatisfy(BinOp->getLHS(), IsBooleanType);
- const bool IsBooleanRHS = allLeavesSatisfy(BinOp->getRHS(), IsBooleanType);
-
- // If both operands are boolean, this is definitely a boolean bitwise
- // operation. Preserve the existing RootAssignsToBoolean value if set,
- // otherwise set it to false (no assignment context).
- if (IsBooleanLHS && IsBooleanRHS)
- return true;
-
- // Check if this operation assigns to a boolean type. This includes:
- // 1. Operations where at least one operand is boolean and the result is
- // assigned to boolean (e.g., `bool x = a | b` where a is int and b is
- // boolean)
- // 2. Compound assignments where the LHS is boolean (e.g., `x |= y` where
- // y is int and x is boolean)
- const bool IsRelevantAssignmentToBoolean =
- ((IsBooleanLHS || IsBooleanRHS) && AssignsToBoolean) ||
- (IsBooleanLHS && BinOp->isCompoundAssignmentOp());
-
- // If this operation assigns to boolean, then this is a boolean bitwise
- // operation. Set RootAssignsToBoolean to true to propagate this
- // information up the call stack.
- return IsRelevantAssignmentToBoolean;
- }
-
bool TraverseBinaryOperator(clang::BinaryOperator *BinOp) override {
if (!BinOp)
return true;
@@ -346,18 +335,14 @@ class BinaryOperatorVisitor : public clang::DynamicRecursiveASTVisitor {
void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinOpRoot = Result.Nodes.getNodeAs<BinaryOperator>("binOpRoot");
const auto *ParentRoot = Result.Nodes.getNodeAs<BinaryOperator>("p");
- const bool AssignsToBoolean =
- Result.Nodes.getMap().find("ice") != Result.Nodes.getMap().end();
assert(BinOpRoot);
const SourceManager &SM = *Result.SourceManager;
ASTContext &Ctx = *Result.Context;
BinaryOperatorVisitor Visitor(*this, SM, Ctx, ParentRoot);
- if (Visitor.isBooleanBitwise(BinOpRoot, AssignsToBoolean)) {
- // TraverseStmt requires non-const pointer, but we're only reading
- Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
- }
+ // TraverseStmt requires non-const pointer, but we're only reading
+ Visitor.TraverseStmt(const_cast<BinaryOperator *>(BinOpRoot));
}
} // namespace clang::tidy::misc
>From 6d390139e39fb92aebbcc787c845257193b648b0 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 09:32:09 +0300
Subject: [PATCH 39/49] change comments
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index bc69853f271b2..e66f571d78c84 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -110,9 +110,11 @@ void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
auto NotNestedInBitwise = unless(hasParent(binaryOperator(BitwiseOps)));
auto OptionalParent = optionally(hasParent(binaryOperator().bind("p")));
- // Conditions that make it a boolean bitwise operation without ICE context:
+ // Conditions that make it a boolean bitwise operation without ICE(*) context:
// 1. Both LHS and RHS have all boolean leaves
// 2. LHS has boolean leaves AND it's a compound assignment
+ //
+ // * ICE - Implicit cast expression
auto BothBoolean = allOf(hasLHS(BooleanLeaves), hasRHS(BooleanLeaves));
auto CompoundWithBoolLHS = allOf(hasLHS(BooleanLeaves), CompoundBitwiseOps);
auto NoContextNeeded = anyOf(BothBoolean, CompoundWithBoolLHS);
>From f84b2d82613178b829daf26b9d43b897622e2d0d Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 11:00:29 +0300
Subject: [PATCH 40/49] More tests for volatile && simplify
---
.../misc/BoolBitwiseOperationCheck.cpp | 1 -
.../bool-bitwise-operation-nontraditional.cpp | 81 +++++++++++++++++++
.../checkers/misc/bool-bitwise-operation.cpp | 81 +++++++++++++++++++
3 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index e66f571d78c84..7301e4dd1f5b3 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -157,7 +157,6 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
return E->IgnoreImpCasts()
->getType()
- .getDesugaredType(Ctx)
.isVolatileQualified();
});
if (HasVolatileOperand) {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 4a0581b6f194a..94d67a939d356 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -122,6 +122,22 @@ void bad_side_effects() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
+void bad_pointers() {
+ bool pointee = false;
+ bool* a = &pointee;
+ bool* b = &pointee;
+ *a bitor *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: *a or *b;
+ *a bitand *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: *a and *b;
+
+ // FIXME: implement fixit for these 2 cases
+ // *a or_eq *b;
+ // *a and_eq *b;
+}
+
void bad_side_effects_volatile() {
bool a = true;
volatile bool b = false;
@@ -152,6 +168,71 @@ void bad_side_effects_volatile() {
// CHECK-FIXES: a or c bitor b;
}
+void bad_side_effects_volatile_typedef() {
+ using volatile_bool_t = volatile bool;
+ bool a = true;
+ volatile_bool_t b = false;
+ bool c = true;
+
+ a bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a bitand b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a or_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a and_eq b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ (a bitor c) bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (a or c) bitor b;
+
+ a bitor c bitor b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a or c bitor b;
+}
+
+void bad_side_effects_volatile_typedef_pointers() {
+ using volatile_bool_t = volatile bool;
+ bool pointee = false;
+ volatile_bool_t* a = &pointee;
+ volatile_bool_t* b = &pointee;
+ *a bitor *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ *a bitand *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // FIXME: implement fixit for these 2 cases
+ // *a or_eq *b;
+ // *a and_eq *b;
+}
+
+void bad_side_effects_volatile_typedef_pointers_2() {
+ using volatile_bool_t = volatile bool*;
+ bool pointee = false;
+ volatile_bool_t a = &pointee;
+ volatile_bool_t b = &pointee;
+ *a bitor *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ *a bitand *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // FIXME: implement fixit for these 2 cases
+ // *a or_eq *b;
+ // *a and_eq *b;
+}
+
void bad_with_priors() {
bool a = false, b = true, c = true;
a and b bitor c;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
index 2c30de717d41e..350c3a0669f39 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation.cpp
@@ -122,6 +122,22 @@ void bad_side_effects() {
// CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
}
+void bad_pointers() {
+ bool pointee = false;
+ bool* a = &pointee;
+ bool* b = &pointee;
+ *a | *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: *a || *b;
+ *a & *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: *a && *b;
+
+ // FIXME: implement fixit for these 2 cases
+ // *a |= *b;
+ // *a &= *b;
+}
+
void bad_side_effects_volatile() {
bool a = true;
volatile bool b = false;
@@ -152,6 +168,71 @@ void bad_side_effects_volatile() {
// CHECK-FIXES: a || c | b;
}
+void bad_side_effects_volatile_typedef() {
+ using volatile_bool_t = volatile bool;
+ bool a = true;
+ volatile_bool_t b = false;
+ bool c = true;
+
+ a | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ a |= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ a &= b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ (a | c) | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: (a || c) | b;
+
+ a | c | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || c | b;
+}
+
+void bad_side_effects_volatile_typedef_pointers() {
+ using volatile_bool_t = volatile bool;
+ bool pointee = false;
+ volatile_bool_t* a = &pointee;
+ volatile_bool_t* b = &pointee;
+ *a | *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ *a & *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // FIXME: implement fixit for these 2 cases
+ // *a |= *b;
+ // *a &= *b;
+}
+
+void bad_side_effects_volatile_typedef_pointers_2() {
+ using volatile_bool_t = volatile bool*;
+ bool pointee = false;
+ volatile_bool_t a = &pointee;
+ volatile_bool_t b = &pointee;
+ *a | *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+ *a & *b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+
+ // FIXME: implement fixit for these 2 cases
+ // *a |= *b;
+ // *a &= *b;
+}
+
void bad_with_priors() {
bool a = false, b = true, c = true;
a && b | c;
>From 61ac0b178383f3981f862b1822b18935f8cc14da Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 11:44:10 +0300
Subject: [PATCH 41/49] refactoring
---
.../misc/BoolBitwiseOperationCheck.cpp | 103 ++++++++++--------
1 file changed, 55 insertions(+), 48 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 7301e4dd1f5b3..dfb6b3672240a 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -11,7 +11,6 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include <array>
-#include <optional>
#include <utility>
#include <vector>
@@ -153,6 +152,17 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
<< translate(BinOp->getOpcodeStr()) << BinOp->getOpcodeStr();
};
+ // Helper lambda to check if location is valid and not in a macro
+ auto IsValidLocation = [&](SourceLocation Loc) -> bool {
+ if (Loc.isInvalid() || Loc.isMacroID()) {
+ if (!IgnoreMacros)
+ DiagEmitter();
+ return false;
+ }
+ return true;
+ };
+
+ // Early validation: check for volatile operands
const bool HasVolatileOperand = llvm::any_of(
std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
return E->IgnoreImpCasts()
@@ -164,108 +174,105 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
return;
}
+ // Early validation: check for side effects
const bool HasSideEffects = BinOp->getRHS()->HasSideEffects(
- Ctx, /*IncludePossibleEffects=*/!UnsafeMode);
+ Ctx, /*IncludePossibleEffects=*/!UnsafeMode);
if (HasSideEffects) {
DiagEmitter();
return;
}
- SourceLocation Loc = BinOp->getOperatorLoc();
-
- if (Loc.isInvalid() || Loc.isMacroID()) {
- IgnoreMacros || DiagEmitter();
+ // Get and validate operator location
+ SourceLocation OpLoc = BinOp->getOperatorLoc();
+ if (!IsValidLocation(OpLoc))
return;
- }
- Loc = SM.getSpellingLoc(Loc);
- if (Loc.isInvalid() || Loc.isMacroID()) {
- IgnoreMacros || DiagEmitter();
+ OpLoc = SM.getSpellingLoc(OpLoc);
+ if (!IsValidLocation(OpLoc))
return;
- }
- const CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc);
+ // Generate fix-it hint for operator replacement
+ const CharSourceRange TokenRange = CharSourceRange::getTokenRange(OpLoc);
if (TokenRange.isInvalid()) {
- IgnoreMacros || DiagEmitter();
+ if (!IgnoreMacros)
+ DiagEmitter();
return;
}
const StringRef FixSpelling =
translate(Lexer::getSourceText(TokenRange, SM, Ctx.getLangOpts()));
-
if (FixSpelling.empty()) {
DiagEmitter();
return;
}
- FixItHint InsertEqual;
+ FixItHint ReplaceOpHint = FixItHint::CreateReplacement(TokenRange, FixSpelling);
+
+ // Generate fix-it hint for compound assignment (if applicable)
+ FixItHint InsertEqualHint;
if (BinOp->isCompoundAssignmentOp()) {
const auto *LHS = getAcceptableCompoundsLHS(BinOp);
if (!LHS) {
DiagEmitter();
return;
}
+
const SourceLocation LocLHS = LHS->getEndLoc();
- if (LocLHS.isInvalid() || LocLHS.isMacroID()) {
- IgnoreMacros || DiagEmitter();
+ if (!IsValidLocation(LocLHS))
return;
- }
+
const SourceLocation InsertLoc =
clang::Lexer::getLocForEndOfToken(LocLHS, 0, SM, Ctx.getLangOpts());
- if (InsertLoc.isInvalid() || InsertLoc.isMacroID()) {
- IgnoreMacros || DiagEmitter();
+ if (!IsValidLocation(InsertLoc))
return;
- }
+
auto SourceText = static_cast<std::string>(Lexer::getSourceText(
CharSourceRange::getTokenRange(LHS->getSourceRange()), SM,
Ctx.getLangOpts()));
llvm::erase_if(SourceText,
[](unsigned char Ch) { return std::isspace(Ch); });
- InsertEqual = FixItHint::CreateInsertion(InsertLoc, " = " + SourceText);
+ InsertEqualHint = FixItHint::CreateInsertion(InsertLoc, " = " + SourceText);
}
- auto ReplaceOperator = FixItHint::CreateReplacement(TokenRange, FixSpelling);
-
- std::optional<BinaryOperatorKind> ParentOpcode;
- if (ParentBinOp)
- ParentOpcode = ParentBinOp->getOpcode();
-
- const auto *RHS = dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts());
- std::optional<BinaryOperatorKind> RHSOpcode;
- if (RHS)
- RHSOpcode = RHS->getOpcode();
-
+ // Determine if parentheses are needed based on operator precedence
const Expr *SurroundedExpr = nullptr;
- if ((BinOp->getOpcode() == BO_Or && ParentOpcode == BO_LAnd) ||
- (BinOp->getOpcode() == BO_And &&
- llvm::is_contained({BO_Xor, BO_Or}, ParentOpcode))) {
- const Expr *Side = ParentBinOp->getLHS()->IgnoreParenImpCasts() == BinOp
- ? ParentBinOp->getLHS()
- : ParentBinOp->getRHS();
- SurroundedExpr = Side->IgnoreImpCasts();
- assert(SurroundedExpr->IgnoreParens() == BinOp);
- } else if (BinOp->getOpcode() == BO_AndAssign && RHSOpcode == BO_LOr)
- SurroundedExpr = RHS;
+ if (ParentBinOp) {
+ const BinaryOperatorKind ParentOpcode = ParentBinOp->getOpcode();
+ if ((BinOp->getOpcode() == BO_Or && ParentOpcode == BO_LAnd) ||
+ (BinOp->getOpcode() == BO_And &&
+ llvm::is_contained({BO_Xor, BO_Or}, ParentOpcode))) {
+ const Expr *Side = ParentBinOp->getLHS()->IgnoreParenImpCasts() == BinOp
+ ? ParentBinOp->getLHS()
+ : ParentBinOp->getRHS();
+ SurroundedExpr = Side->IgnoreImpCasts();
+ assert(SurroundedExpr->IgnoreParens() == BinOp);
+ }
+ }
+
+ if (!SurroundedExpr) {
+ const auto *RHS = dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts());
+ if (RHS && BinOp->getOpcode() == BO_AndAssign && RHS->getOpcode() == BO_LOr)
+ SurroundedExpr = RHS;
+ }
if (isa_and_nonnull<ParenExpr>(SurroundedExpr))
SurroundedExpr = nullptr;
+ // Generate fix-it hints for parentheses (if needed)
FixItHint InsertBrace1;
FixItHint InsertBrace2;
if (SurroundedExpr) {
const SourceLocation InsertFirstLoc = SurroundedExpr->getBeginLoc();
const SourceLocation InsertSecondLoc = clang::Lexer::getLocForEndOfToken(
SurroundedExpr->getEndLoc(), 0, SM, Ctx.getLangOpts());
- if (InsertFirstLoc.isInvalid() || InsertFirstLoc.isMacroID() ||
- InsertSecondLoc.isInvalid() || InsertSecondLoc.isMacroID()) {
- IgnoreMacros || DiagEmitter();
+ if (!IsValidLocation(InsertFirstLoc) || !IsValidLocation(InsertSecondLoc))
return;
- }
+
InsertBrace1 = FixItHint::CreateInsertion(InsertFirstLoc, "(");
InsertBrace2 = FixItHint::CreateInsertion(InsertSecondLoc, ")");
}
- DiagEmitter() << InsertEqual << ReplaceOperator << InsertBrace1
+ DiagEmitter() << InsertEqualHint << ReplaceOpHint << InsertBrace1
<< InsertBrace2;
}
>From 030cf62a9085fb7506dae379bdc90f035df50b13 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 12:15:36 +0300
Subject: [PATCH 42/49] Add StrictMode option
---
.../misc/BoolBitwiseOperationCheck.cpp | 21 ++++++---
.../misc/BoolBitwiseOperationCheck.h | 1 +
.../checks/misc/bool-bitwise-operation.rst | 9 +++-
...bitwise-operation-strict-mode-disabled.cpp | 47 +++++++++++++++++++
4 files changed, 70 insertions(+), 8 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-strict-mode-disabled.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index dfb6b3672240a..0b0fc2a36c1c5 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -92,12 +92,14 @@ BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
UnsafeMode(Options.get("UnsafeMode", false)),
- IgnoreMacros(Options.get("IgnoreMacros", false)) {}
+ IgnoreMacros(Options.get("IgnoreMacros", false)),
+ StrictMode(Options.get("StrictMode", true)) {}
void BoolBitwiseOperationCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "UnsafeMode", UnsafeMode);
Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+ Options.store(Opts, "StrictMode", StrictMode);
}
void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
@@ -152,11 +154,16 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
<< translate(BinOp->getOpcodeStr()) << BinOp->getOpcodeStr();
};
+ auto DiagEmitterForStrictMode = [&] {
+ if (StrictMode)
+ DiagEmitter();
+ };
+
// Helper lambda to check if location is valid and not in a macro
auto IsValidLocation = [&](SourceLocation Loc) -> bool {
if (Loc.isInvalid() || Loc.isMacroID()) {
if (!IgnoreMacros)
- DiagEmitter();
+ DiagEmitterForStrictMode();
return false;
}
return true;
@@ -170,7 +177,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
.isVolatileQualified();
});
if (HasVolatileOperand) {
- DiagEmitter();
+ DiagEmitterForStrictMode();
return;
}
@@ -178,7 +185,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
const bool HasSideEffects = BinOp->getRHS()->HasSideEffects(
Ctx, /*IncludePossibleEffects=*/!UnsafeMode);
if (HasSideEffects) {
- DiagEmitter();
+ DiagEmitterForStrictMode();
return;
}
@@ -195,14 +202,14 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
const CharSourceRange TokenRange = CharSourceRange::getTokenRange(OpLoc);
if (TokenRange.isInvalid()) {
if (!IgnoreMacros)
- DiagEmitter();
+ DiagEmitterForStrictMode();
return;
}
const StringRef FixSpelling =
translate(Lexer::getSourceText(TokenRange, SM, Ctx.getLangOpts()));
if (FixSpelling.empty()) {
- DiagEmitter();
+ DiagEmitterForStrictMode();
return;
}
@@ -213,7 +220,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
if (BinOp->isCompoundAssignmentOp()) {
const auto *LHS = getAcceptableCompoundsLHS(BinOp);
if (!LHS) {
- DiagEmitter();
+ DiagEmitterForStrictMode();
return;
}
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
index b3977a3d41824..3defcf8461969 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.h
@@ -36,6 +36,7 @@ class BoolBitwiseOperationCheck : public ClangTidyCheck {
private:
bool UnsafeMode;
bool IgnoreMacros;
+ bool StrictMode;
};
} // namespace clang::tidy::misc
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
index f7f03575ae126..f401bea4b7f53 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -73,4 +73,11 @@ Options
.. option:: IgnoreMacros
Don't warn if a macro inside the expression body prevents replacing a
- bitwise operator with a logical one. Default value is `false`.
\ No newline at end of file
+ bitwise operator with a logical one. Default value is `false`.
+
+.. option:: StrictMode
+
+ When enabled, show warnings even when fix-it hints cannot be generated
+ (e.g., for volatile operands or expressions with side effects). When
+ disabled, only show warnings when fix-it hints are available. Default
+ value is `true`.
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-strict-mode-disabled.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-strict-mode-disabled.cpp
new file mode 100644
index 0000000000000..0e2c36d3937c1
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-strict-mode-disabled.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-bool-bitwise-operation %t \
+// RUN: -config="{CheckOptions: { \
+// RUN: misc-bool-bitwise-operation.StrictMode: false }}"
+
+// Test with StrictMode=false: warnings should NOT be shown when fixits don't exist
+
+bool function_with_possible_side_effects();
+
+void test_strict_mode_disabled() {
+ bool a = true, b = false;
+
+ // Case 1: Side effects in RHS - no fixit, no warning should be shown
+ a | function_with_possible_side_effects();
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+
+ a & function_with_possible_side_effects();
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+
+ a |= function_with_possible_side_effects();
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+
+ a &= function_with_possible_side_effects();
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+
+ // Case 2: Volatile operands - no fixit, no warning should be shown
+ volatile bool v = false;
+ a | v;
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+
+ a & v;
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+
+ a |= v;
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|=' [misc-bool-bitwise-operation]
+
+ a &= v;
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:{{.*}}: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&=' [misc-bool-bitwise-operation]
+
+ // Case 3: Normal case with fixit - warning should still be shown with fixit
+ a | b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a || b;
+
+ a & b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: a && b;
+}
>From 515b364dcc9ddf15621744bc761e2a7838b9c847 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 12:16:33 +0300
Subject: [PATCH 43/49] format
---
.../misc/BoolBitwiseOperationCheck.cpp | 47 ++++++++++---------
1 file changed, 24 insertions(+), 23 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 0b0fc2a36c1c5..9854360c1eb01 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -48,16 +48,17 @@ static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
return isa<DeclRefExpr, MemberExpr>(LHS) ? LHS : nullptr;
}
-/// Checks if all leaf nodes in an bitwise expression satisfy a given condition. This
-/// handles cases like `(a | b) & c` where we need to check that a, b, and c
-/// all satisfy the condition.
+/// Checks if all leaf nodes in an bitwise expression satisfy a given condition.
+/// This handles cases like `(a | b) & c` where we need to check that a, b, and
+/// c all satisfy the condition.
///
/// \param Expr The bitwise expression to check.
/// \param Condition A function that checks if an leaf node satisfies the
/// desired condition.
/// \returns true if all leaf nodes satisfy the condition, false otherwise.
template <typename F>
-static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr, const F& Condition) {
+static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr,
+ const F &Condition) {
// For leaf nodes, check if the condition is satisfied
if (Condition(Expr))
return true;
@@ -69,14 +70,15 @@ static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr, const F& Conditio
if (!isBitwiseOperation(BinOp->getOpcodeStr()))
return false;
return allLeavesOfBitwiseSatisfy(BinOp->getLHS(), Condition) &&
- allLeavesOfBitwiseSatisfy(BinOp->getRHS(), Condition);
+ allLeavesOfBitwiseSatisfy(BinOp->getRHS(), Condition);
}
return false;
}
-/// Custom matcher that checks if all leaf nodes in an bitwise expression satisfy
-/// the given inner matcher condition. This uses allLeavesOfBitwiseSatisfy to recursively
+/// Custom matcher that checks if all leaf nodes in an bitwise expression
+/// satisfy the given inner matcher condition. This uses
+/// allLeavesOfBitwiseSatisfy to recursively
///
/// Example usage:
/// expr(hasAllLeavesOfBitwiseSatisfying(hasType(booleanType())))
@@ -125,19 +127,18 @@ void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
auto AtLeastOneBoolean = anyOf(hasLHS(BooleanLeaves), hasRHS(BooleanLeaves));
// Matcher for binop that doesn't need ICE context
- auto BinOpNoContext = traverse(
- TK_IgnoreUnlessSpelledInSource,
- binaryOperator(NotNestedInBitwise, BitwiseOps, OptionalParent,
- NoContextNeeded)
- .bind("binOpRoot"));
+ auto BinOpNoContext = traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperator(NotNestedInBitwise, BitwiseOps,
+ OptionalParent, NoContextNeeded)
+ .bind("binOpRoot"));
// Matcher for binop that needs ICE context (at least one boolean operand,
// but not already covered by NoContextNeeded)
- auto BinOpNeedsContext = traverse(
- TK_IgnoreUnlessSpelledInSource,
- binaryOperator(NotNestedInBitwise, BitwiseOps, OptionalParent,
- AtLeastOneBoolean, unless(NoContextNeeded))
- .bind("binOpRoot"));
+ auto BinOpNeedsContext =
+ traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperator(NotNestedInBitwise, BitwiseOps, OptionalParent,
+ AtLeastOneBoolean, unless(NoContextNeeded))
+ .bind("binOpRoot"));
auto BooleanICE =
implicitCastExpr(hasType(booleanType()), has(BinOpNeedsContext));
@@ -172,9 +173,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
// Early validation: check for volatile operands
const bool HasVolatileOperand = llvm::any_of(
std::array{BinOp->getLHS(), BinOp->getRHS()}, [&](const Expr *E) {
- return E->IgnoreImpCasts()
- ->getType()
- .isVolatileQualified();
+ return E->IgnoreImpCasts()->getType().isVolatileQualified();
});
if (HasVolatileOperand) {
DiagEmitterForStrictMode();
@@ -183,7 +182,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
// Early validation: check for side effects
const bool HasSideEffects = BinOp->getRHS()->HasSideEffects(
- Ctx, /*IncludePossibleEffects=*/!UnsafeMode);
+ Ctx, /*IncludePossibleEffects=*/!UnsafeMode);
if (HasSideEffects) {
DiagEmitterForStrictMode();
return;
@@ -213,7 +212,8 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
return;
}
- FixItHint ReplaceOpHint = FixItHint::CreateReplacement(TokenRange, FixSpelling);
+ FixItHint ReplaceOpHint =
+ FixItHint::CreateReplacement(TokenRange, FixSpelling);
// Generate fix-it hint for compound assignment (if applicable)
FixItHint InsertEqualHint;
@@ -257,7 +257,8 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
}
if (!SurroundedExpr) {
- const auto *RHS = dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts());
+ const auto *RHS =
+ dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts());
if (RHS && BinOp->getOpcode() == BO_AndAssign && RHS->getOpcode() == BO_LOr)
SurroundedExpr = RHS;
}
>From 18242190ce251fca35ef0741096c2da303fbd1e3 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 13:20:28 +0300
Subject: [PATCH 44/49] change tests
---
.../checkers/misc/bool-bitwise-operation-nontraditional.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
index 94d67a939d356..e403cd83b1ca4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-nontraditional.cpp
@@ -260,11 +260,9 @@ void bad_with_priors() {
void bad_with_priors2() {
bool a = false, b = true, c = true;
- bool r;
a xor b bitand c;
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use logical operator '&&' for boolean semantics instead of bitwise operator '&' [misc-bool-bitwise-operation]
// CHECK-FIXES: a xor (b and c);
-
// braces added in the first change
a bitor b bitand c;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
>From 51e7922e029af17cfec6dae264f5698f8d54c06e Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 13:20:38 +0300
Subject: [PATCH 45/49] lint
---
.../clang-tidy/checks/misc/bool-bitwise-operation.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
index f401bea4b7f53..6ea6e827b797a 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/bool-bitwise-operation.rst
@@ -3,11 +3,11 @@
misc-bool-bitwise-operation
===========================
-Finds potentially inefficient use of bitwise operators such as ``&``, ``|``
-and their compound analogues on Boolean values where logical operators like
+Finds potentially inefficient use of bitwise operators such as ``&``, ``|``
+and their compound analogues on Boolean values where logical operators like
``&&`` and ``||`` would be more appropriate.
-Bitwise operations on Booleans can incur unnecessary performance overhead due
+Bitwise operations on Booleans can incur unnecessary performance overhead due
to implicit integer conversions and missed short-circuit evaluation.
.. code-block:: c++
@@ -29,7 +29,7 @@ to implicit integer conversions and missed short-circuit evaluation.
// error handling
}
-These 3 warnings suggest assigning the result of a logical ``||`` operation
+These 3 warnings suggest assigning the result of a logical ``||`` operation
instead of using the ``|=`` operator:
.. code-block:: c++
@@ -80,4 +80,4 @@ Options
When enabled, show warnings even when fix-it hints cannot be generated
(e.g., for volatile operands or expressions with side effects). When
disabled, only show warnings when fix-it hints are available. Default
- value is `true`.
\ No newline at end of file
+ value is `true`.
>From cb00072d9ce672742c29882e0b1738bb6bfdc1ba Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 13:22:10 +0300
Subject: [PATCH 46/49] lint
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 9854360c1eb01..928d1eddf0789 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -29,10 +29,9 @@ static constexpr std::array<std::pair<StringRef, StringRef>, 8U>
{"or_eq", "or"}}};
static StringRef translate(StringRef Value) {
- for (const auto &[Bitwise, Logical] : OperatorsTransformation) {
+ for (const auto &[Bitwise, Logical] : OperatorsTransformation)
if (Value == Bitwise)
return Logical;
- }
return {};
}
>From aea089b8612b185e6320ec6c00b5e050fa167e61 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 13:42:02 +0300
Subject: [PATCH 47/49] lint
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 928d1eddf0789..8ba29a8051490 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -75,6 +75,7 @@ static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr,
return false;
}
+namespace {
/// Custom matcher that checks if all leaf nodes in an bitwise expression
/// satisfy the given inner matcher condition. This uses
/// allLeavesOfBitwiseSatisfy to recursively
@@ -88,6 +89,7 @@ AST_MATCHER_P(Expr, hasAllLeavesOfBitwiseSatisfying,
};
return allLeavesOfBitwiseSatisfy(&Node, Condition);
}
+} // namespace
BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
ClangTidyContext *Context)
@@ -211,7 +213,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
return;
}
- FixItHint ReplaceOpHint =
+ const FixItHint ReplaceOpHint =
FixItHint::CreateReplacement(TokenRange, FixSpelling);
// Generate fix-it hint for compound assignment (if applicable)
>From 67d7af177e5e50878a9080df6679f05ef9503220 Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 16:21:09 +0300
Subject: [PATCH 48/49] Fix false positive
---
.../misc/BoolBitwiseOperationCheck.cpp | 52 ++--
...itwise-operation-not-only-bool-operand.cpp | 256 ++++++++++++++++++
2 files changed, 292 insertions(+), 16 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index 8ba29a8051490..ef52e87e043d0 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -11,6 +11,7 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include <array>
+#include <functional>
#include <utility>
#include <vector>
@@ -47,17 +48,17 @@ static const Expr *getAcceptableCompoundsLHS(const BinaryOperator *BinOp) {
return isa<DeclRefExpr, MemberExpr>(LHS) ? LHS : nullptr;
}
-/// Checks if all leaf nodes in an bitwise expression satisfy a given condition.
-/// This handles cases like `(a | b) & c` where we need to check that a, b, and
-/// c all satisfy the condition.
+/// Checks if leaf nodes in a bitwise expression satisfy a given condition.
///
/// \param Expr The bitwise expression to check.
-/// \param Condition A function that checks if an leaf node satisfies the
+/// \param Condition A function that checks if a leaf node satisfies the
/// desired condition.
-/// \returns true if all leaf nodes satisfy the condition, false otherwise.
-template <typename F>
-static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr,
- const F &Condition) {
+/// \param Combine A function that combines results from LHS and RHS (e.g., &&
+/// for "all", || for "any").
+/// \returns true if the condition is satisfied according to the combiner logic.
+template <typename F, typename Combiner>
+static bool leavesOfBitwiseSatisfy(const clang::Expr *Expr, const F &Condition,
+ const Combiner &Combine) {
// For leaf nodes, check if the condition is satisfied
if (Condition(Expr))
return true;
@@ -68,8 +69,8 @@ static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr,
if (const auto *BinOp = dyn_cast<clang::BinaryOperator>(Expr)) {
if (!isBitwiseOperation(BinOp->getOpcodeStr()))
return false;
- return allLeavesOfBitwiseSatisfy(BinOp->getLHS(), Condition) &&
- allLeavesOfBitwiseSatisfy(BinOp->getRHS(), Condition);
+ return Combine(leavesOfBitwiseSatisfy(BinOp->getLHS(), Condition, Combine),
+ leavesOfBitwiseSatisfy(BinOp->getRHS(), Condition, Combine));
}
return false;
@@ -78,7 +79,7 @@ static bool allLeavesOfBitwiseSatisfy(const clang::Expr *Expr,
namespace {
/// Custom matcher that checks if all leaf nodes in an bitwise expression
/// satisfy the given inner matcher condition. This uses
-/// allLeavesOfBitwiseSatisfy to recursively
+/// leavesOfBitwiseSatisfy to recursively check.
///
/// Example usage:
/// expr(hasAllLeavesOfBitwiseSatisfying(hasType(booleanType())))
@@ -87,7 +88,21 @@ AST_MATCHER_P(Expr, hasAllLeavesOfBitwiseSatisfying,
auto Condition = [&](const clang::Expr *E) -> bool {
return InnerMatcher.matches(*E, Finder, Builder);
};
- return allLeavesOfBitwiseSatisfy(&Node, Condition);
+ return leavesOfBitwiseSatisfy(&Node, Condition, std::logical_and<bool>());
+}
+
+/// Custom matcher that checks if any leaf node in a bitwise expression
+/// satisfies the given inner matcher condition. This uses
+/// leavesOfBitwiseSatisfy to recursively check.
+///
+/// Example usage:
+/// expr(hasAnyLeafOfBitwiseSatisfying(hasType(booleanType())))
+AST_MATCHER_P(Expr, hasAnyLeafOfBitwiseSatisfying,
+ ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+ auto Condition = [&](const clang::Expr *E) -> bool {
+ return InnerMatcher.matches(*E, Finder, Builder);
+ };
+ return leavesOfBitwiseSatisfy(&Node, Condition, std::logical_or<bool>());
}
} // namespace
@@ -106,8 +121,12 @@ void BoolBitwiseOperationCheck::storeOptions(
}
void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
- // Matcher for checking if all leaves in an expression are boolean type
+ // Matcher for checking if all leaves in an bitwise expression are boolean
+ // type
auto BooleanLeaves = hasAllLeavesOfBitwiseSatisfying(hasType(booleanType()));
+ // Matcher for checking if at least one leaf in an bitwise expression is
+ // boolean type
+ auto BooleanAnyLeaf = hasAnyLeafOfBitwiseSatisfying(hasType(booleanType()));
auto BitwiseOps = hasAnyOperatorName("|", "&", "|=", "&=");
auto CompoundBitwiseOps = hasAnyOperatorName("|=", "&=");
@@ -123,9 +142,10 @@ void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
auto CompoundWithBoolLHS = allOf(hasLHS(BooleanLeaves), CompoundBitwiseOps);
auto NoContextNeeded = anyOf(BothBoolean, CompoundWithBoolLHS);
- // At least one boolean operand (needs ICE context to be considered boolean
- // bitwise)
- auto AtLeastOneBoolean = anyOf(hasLHS(BooleanLeaves), hasRHS(BooleanLeaves));
+ // Check if any leaf in LHS or RHS is boolean (needs ICE context to be
+ // considered boolean bitwise)
+ auto AtLeastOneBoolean =
+ anyOf(hasLHS(BooleanAnyLeaf), hasRHS(BooleanAnyLeaf));
// Matcher for binop that doesn't need ICE context
auto BinOpNoContext = traverse(TK_IgnoreUnlessSpelledInSource,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
index c3b6744c1cb14..c90514dc69f2c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/bool-bitwise-operation-not-only-bool-operand.cpp
@@ -12,6 +12,16 @@ void general(unsigned flags, bool value) {
flags = (flags << 1) | (flags << 2) | (flags << 4) | value;
take_int((flags << 1) | value);
take_int((flags << 1) | (flags << 2) | value);
+ value | (flags << 1);
+ flags = value | (flags << 1);
+ flags = value | (flags << 1) | (flags << 2);
+ flags = value | (flags << 1) | (flags << 2) | (flags << 4);
+ flags = (flags << 1) | value | (flags << 2);
+ flags = (flags << 1) | value | (flags << 2) | (flags << 4);
+ flags = (flags << 1) | (flags << 2) | value | (flags << 4);
+ take_int(value | (flags << 1));
+ take_int(value | (flags << 1) | (flags << 2));
+ take_int((flags << 1) | value | (flags << 2));
}
// FIXME: implement `template<bool bb=true|1>` cases
@@ -50,6 +60,47 @@ void assign_to_boolean(unsigned flags, bool value) {
// CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (flags << 1) || (flags << 2) || (flags << 4) || value;
+ bool result2 = value | (flags << 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result2 = value || (flags << 1);
+ bool a2 = value | (flags << 2),
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a2 = value || (flags << 2),
+ b2 = value | (flags << 4),
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b2 = value || (flags << 4),
+ c2 = value | (flags << 8);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c2 = value || (flags << 8);
+ result2 = value | (flags << 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = value || (flags << 1);
+ take(value | (flags << 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(value || (flags << 1));
+ result2 = value | (flags << 1) | (flags << 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = value || (flags << 1) || (flags << 2);
+ result2 = value | (flags << 1) | (flags << 2) | (flags << 4);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:51: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = value || (flags << 1) || (flags << 2) || (flags << 4);
+ result2 = (flags << 1) | value | (flags << 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (flags << 1) || value || (flags << 2);
+ result2 = (flags << 1) | value | (flags << 2) | (flags << 4);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:51: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (flags << 1) || value || (flags << 2) || (flags << 4);
+ result2 = (flags << 1) | (flags << 2) | value | (flags << 4);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:51: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (flags << 1) || (flags << 2) || value || (flags << 4);
}
void assign_to_boolean_parens(unsigned flags, bool value) {
@@ -86,6 +137,47 @@ void assign_to_boolean_parens(unsigned flags, bool value) {
// CHECK-MESSAGES: :[[@LINE-2]]:43: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-3]]:58: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = ((flags << 1) || (flags << 2) || (flags << 4) || value);
+ bool result2 = ((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result2 = ((value || (flags << 1)));
+ bool a2 = ((value | (flags << 2))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a2 = ((value || (flags << 2))),
+ b2 = ((value | (flags << 4))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b2 = ((value || (flags << 4))),
+ c2 = ((value | (flags << 8)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c2 = ((value || (flags << 8)));
+ result2 = ((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = ((value || (flags << 1)));
+ take(((value | (flags << 1))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(((value || (flags << 1))));
+ result2 = ((value | (flags << 1) | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = ((value || (flags << 1) || (flags << 2)));
+ result2 = ((value | (flags << 1) | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = ((value || (flags << 1) || (flags << 2) || (flags << 4)));
+ result2 = (((flags << 1) | value | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (((flags << 1) || value || (flags << 2)));
+ result2 = (((flags << 1) | value | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (((flags << 1) || value || (flags << 2) || (flags << 4)));
+ result2 = (((flags << 1) | (flags << 2) | value | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (((flags << 1) || (flags << 2) || value || (flags << 4)));
}
void assign_to_boolean_parens2(unsigned flags, bool value) {
@@ -122,6 +214,47 @@ void assign_to_boolean_parens2(unsigned flags, bool value) {
// CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (((flags << 1) || (flags << 2) || (flags << 4) || value));
+ bool result2 = (((value | (flags << 1))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result2 = (((value || (flags << 1))));
+ bool a2 = (((value | (flags << 2)))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a2 = (((value || (flags << 2)))),
+ b2 = (((value | (flags << 4)))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b2 = (((value || (flags << 4)))),
+ c2 = (((value | (flags << 8))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c2 = (((value || (flags << 8))));
+ result2 = (((value | (flags << 1))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (((value || (flags << 1))));
+ take((((value | (flags << 1)))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take((((value || (flags << 1)))));
+ result2 = (((value | (flags << 1) | (flags << 2))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (((value || (flags << 1) || (flags << 2))));
+ result2 = (((value | (flags << 1) | (flags << 2) | (flags << 4))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:54: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (((value || (flags << 1) || (flags << 2) || (flags << 4))));
+ result2 = ((((flags << 1) | value | (flags << 2))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = ((((flags << 1) || value || (flags << 2))));
+ result2 = ((((flags << 1) | value | (flags << 2) | (flags << 4))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:54: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = ((((flags << 1) || value || (flags << 2) || (flags << 4))));
+ result2 = ((((flags << 1) | (flags << 2) | value | (flags << 4))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:46: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:54: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = ((((flags << 1) || (flags << 2) || value || (flags << 4))));
}
// functional cast
@@ -159,6 +292,47 @@ void assign_to_boolean_fcast(unsigned flags, bool value) {
// CHECK-MESSAGES: :[[@LINE-2]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-3]]:62: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = bool((flags << 1) || (flags << 2) || (flags << 4) || value);
+ bool result2 = bool((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result2 = bool((value || (flags << 1)));
+ bool a2 = bool((value | (flags << 2))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a2 = bool((value || (flags << 2))),
+ b2 = bool((value | (flags << 4))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b2 = bool((value || (flags << 4))),
+ c2 = bool((value | (flags << 8)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c2 = bool((value || (flags << 8)));
+ result2 = bool((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = bool((value || (flags << 1)));
+ take(bool((value | (flags << 1))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(bool((value || (flags << 1))));
+ result2 = bool((value | (flags << 1) | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = bool((value || (flags << 1) || (flags << 2)));
+ result2 = bool((value | (flags << 1) | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = bool((value || (flags << 1) || (flags << 2) || (flags << 4)));
+ result2 = bool(((flags << 1) | value | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = bool(((flags << 1) || value || (flags << 2)));
+ result2 = bool(((flags << 1) | value | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = bool(((flags << 1) || value || (flags << 2) || (flags << 4)));
+ result2 = bool(((flags << 1) | (flags << 2) | value | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:57: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = bool(((flags << 1) || (flags << 2) || value || (flags << 4)));
}
// C-style cast
@@ -196,6 +370,47 @@ void assign_to_boolean_ccast(unsigned flags, bool value) {
// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-3]]:64: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = (bool)((flags << 1) || (flags << 2) || (flags << 4) || value);
+ bool result2 = (bool)((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result2 = (bool)((value || (flags << 1)));
+ bool a2 = (bool)((value | (flags << 2))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a2 = (bool)((value || (flags << 2))),
+ b2 = (bool)((value | (flags << 4))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b2 = (bool)((value || (flags << 4))),
+ c2 = (bool)((value | (flags << 8)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c2 = (bool)((value || (flags << 8)));
+ result2 = (bool)((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (bool)((value || (flags << 1)));
+ take((bool)((value | (flags << 1))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take((bool)((value || (flags << 1))));
+ result2 = (bool)((value | (flags << 1) | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (bool)((value || (flags << 1) || (flags << 2)));
+ result2 = (bool)((value | (flags << 1) | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (bool)((value || (flags << 1) || (flags << 2) || (flags << 4)));
+ result2 = (bool)(((flags << 1) | value | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (bool)(((flags << 1) || value || (flags << 2)));
+ result2 = (bool)(((flags << 1) | value | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (bool)(((flags << 1) || value || (flags << 2) || (flags << 4)));
+ result2 = (bool)(((flags << 1) | (flags << 2) | value | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:51: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:59: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = (bool)(((flags << 1) || (flags << 2) || value || (flags << 4)));
}
// static_cast
@@ -233,6 +448,47 @@ void assign_to_boolean_scast(unsigned flags, bool value) {
// CHECK-MESSAGES: :[[@LINE-2]]:60: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-MESSAGES: :[[@LINE-3]]:75: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
// CHECK-FIXES: result = static_cast<bool>((flags << 1) || (flags << 2) || (flags << 4) || value);
+ bool result2 = static_cast<bool>((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool result2 = static_cast<bool>((value || (flags << 1)));
+ bool a2 = static_cast<bool>((value | (flags << 2))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: bool a2 = static_cast<bool>((value || (flags << 2))),
+ b2 = static_cast<bool>((value | (flags << 4))),
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: b2 = static_cast<bool>((value || (flags << 4))),
+ c2 = static_cast<bool>((value | (flags << 8)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: c2 = static_cast<bool>((value || (flags << 8)));
+ result2 = static_cast<bool>((value | (flags << 1)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = static_cast<bool>((value || (flags << 1)));
+ take(static_cast<bool>((value | (flags << 1))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: take(static_cast<bool>((value || (flags << 1))));
+ result2 = static_cast<bool>((value | (flags << 1) | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:55: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = static_cast<bool>((value || (flags << 1) || (flags << 2)));
+ result2 = static_cast<bool>((value | (flags << 1) | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:55: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:70: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = static_cast<bool>((value || (flags << 1) || (flags << 2) || (flags << 4)));
+ result2 = static_cast<bool>(((flags << 1) | value | (flags << 2)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:55: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = static_cast<bool>(((flags << 1) || value || (flags << 2)));
+ result2 = static_cast<bool>(((flags << 1) | value | (flags << 2) | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:55: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:70: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = static_cast<bool>(((flags << 1) || value || (flags << 2) || (flags << 4)));
+ result2 = static_cast<bool>(((flags << 1) | (flags << 2) | value | (flags << 4)));
+ // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-2]]:62: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-MESSAGES: :[[@LINE-3]]:70: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation]
+ // CHECK-FIXES: result2 = static_cast<bool>(((flags << 1) || (flags << 2) || value || (flags << 4)));
}
>From bf71aab89f372461e3f85f571ab82dfd8dfd9b2e Mon Sep 17 00:00:00 2001
From: denzor200 <denismikhaylov38 at gmail.com>
Date: Sat, 17 Jan 2026 16:30:28 +0300
Subject: [PATCH 49/49] lint
---
.../clang-tidy/misc/BoolBitwiseOperationCheck.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
index ef52e87e043d0..9ac8af1d905f9 100644
--- a/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/BoolBitwiseOperationCheck.cpp
@@ -88,7 +88,7 @@ AST_MATCHER_P(Expr, hasAllLeavesOfBitwiseSatisfying,
auto Condition = [&](const clang::Expr *E) -> bool {
return InnerMatcher.matches(*E, Finder, Builder);
};
- return leavesOfBitwiseSatisfy(&Node, Condition, std::logical_and<bool>());
+ return leavesOfBitwiseSatisfy(&Node, Condition, std::logical_and{});
}
/// Custom matcher that checks if any leaf node in a bitwise expression
@@ -102,7 +102,7 @@ AST_MATCHER_P(Expr, hasAnyLeafOfBitwiseSatisfying,
auto Condition = [&](const clang::Expr *E) -> bool {
return InnerMatcher.matches(*E, Finder, Builder);
};
- return leavesOfBitwiseSatisfy(&Node, Condition, std::logical_or<bool>());
+ return leavesOfBitwiseSatisfy(&Node, Condition, std::logical_or{});
}
} // namespace
More information about the cfe-commits
mailing list