[clang-tools-extra] [clang-tidy] Add performance-bool-bitwise-operation check (PR #142324)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 2 00:16:13 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tidy
Author: Denis Mikhailov (denzor200)
<details>
<summary>Changes</summary>
Add new clang-tidy check that 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.
Small example:
```
bool invalid = false;
invalid |= x > limit.x; // warning: use logical operator instead of bitwise one for bool
invalid |= y > limit.y; // warning: use logical operator instead of bitwise one for bool
invalid |= z > limit.z; // warning: use logical operator instead of bitwise one for bool
if (invalid) {
// error handling
}
```
Fixes: https://github.com/llvm/llvm-project/issues/40307
---
Patch is 61.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142324.diff
10 Files Affected:
- (added) clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp (+200)
- (added) clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.h (+38)
- (modified) clang-tools-extra/clang-tidy/performance/CMakeLists.txt (+1)
- (modified) clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp (+3)
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+7)
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1)
- (added) clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst (+40)
- (added) clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-change-possible-side-effect.cpp (+83)
- (added) clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-nontraditional.cpp (+388)
- (added) clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation.cpp (+388)
``````````diff
diff --git a/clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp b/clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
new file mode 100644
index 0000000000000..148ba65de129d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
@@ -0,0 +1,200 @@
+//===--- 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::performance {
+namespace {
+bool hasExplicitParentheses(const Expr *E, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ if (!E)
+ return false;
+
+ const SourceLocation Start = E->getBeginLoc();
+ const SourceLocation End = E->getEndLoc();
+
+ if (Start.isMacroID() || End.isMacroID() || !Start.isValid() ||
+ !End.isValid()) {
+ return false;
+ }
+
+ const std::optional<Token> PrevTok =
+ Lexer::findPreviousToken(Start, SM, LangOpts, /*IncludeComments=*/false);
+ const std::optional<Token> NextTok =
+ Lexer::findNextToken(End, SM, LangOpts, /*IncludeComments=*/false);
+
+ return (PrevTok && PrevTok->is(tok::l_paren)) &&
+ (NextTok && NextTok->is(tok::r_paren));
+}
+
+template <typename AstNode>
+bool isInTemplateFunction(const AstNode *AN, ASTContext &Context) {
+ auto Parents = Context.getParents(*AN);
+ for (const auto &Parent : Parents) {
+ if (const auto *FD = Parent.template get<FunctionDecl>()) {
+ return FD->isTemplateInstantiation() ||
+ FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate;
+ }
+ if (const auto *S = Parent.template get<Stmt>()) {
+ return isInTemplateFunction(S, Context);
+ }
+ }
+ return false;
+}
+
+constexpr std::array<std::pair<llvm::StringRef, llvm::StringRef>, 8U>
+ OperatorsTransformation{{{"|", "||"},
+ {"|=", "||"},
+ {"&", "&&"},
+ {"&=", "&&"},
+ {"bitand", "and"},
+ {"and_eq", "and"},
+ {"bitor", "or"},
+ {"or_eq", "or"}}};
+
+llvm::StringRef translate(llvm::StringRef Value) {
+ for (const auto &[Bitwise, Logical] : OperatorsTransformation) {
+ if (Value == Bitwise)
+ return Logical;
+ }
+
+ return {};
+}
+} // namespace
+
+BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context), ChangePossibleSideEffects(Options.get(
+ "ChangePossibleSideEffects", false)) {}
+
+void BoolBitwiseOperationCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "ChangePossibleSideEffects", ChangePossibleSideEffects);
+}
+
+void BoolBitwiseOperationCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ binaryOperator(
+ unless(isExpansionInSystemHeader()),
+ hasAnyOperatorName("|", "&", "|=", "&="),
+ hasEitherOperand(expr(ignoringImpCasts(hasType(booleanType())))),
+ optionally(hasAncestor( // 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 Diag = diag(MatchedExpr->getOperatorLoc(),
+ "use logical operator instead of bitwise one for bool");
+
+ if (isInTemplateFunction(MatchedExpr, *Result.Context))
+ return;
+
+ const bool HasVolatileOperand = llvm::any_of(
+ std::array{MatchedExpr->getLHS(), MatchedExpr->getRHS()},
+ [](const Expr *E) {
+ return E->IgnoreImpCasts()->getType().isVolatileQualified();
+ });
+ const bool HasSideEffects = MatchedExpr->getRHS()->HasSideEffects(
+ *Result.Context, !ChangePossibleSideEffects);
+ if (HasVolatileOperand || HasSideEffects)
+ return;
+
+ SourceLocation Loc = MatchedExpr->getOperatorLoc();
+
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return;
+
+ Loc = Result.SourceManager->getSpellingLoc(Loc);
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return;
+
+ const CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc);
+ if (TokenRange.isInvalid())
+ return;
+
+ StringRef Spelling = Lexer::getSourceText(TokenRange, *Result.SourceManager,
+ Result.Context->getLangOpts());
+ StringRef TranslatedSpelling = translate(Spelling);
+
+ if (TranslatedSpelling.empty())
+ return;
+
+ std::string FixSpelling = TranslatedSpelling.str();
+
+ FixItHint InsertEqual, ReplaceOperator, InsertBrace1, InsertBrace2;
+ if (MatchedExpr->isCompoundAssignmentOp()) {
+ const auto *DelcRefLHS =
+ dyn_cast<DeclRefExpr>(MatchedExpr->getLHS()->IgnoreImpCasts());
+ if (!DelcRefLHS)
+ return;
+ const SourceLocation LocLHS = DelcRefLHS->getEndLoc();
+ if (LocLHS.isInvalid() || LocLHS.isMacroID())
+ return;
+ const SourceLocation InsertLoc = clang::Lexer::getLocForEndOfToken(
+ LocLHS, 0, *Result.SourceManager, Result.Context->getLangOpts());
+ if (InsertLoc.isInvalid() || InsertLoc.isMacroID()) {
+ return;
+ }
+ InsertEqual = FixItHint::CreateInsertion(
+ InsertLoc, " = " + DelcRefLHS->getDecl()->getNameAsString());
+ }
+ ReplaceOperator = FixItHint::CreateReplacement(TokenRange, FixSpelling);
+
+ std::optional<BinaryOperatorKind> ParentOpcode;
+ if (const auto *Parent = Result.Nodes.getNodeAs<BinaryOperator>("p"); Parent)
+ ParentOpcode = Parent->getOpcode();
+
+ const auto *RHS =
+ dyn_cast<BinaryOperator>(MatchedExpr->getRHS()->IgnoreParenCasts());
+ std::optional<BinaryOperatorKind> RHSOpcode;
+ if (RHS)
+ RHSOpcode = RHS->getOpcode();
+
+ const BinaryOperator *SurroundedExpr = nullptr;
+ if ((MatchedExpr->getOpcode() == BO_Or && ParentOpcode.has_value() &&
+ *ParentOpcode == BO_LAnd) ||
+ (MatchedExpr->getOpcode() == BO_And && ParentOpcode.has_value() &&
+ llvm::is_contained({BO_Xor, BO_Or}, *ParentOpcode))) {
+ SurroundedExpr = MatchedExpr;
+ } else if (MatchedExpr->getOpcode() == BO_AndAssign &&
+ RHSOpcode.has_value() && *RHSOpcode == BO_LOr) {
+ SurroundedExpr = RHS;
+ }
+
+ if (hasExplicitParentheses(SurroundedExpr, *Result.SourceManager,
+ Result.Context->getLangOpts()))
+ SurroundedExpr = nullptr;
+
+ 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;
+ InsertBrace1 = FixItHint::CreateInsertion(InsertFirstLoc, "(");
+ InsertBrace2 = FixItHint::CreateInsertion(InsertSecondLoc, ")");
+ }
+
+ Diag << InsertEqual << ReplaceOperator << InsertBrace1 << InsertBrace2;
+}
+
+} // namespace clang::tidy::performance
diff --git a/clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.h b/clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.h
new file mode 100644
index 0000000000000..6a5f0c7db6f1b
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.h
@@ -0,0 +1,38 @@
+//===--- 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_PERFORMANCE_BOOLBITWISEOPERATIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_BOOLBITWISEOPERATIONCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::performance {
+
+/// Finds potentially unefficient uses of bitwise operators such as `|`,
+/// `&` and their compound analogues with `bool` type and suggests replacing
+/// them with logical ones, like `||` and `&&`.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance/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;
+ }
+
+private:
+ bool ChangePossibleSideEffects;
+};
+
+} // namespace clang::tidy::performance
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_BOOLBITWISEOPERATIONCHECK_H
diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index c6e547c5089fb..5a600e988d65e 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangTidyPerformanceModule STATIC
AvoidEndlCheck.cpp
+ BoolBitwiseOperationCheck.cpp
EnumSizeCheck.cpp
FasterStringFindCheck.cpp
ForRangeCopyCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 9e0fa6f88b36a..971951213aac1 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -10,6 +10,7 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "AvoidEndlCheck.h"
+#include "BoolBitwiseOperationCheck.h"
#include "EnumSizeCheck.h"
#include "FasterStringFindCheck.h"
#include "ForRangeCopyCheck.h"
@@ -36,6 +37,8 @@ class PerformanceModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<AvoidEndlCheck>("performance-avoid-endl");
+ CheckFactories.registerCheck<BoolBitwiseOperationCheck>(
+ "performance-bool-bitwise-operation");
CheckFactories.registerCheck<EnumSizeCheck>("performance-enum-size");
CheckFactories.registerCheck<FasterStringFindCheck>(
"performance-faster-string-find");
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e0f81a032c38d..6499ed554968f 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -136,6 +136,13 @@ New checks
Finds unintended character output from ``unsigned char`` and ``signed char``
to an ``ostream``.
+- New :doc:`performance-bool-bitwise-operation
+ <clang-tidy/checks/performance/bool-bitwise-operation>` check.
+
+ Finds potentially unefficient uses of bitwise operators such as ``|``,
+ ``&`` and their compound analogues with ``bool`` type and suggests replacing
+ them with logical ones, like ``||`` and ``&&``.
+
- New :doc:`portability-avoid-pragma-once
<clang-tidy/checks/portability/avoid-pragma-once>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 5a79d61b1fd7e..19f96afb06cc0 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -333,6 +333,7 @@ Clang-Tidy Checks
:doc:`openmp-exception-escape <openmp/exception-escape>`,
:doc:`openmp-use-default-none <openmp/use-default-none>`,
:doc:`performance-avoid-endl <performance/avoid-endl>`, "Yes"
+ :doc:`performance-bool-bitwise-operation <performance/bool-bitwise-operation>`, "Yes"
:doc:`performance-enum-size <performance/enum-size>`,
:doc:`performance-faster-string-find <performance/faster-string-find>`, "Yes"
:doc:`performance-for-range-copy <performance/for-range-copy>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst
new file mode 100644
index 0000000000000..762e57352db66
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst
@@ -0,0 +1,40 @@
+.. title:: clang-tidy - performance-bool-bitwise-operation
+
+performance-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 instead of bitwise one for bool
+ invalid |= y > limit.y; // warning: use logical operator instead of bitwise one for bool
+ invalid |= z > limit.z; // warning: use logical operator instead of bitwise one for bool
+ if (invalid) {
+ // error handling
+ }
+
+These 3 warnings suggest to assign result of logical ``||`` operation instead of using ``|=`` 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
+ }
+
+Options
+-------
+
+.. option:: ChangePossibleSideEffects
+
+ Enabling this option promotes more fixit hints even when they might
+ change evaluation order or skip side effects. Default value is `false`.
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-change-possible-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-change-possible-side-effect.cpp
new file mode 100644
index 0000000000000..b22f504d56b4c
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-change-possible-side-effect.cpp
@@ -0,0 +1,83 @@
+// RUN: %check_clang_tidy %s performance-bool-bitwise-operation %t \
+// RUN: -config="{CheckOptions: { \
+// RUN: performance-bool-bitwise-operation.ChangePossibleSideEffects: 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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-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 instead of bitwise one for bool [performance-bool-bitwise-operation]
+ // CHECK-MESSAGES-NOT: :[[@LINE-2]]:{{.*}}: note: FIX-IT applied suggested code changes
+}
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-nontraditional.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-nontraditional.cpp
new file mode 100644
index 0000000000000..e1463a290453d
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/bool-bitwise-operation-nontraditional.cpp
@@ -0,0 +1,388 @@
+// RUN: %check_clang_tidy %s performance-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 __att...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/142324
More information about the cfe-commits
mailing list