-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang-tidy] Add performance-bool-bitwise-operation check #142324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang-tidy Author: Denis Mikhailov (denzor200) ChangesAdd new clang-tidy check that finds potentially inefficient use of bitwise operators such as Small example:
Fixes: #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:
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]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some general feedback, mostly docs/wording suggestions.
For ease of review in the future, may you try to make BoolBitwiseOperationCheck::check
function easier to read.
E.g. extract some helper functions like HasVolatileOrSideEffects
, GetTranslatedSpelling
etc..
Mostly to cover noise of many return
statements. Helper functions would be easy to review and we could focus on main logic in check
method.
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.h
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/performance/BoolBitwiseOperationCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/performance/bool-bitwise-operation.rst
Outdated
Show resolved
Hide resolved
Personally I don't think this is a |
✅ With the latest revision this PR passed the C/C++ code formatter. |
Please run Clang-Format over code. |
I've put this in the performance section because evaluating only one operand(which will be in most cases) takes less time than evaluating both operands. I think no place for this check in readability section - someone might say that |
<clang-tidy/checks/performance/bool-bitwise-operation>` check. | ||
|
||
Finds potentially inefficient use of bitwise operators such as ``&``, ``|`` | ||
and their compound analogues on boolean values where logical operators like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and their compound analogues on boolean values where logical operators like | |
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and their compound analogues on boolean values where logical operators like | |
and their compound analogues on Boolean values where logical operators like |
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:
Fixes: #40307