From 710b7b4de1fdef8f4b159d5cc3503f151e8ecbfc Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Tue, 21 Oct 2025 19:52:57 +0300 Subject: [PATCH 01/29] 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 +#include +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::misc { + +static const NamedDecl * +getLHSNamedDeclIfCompoundAssign(const BinaryOperator *BO) { + if (BO->isCompoundAssignmentOp()) { + const auto *DeclRefLHS = + dyn_cast(BO->getLHS()->IgnoreImpCasts()); + return DeclRefLHS ? DeclRefLHS->getDecl() : nullptr; + } + return nullptr; +} + +constexpr std::array, 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("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(DiagEmitter()); + + const bool HasSideEffects = MatchedExpr->getRHS()->HasSideEffects( + *Result.Context, /*IncludePossibleEffects=*/!StrictMode); + if (HasSideEffects) + return static_cast(DiagEmitter()); + + SourceLocation Loc = MatchedExpr->getOperatorLoc(); + + if (Loc.isInvalid() || Loc.isMacroID()) + return static_cast(IgnoreMacros || DiagEmitter()); + + Loc = Result.SourceManager->getSpellingLoc(Loc); + if (Loc.isInvalid() || Loc.isMacroID()) + return static_cast(IgnoreMacros || DiagEmitter()); + + const CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc); + if (TokenRange.isInvalid()) + return static_cast(IgnoreMacros || DiagEmitter()); + + const StringRef FixSpelling = translate(Lexer::getSourceText( + TokenRange, *Result.SourceManager, Result.Context->getLangOpts())); + + if (FixSpelling.empty()) + return static_cast(DiagEmitter()); + + FixItHint InsertEqual; + if (MatchedExpr->isCompoundAssignmentOp()) { + const auto *DeclRefLHS = + dyn_cast(MatchedExpr->getLHS()->IgnoreImpCasts()); + if (!DeclRefLHS) + return static_cast(DiagEmitter()); + const SourceLocation LocLHS = DeclRefLHS->getEndLoc(); + if (LocLHS.isInvalid() || LocLHS.isMacroID()) + return static_cast(IgnoreMacros || DiagEmitter()); + const SourceLocation InsertLoc = clang::Lexer::getLocForEndOfToken( + LocLHS, 0, *Result.SourceManager, Result.Context->getLangOpts()); + if (InsertLoc.isInvalid() || InsertLoc.isMacroID()) + return static_cast(IgnoreMacros || DiagEmitter()); + InsertEqual = FixItHint::CreateInsertion( + InsertLoc, " = " + DeclRefLHS->getDecl()->getNameAsString()); + } + + auto ReplaceOperator = FixItHint::CreateReplacement(TokenRange, FixSpelling); + + const auto *Parent = Result.Nodes.getNodeAs("p"); + std::optional ParentOpcode; + if (Parent) + ParentOpcode = Parent->getOpcode(); + + const auto *RHS = + dyn_cast(MatchedExpr->getRHS()->IgnoreImpCasts()); + std::optional 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(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(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 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( + "misc-bool-bitwise-operation"); CheckFactories.registerCheck( "misc-confusable-identifiers"); CheckFactories.registerCheck( 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 + ` 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 ` 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 `, :doc:`bugprone-virtual-near-miss `, "Yes" :doc:`cert-dcl58-cpp `, + :doc:`cert-env33-c `, :doc:`cert-err33-c `, + :doc:`cert-err52-cpp `, :doc:`cert-err60-cpp `, :doc:`cert-flp30-c `, :doc:`cert-mem57-cpp `, @@ -261,6 +263,7 @@ Clang-Tidy Checks :doc:`llvmlibc-implementation-in-namespace `, :doc:`llvmlibc-inline-function-decl `, "Yes" :doc:`llvmlibc-restrict-system-libc-headers `, "Yes" + :doc:`misc-bool-bitwise-operation `, "Yes" :doc:`misc-confusable-identifiers `, :doc:`misc-const-correctness `, "Yes" :doc:`misc-coroutine-hostile-raii `, @@ -372,7 +375,7 @@ Clang-Tidy Checks :doc:`readability-avoid-nested-conditional-operator `, :doc:`readability-avoid-return-with-void-value `, "Yes" :doc:`readability-avoid-unconditional-preprocessor-if `, - :doc:`readability-braces-around-statements `, "Yes" + :doc:`readability-braces-around-statements `, :doc:`readability-const-return-type `, "Yes" :doc:`readability-container-contains `, "Yes" :doc:`readability-container-data-pointer `, "Yes" @@ -442,9 +445,7 @@ Check aliases :doc:`cert-dcl54-cpp `, :doc:`misc-new-delete-overloads `, :doc:`cert-dcl59-cpp `, :doc:`google-build-namespaces `, :doc:`cert-err09-cpp `, :doc:`misc-throw-by-value-catch-by-reference `, - :doc:`cert-env33-c `, :doc:`bugprone-command-processor `, :doc:`cert-err34-c `, :doc:`bugprone-unchecked-string-to-number-conversion `, - :doc:`cert-err52-cpp `, :doc:`modernize-avoid-setjmp-longjmp `, :doc:`cert-err58-cpp `, :doc:`bugprone-throwing-static-initialization `, :doc:`cert-err61-cpp `, :doc:`misc-throw-by-value-catch-by-reference `, :doc:`cert-exp42-c `, :doc:`bugprone-suspicious-memory-comparison `, @@ -571,12 +572,12 @@ Check aliases :doc:`cppcoreguidelines-non-private-member-variables-in-classes `, :doc:`misc-non-private-member-variables-in-classes `, :doc:`cppcoreguidelines-use-default-member-init `, :doc:`modernize-use-default-member-init `, "Yes" :doc:`fuchsia-header-anon-namespaces `, :doc:`google-build-namespaces `, - :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" + :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, :doc:`google-readability-function-size `, :doc:`readability-function-size `, :doc:`google-readability-namespace-comments `, :doc:`llvm-namespace-comment `, :doc:`hicpp-avoid-c-arrays `, :doc:`modernize-avoid-c-arrays `, :doc:`hicpp-avoid-goto `, :doc:`cppcoreguidelines-avoid-goto `, - :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" + :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, :doc:`hicpp-deprecated-headers `, :doc:`modernize-deprecated-headers `, "Yes" :doc:`hicpp-explicit-conversions `, :doc:`google-explicit-constructor `, "Yes" :doc:`hicpp-function-size `, :doc:`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 + 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 +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 +void good_in_unreachable_template(T a, T b) { + a bitor b; + a bitand b; + a or_eq b; + a and_eq b; +} + +template +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 +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 +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 +void good_in_unreachable_template(T a, T b) { + a | b; + a & b; + a |= b; + a &= b; +} + +template +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 +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 Date: Thu, 6 Nov 2025 19:59:01 +0300 Subject: [PATCH 02/29] 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(S)) { + S = PE->getSubExpr(); + } + return S; +} + +template +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(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()) { + const Expr* InitExpr = nullptr; + + if (const auto* VD = dyn_cast(D)) { + InitExpr = VD->getInit(); + } else if (const auto* FD = dyn_cast(D)) { + InitExpr = FD->getInClassInitializer(); + } else if (const auto* NTTPD = dyn_cast(D)) { + if (NTTPD->getType()->isBooleanType()) { + return true; + } + } + + if (InitExpr && isBooleanImplicitCastStmt(InitExpr)) { + return true; + } + } + + // Check for Stmt parents + if (const auto* S = Parent.template get()) { + 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 OperatorsNames{"|", "&", "|=", "&="}; + constexpr std::array, 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 @@ -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 +// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation] +// CHECK-FIXES: template +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 +// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation] +// CHECK-FIXES: template +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 +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation] +// CHECK-FIXES: template +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 +// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation] +// CHECK-FIXES: template +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 +// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean values instead of bitwise operator '|' [misc-bool-bitwise-operation] +// CHECK-FIXES: template +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(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(true || 1)> +void assign_to_boolean_scast(unsigned flags, bool value) { + struct A { bool a = static_cast(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(true || 1); }; + struct B { union { bool a = static_cast(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(true || 1); }; }; + bool result = static_cast((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((flags << 1) || value); + bool a = static_cast((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((flags << 2) || value), + b = static_cast((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((flags << 4) || value), + c = static_cast((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((flags << 8) || value); + result = static_cast((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((flags << 1) || value); + take(static_cast((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((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 @@ -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 Date: Fri, 7 Nov 2025 19:02:36 +0300 Subject: [PATCH 03/29] 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(S)) { - S = PE->getSubExpr(); - } - return S; -} - -template -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()) { + if (isa(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(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()) { - const Expr* InitExpr = nullptr; - - if (const auto* VD = dyn_cast(D)) { - InitExpr = VD->getInit(); - } else if (const auto* FD = dyn_cast(D)) { - InitExpr = FD->getInClassInitializer(); - } else if (const auto* NTTPD = dyn_cast(D)) { + for (const auto &Parent : Parents) { + const auto *ParentNoParen = ignoreParensTowardsTheRoot(&Parent, AC); + // Special handling for `template` cases + if (const auto *D = ParentNoParen->get()) { + if (const auto *NTTPD = dyn_cast(D)) { if (NTTPD->getType()->isBooleanType()) { return true; } } - - if (InitExpr && isBooleanImplicitCastStmt(InitExpr)) { - return true; - } } - - // Check for Stmt parents - if (const auto* S = Parent.template get()) { - for (const Stmt* Child : S->children()) { - if (isBooleanImplicitCastStmt(Child) && containsNodeIgnoringParenExpr(Child->children(), &Node)) { + + if (const auto *S = ParentNoParen->get()) { + if (const auto *ICE = dyn_cast(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 OperatorsNames{"|", "&", "|=", "&="}; - constexpr std::array, 8U> OperatorsTransformation{{{"|", "||"}, {"|=", "||"}, @@ -103,13 +79,32 @@ constexpr std::array, 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("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(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(DiagEmitter()); - SourceLocation Loc = MatchedExpr->getOperatorLoc(); + SourceLocation Loc = BinOp->getOperatorLoc(); if (Loc.isInvalid() || Loc.isMacroID()) return static_cast(IgnoreMacros || DiagEmitter()); - Loc = Result.SourceManager->getSpellingLoc(Loc); + Loc = SM.getSpellingLoc(Loc); if (Loc.isInvalid() || Loc.isMacroID()) return static_cast(IgnoreMacros || DiagEmitter()); @@ -177,23 +163,23 @@ void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) { if (TokenRange.isInvalid()) return static_cast(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(DiagEmitter()); FixItHint InsertEqual; - if (MatchedExpr->isCompoundAssignmentOp()) { + if (BinOp->isCompoundAssignmentOp()) { const auto *DeclRefLHS = - dyn_cast(MatchedExpr->getLHS()->IgnoreImpCasts()); + dyn_cast(BinOp->getLHS()->IgnoreImpCasts()); if (!DeclRefLHS) return static_cast(DiagEmitter()); const SourceLocation LocLHS = DeclRefLHS->getEndLoc(); if (LocLHS.isInvalid() || LocLHS.isMacroID()) return static_cast(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(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("p"); std::optional ParentOpcode; - if (Parent) - ParentOpcode = Parent->getOpcode(); + if (ParentBinOp) + ParentOpcode = ParentBinOp->getOpcode(); - const auto *RHS = - dyn_cast(MatchedExpr->getRHS()->IgnoreImpCasts()); + const auto *RHS = dyn_cast(BinOp->getRHS()->IgnoreImpCasts()); std::optional 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(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(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(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp, + SM, Ctx); + visitBinaryTreesNode( + dyn_cast(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp, + SM, Ctx); +} + +void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) { + const auto *binOpRoot = Result.Nodes.getNodeAs("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 Date: Fri, 7 Nov 2025 20:01:30 +0300 Subject: [PATCH 04/29] 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& 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& rootAssignsToBoolean) { if (!BinOp) { return; } - if (isBooleanBitwise(BinOp, &Ctx)) { + if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean)) { emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx); } visitBinaryTreesNode( dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp, - SM, Ctx); + SM, Ctx, rootAssignsToBoolean); visitBinaryTreesNode( dyn_cast(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp, - SM, Ctx); + SM, Ctx, rootAssignsToBoolean); } void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) { const auto *binOpRoot = Result.Nodes.getNodeAs("binOpRoot"); const SourceManager &SM = *Result.SourceManager; ASTContext &Ctx = *Result.Context; - visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx); + std::optional 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& 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 // 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 @@ -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 @@ -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((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((flags << 1) || value)); + result = static_cast((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((flags << 1) || (flags << 2) || value); + result = static_cast((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((flags << 1) || (flags << 2) || (flags << 4) || value); } From 52844e3cc54061a7c8733dd3cdaa18405633740f Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Fri, 7 Nov 2025 20:01:54 +0300 Subject: [PATCH 05/29] 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` cases if (const auto *D = ParentNoParen->get()) { if (const auto *NTTPD = dyn_cast(D)) { - if (NTTPD->getType()->isBooleanType()) { + if (NTTPD->getType()->isBooleanType()) return true; - } } } if (const auto *S = ParentNoParen->get()) { if (const auto *ICE = dyn_cast(S)) { - if (ICE->getType()->isBooleanType()) { + if (ICE->getType()->isBooleanType()) return true; - } } } } @@ -79,9 +77,8 @@ constexpr std::array, 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& rootAssignsToBoolean) { - if (!BinOp) { + if (!BinOp) return; - } - if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean)) { + if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean)) emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx); - } visitBinaryTreesNode( dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp, From d7ae3058c0e0a42c85dd5af8fff7a85b446830eb Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Sat, 8 Nov 2025 01:37:32 +0300 Subject: [PATCH 06/29] 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 Date: Sat, 8 Nov 2025 14:28:42 +0300 Subject: [PATCH 07/29] 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 #include +// 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& rootAssignsToBoolean) { + //llvm::outs() << "ENTER " << rootAssignsToBoolean << "\n"; if (!BinOp) return; @@ -244,6 +251,8 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode( visitBinaryTreesNode( dyn_cast(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 Date: Sat, 8 Nov 2025 15:03:05 +0300 Subject: [PATCH 08/29] 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` cases if (const auto *D = ParentNoParen->get()) { if (const auto *NTTPD = dyn_cast(D)) { - if (NTTPD->getType()->isBooleanType()) + if (NTTPD->getType().getDesugaredType(*AC)->isBooleanType()) return true; } } if (const auto *S = ParentNoParen->get()) { if (const auto *ICE = dyn_cast(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(DiagEmitter()); From 352d11840dc652bd1ac6178fd1e2e93cdada8dee Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Sat, 8 Nov 2025 19:20:58 +0300 Subject: [PATCH 09/29] 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& 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 DummyFlag = false; (lhsBoolean || isBooleanBitwise(dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), AC, DummyFlag)) && (rhsBoolean || isBooleanBitwise(dyn_cast(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 @@ -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 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 @@ -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 Date: Sat, 8 Nov 2025 19:51:01 +0300 Subject: [PATCH 10/29] 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 #include -// 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& rootAssignsToBoolean) { +static bool isBooleanBitwise(const BinaryOperator *BinOp, ASTContext *AC, + std::optional &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 DummyFlag = false; (lhsBoolean || isBooleanBitwise(dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), AC, DummyFlag)) && (rhsBoolean || isBooleanBitwise(dyn_cast(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 DummyFlag = false; + lhsBoolean = + lhsBoolean || + isBooleanBitwise(dyn_cast( + BinOp->getLHS()->IgnoreParenImpCasts()), + AC, DummyFlag); + rhsBoolean = + rhsBoolean || + isBooleanBitwise(dyn_cast( + 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(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& rootAssignsToBoolean) { - //llvm::outs() << "ENTER " << rootAssignsToBoolean << "\n"; + std::optional &rootAssignsToBoolean) { if (!BinOp) return; @@ -264,8 +275,6 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode( visitBinaryTreesNode( dyn_cast(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 -// 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 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 -// 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 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 -// 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 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 -// 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 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 -// 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 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(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(true || 1)> void assign_to_boolean_scast(unsigned flags, bool value) { struct A { bool a = static_cast(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(true || 1); }; struct B { union { bool a = static_cast(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(true || 1); }; }; bool result = static_cast((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((flags << 1) || value); bool a = static_cast((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((flags << 2) || value), b = static_cast((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((flags << 4) || value), c = static_cast((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((flags << 8) || value); result = static_cast((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((flags << 1) || value); take(static_cast((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((flags << 1) || value)); result = static_cast((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((flags << 1) || (flags << 2) || value); result = static_cast((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((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 Date: Sat, 8 Nov 2025 21:37:57 +0300 Subject: [PATCH 11/29] 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(BO->getLHS()->IgnoreImpCasts()); - return DeclRefLHS ? DeclRefLHS->getDecl() : nullptr; + if (const auto *DeclRefLHS = dyn_cast(BO->getLHS()->IgnoreImpCasts())) + return DeclRefLHS->getDecl(); + else if (const auto *MemberLHS = dyn_cast(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(BinOp->getLHS()->IgnoreImpCasts())) + return DeclRefLHS; + else if (const auto *MemberLHS = dyn_cast(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(BinOp->getLHS()->IgnoreImpCasts())) << ND << BinOp->getOpcodeStr(); }; @@ -201,19 +212,22 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible( FixItHint InsertEqual; if (BinOp->isCompoundAssignmentOp()) { - const auto *DeclRefLHS = - dyn_cast(BinOp->getLHS()->IgnoreImpCasts()); - if (!DeclRefLHS) + const auto *LHS = getValidCompoundsLHS(BinOp); + if (!LHS) return static_cast(DiagEmitter()); - const SourceLocation LocLHS = DeclRefLHS->getEndLoc(); + const SourceLocation LocLHS = LHS->getEndLoc(); if (LocLHS.isInvalid() || LocLHS.isMacroID()) return static_cast(IgnoreMacros || DiagEmitter()); const SourceLocation InsertLoc = clang::Lexer::getLocForEndOfToken(LocLHS, 0, SM, Ctx.getLangOpts()); if (InsertLoc.isInvalid() || InsertLoc.isMacroID()) return static_cast(IgnoreMacros || DiagEmitter()); - InsertEqual = FixItHint::CreateInsertion( - InsertLoc, " = " + DeclRefLHS->getDecl()->getNameAsString()); + auto SourceText = static_cast(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 Date: Sat, 8 Nov 2025 21:46:08 +0300 Subject: [PATCH 12/29] 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(BO->getLHS()->IgnoreImpCasts())) - return DeclRefLHS->getDecl(); - else if (const auto *MemberLHS = dyn_cast(BO->getLHS()->IgnoreImpCasts())) - return MemberLHS->getMemberDecl(); - } - return nullptr; -} - constexpr std::array, 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(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 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 From 6457ade991c847945d0f711e00eb7382450be070 Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Sat, 8 Nov 2025 21:50:54 +0300 Subject: [PATCH 13/29] 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 &rootAssignsToBoolean) { + std::optional &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 DummyFlag = false; - lhsBoolean = - lhsBoolean || + IsBooleanLHS = + IsBooleanLHS || isBooleanBitwise(dyn_cast( BinOp->getLHS()->IgnoreParenImpCasts()), AC, DummyFlag); - rhsBoolean = - rhsBoolean || + IsBooleanRHS = + IsBooleanRHS || isBooleanBitwise(dyn_cast( 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(BinOp->getLHS()->IgnoreImpCasts())) + + if (const auto *DeclRefLHS = + dyn_cast(BinOp->getLHS()->IgnoreImpCasts())) return DeclRefLHS; - else if (const auto *MemberLHS = dyn_cast(BinOp->getLHS()->IgnoreImpCasts())) + else if (const auto *MemberLHS = + dyn_cast(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(IgnoreMacros || DiagEmitter()); auto SourceText = static_cast(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 &rootAssignsToBoolean) { + std::optional &RootAssignsToBoolean) { if (!BinOp) return; - if (isBooleanBitwise(BinOp, &Ctx, rootAssignsToBoolean)) + if (isBooleanBitwise(BinOp, &Ctx, RootAssignsToBoolean)) emitWarningAndChangeOperatorsIfPossible(BinOp, ParentBinOp, SM, Ctx); visitBinaryTreesNode( dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), BinOp, - SM, Ctx, rootAssignsToBoolean); + SM, Ctx, RootAssignsToBoolean); visitBinaryTreesNode( dyn_cast(BinOp->getRHS()->IgnoreParenImpCasts()), BinOp, - SM, Ctx, rootAssignsToBoolean); + SM, Ctx, RootAssignsToBoolean); } void BoolBitwiseOperationCheck::check(const MatchFinder::MatchResult &Result) { const auto *binOpRoot = Result.Nodes.getNodeAs("binOpRoot"); const SourceManager &SM = *Result.SourceManager; ASTContext &Ctx = *Result.Context; - std::optional rootAssignsToBoolean = std::nullopt; - visitBinaryTreesNode(binOpRoot, nullptr, SM, Ctx, rootAssignsToBoolean); + std::optional 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& rootAssignsToBoolean); + std::optional &rootAssignsToBoolean); private: bool StrictMode; From 7c6552f01b2c194a2fd5114da1d3ac5b4245470d Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Sat, 8 Nov 2025 22:03:08 +0300 Subject: [PATCH 14/29] 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 `, :doc:`bugprone-virtual-near-miss `, "Yes" :doc:`cert-dcl58-cpp `, - :doc:`cert-env33-c `, :doc:`cert-err33-c `, - :doc:`cert-err52-cpp `, :doc:`cert-err60-cpp `, :doc:`cert-flp30-c `, :doc:`cert-mem57-cpp `, @@ -375,7 +373,7 @@ Clang-Tidy Checks :doc:`readability-avoid-nested-conditional-operator `, :doc:`readability-avoid-return-with-void-value `, "Yes" :doc:`readability-avoid-unconditional-preprocessor-if `, - :doc:`readability-braces-around-statements `, + :doc:`readability-braces-around-statements `, "Yes" :doc:`readability-const-return-type `, "Yes" :doc:`readability-container-contains `, "Yes" :doc:`readability-container-data-pointer `, "Yes" @@ -445,7 +443,9 @@ Check aliases :doc:`cert-dcl54-cpp `, :doc:`misc-new-delete-overloads `, :doc:`cert-dcl59-cpp `, :doc:`google-build-namespaces `, :doc:`cert-err09-cpp `, :doc:`misc-throw-by-value-catch-by-reference `, + :doc:`cert-env33-c `, :doc:`bugprone-command-processor `, :doc:`cert-err34-c `, :doc:`bugprone-unchecked-string-to-number-conversion `, + :doc:`cert-err52-cpp `, :doc:`modernize-avoid-setjmp-longjmp `, :doc:`cert-err58-cpp `, :doc:`bugprone-throwing-static-initialization `, :doc:`cert-err61-cpp `, :doc:`misc-throw-by-value-catch-by-reference `, :doc:`cert-exp42-c `, :doc:`bugprone-suspicious-memory-comparison `, @@ -572,12 +572,12 @@ Check aliases :doc:`cppcoreguidelines-non-private-member-variables-in-classes `, :doc:`misc-non-private-member-variables-in-classes `, :doc:`cppcoreguidelines-use-default-member-init `, :doc:`modernize-use-default-member-init `, "Yes" :doc:`fuchsia-header-anon-namespaces `, :doc:`google-build-namespaces `, - :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, + :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" :doc:`google-readability-function-size `, :doc:`readability-function-size `, :doc:`google-readability-namespace-comments `, :doc:`llvm-namespace-comment `, :doc:`hicpp-avoid-c-arrays `, :doc:`modernize-avoid-c-arrays `, :doc:`hicpp-avoid-goto `, :doc:`cppcoreguidelines-avoid-goto `, - :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, + :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" :doc:`hicpp-deprecated-headers `, :doc:`modernize-deprecated-headers `, "Yes" :doc:`hicpp-explicit-conversions `, :doc:`google-explicit-constructor `, "Yes" :doc:`hicpp-function-size `, :doc:`readability-function-size `, @@ -602,4 +602,4 @@ Check aliases :doc:`hicpp-use-override `, :doc:`modernize-use-override `, "Yes" :doc:`hicpp-vararg `, :doc:`cppcoreguidelines-pro-type-vararg `, :doc:`llvm-else-after-return `, :doc:`readability-else-after-return `, "Yes" - :doc:`llvm-qualified-auto `, :doc:`readability-qualified-auto `, "Yes" + :doc:`llvm-qualified-auto `, :doc:`readability-qualified-auto `, "Yes" \ No newline at end of file From 2aaa9285f51bc45135b901fd68c0f1c508183d18 Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Sun, 9 Nov 2025 02:02:54 +0300 Subject: [PATCH 15/29] 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 &RootAssignsToBoolean); + +static bool recheckIsBooleanDeeply(const BinaryOperator *BinOp, ASTContext *AC, + bool &IsBooleanLHS, bool &IsBooleanRHS) { + std::optional DummyFlag = false; + IsBooleanLHS = IsBooleanLHS || + isBooleanBitwise(dyn_cast( + BinOp->getLHS()->IgnoreParenImpCasts()), + AC, DummyFlag); + IsBooleanRHS = IsBooleanRHS || + isBooleanBitwise(dyn_cast( + 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 &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 DummyFlag = false; - IsBooleanLHS = - IsBooleanLHS || - isBooleanBitwise(dyn_cast( - BinOp->getLHS()->IgnoreParenImpCasts()), - AC, DummyFlag); - IsBooleanRHS = - IsBooleanRHS || - isBooleanBitwise(dyn_cast( - 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(DiagEmitter()); const SourceLocation LocLHS = LHS->getEndLoc(); From 75a5399deac0599ce9da27a3dadbbee3d7d4f4aa Mon Sep 17 00:00:00 2001 From: Denis Mikhailov Date: Sun, 9 Nov 2025 02:35:11 +0300 Subject: [PATCH 16/29] 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 &RootAssignsToBoolean); - -static bool recheckIsBooleanDeeply(const BinaryOperator *BinOp, ASTContext *AC, - bool &IsBooleanLHS, bool &IsBooleanRHS) { - std::optional DummyFlag = false; - IsBooleanLHS = IsBooleanLHS || - isBooleanBitwise(dyn_cast( - BinOp->getLHS()->IgnoreParenImpCasts()), - AC, DummyFlag); - IsBooleanRHS = IsBooleanRHS || - isBooleanBitwise(dyn_cast( - 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 &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 DummyFlag = false; + IsBooleanLHS = + IsBooleanLHS || + isBooleanBitwise( + dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), + AC, DummyFlag); + IsBooleanRHS = + IsBooleanRHS || + isBooleanBitwise( + dyn_cast(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 Date: Wed, 12 Nov 2025 20:23:50 +0300 Subject: [PATCH 17/29] 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` cases - if (const auto *D = ParentNoParen->get()) { - if (const auto *NTTPD = dyn_cast(D)) { - if (NTTPD->getType().getDesugaredType(*AC)->isBooleanType()) - return true; - } - } - - if (const auto *S = ParentNoParen->get()) { + if (const auto *S = ignoreParensTowardsTheRoot(&Parent, AC)->get()) { if (const auto *ICE = dyn_cast(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 -// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation] -// CHECK-FIXES: template +// FIXME: implement `template` 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 -// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation] -// CHECK-FIXES: template 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 -// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation] -// CHECK-FIXES: template 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 -// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation] -// CHECK-FIXES: template 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 -// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use logical operator '||' for boolean semantics instead of bitwise operator '|' [misc-bool-bitwise-operation] -// CHECK-FIXES: template 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(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(true || 1)> void assign_to_boolean_scast(unsigned flags, bool value) { struct A { bool a = static_cast(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 Date: Wed, 12 Nov 2025 20:55:49 +0300 Subject: [PATCH 18/29] 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(BinOp->getLHS()->IgnoreImpCasts())) return DeclRefLHS; - else if (const auto *MemberLHS = - dyn_cast(BinOp->getLHS()->IgnoreImpCasts())) + if (const auto *MemberLHS = + dyn_cast(BinOp->getLHS()->IgnoreImpCasts())) return MemberLHS; return nullptr; @@ -168,50 +168,68 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible( .getDesugaredType(Ctx) .isVolatileQualified(); }); - if (HasVolatileOperand) - return static_cast(DiagEmitter()); + if (HasVolatileOperand) { + DiagEmitter(); + return; + } const bool HasSideEffects = BinOp->getRHS()->HasSideEffects( Ctx, /*IncludePossibleEffects=*/!StrictMode); - if (HasSideEffects) - return static_cast(DiagEmitter()); + if (HasSideEffects) { + DiagEmitter(); + return; + } SourceLocation Loc = BinOp->getOperatorLoc(); - if (Loc.isInvalid() || Loc.isMacroID()) - return static_cast(IgnoreMacros || DiagEmitter()); + if (Loc.isInvalid() || Loc.isMacroID()) { + IgnoreMacros || DiagEmitter(); + return; + } Loc = SM.getSpellingLoc(Loc); - if (Loc.isInvalid() || Loc.isMacroID()) - return static_cast(IgnoreMacros || DiagEmitter()); + if (Loc.isInvalid() || Loc.isMacroID()) { + IgnoreMacros || DiagEmitter(); + return; + } const CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc); - if (TokenRange.isInvalid()) - return static_cast(IgnoreMacros || DiagEmitter()); + if (TokenRange.isInvalid()) { + IgnoreMacros || DiagEmitter(); + return; + } const StringRef FixSpelling = translate(Lexer::getSourceText(TokenRange, SM, Ctx.getLangOpts())); - if (FixSpelling.empty()) - return static_cast(DiagEmitter()); + if (FixSpelling.empty()) { + DiagEmitter(); + return; + } FixItHint InsertEqual; if (BinOp->isCompoundAssignmentOp()) { const auto *LHS = getAcceptableCompoundsLHS(BinOp); - if (!LHS) - return static_cast(DiagEmitter()); + if (!LHS) { + DiagEmitter(); + return; + } const SourceLocation LocLHS = LHS->getEndLoc(); - if (LocLHS.isInvalid() || LocLHS.isMacroID()) - return static_cast(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(IgnoreMacros || DiagEmitter()); + if (InsertLoc.isInvalid() || InsertLoc.isMacroID()) { + IgnoreMacros || DiagEmitter(); + return; + } auto SourceText = static_cast(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(SurroundedExpr)) + if (isa_and_nonnull(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(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("binOpRoot"); + const auto *BinOpRoot = Result.Nodes.getNodeAs("binOpRoot"); const SourceManager &SM = *Result.SourceManager; ASTContext &Ctx = *Result.Context; std::optional 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 &rootAssignsToBoolean); + std::optional &RootAssignsToBoolean); -private: bool StrictMode; bool IgnoreMacros; }; From aaf2612e509e58179b7efa194f852215b4fefca6 Mon Sep 17 00:00:00 2001 From: denzor200 Date: Wed, 12 Nov 2025 21:16:18 +0300 Subject: [PATCH 19/29] 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 &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 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 Date: Fri, 14 Nov 2025 01:11:55 +0300 Subject: [PATCH 20/29] 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 Date: Fri, 14 Nov 2025 01:16:26 +0300 Subject: [PATCH 21/29] 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 Date: Fri, 14 Nov 2025 02:00:42 +0300 Subject: [PATCH 22/29] 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()) { if (isa(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, 8U> +static constexpr std::array, 8U> OperatorsTransformation{{{"|", "||"}, {"|=", "||"}, {"&", "&&"}, @@ -56,7 +56,7 @@ constexpr std::array, 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 `, :doc:`modernize-use-override `, "Yes" :doc:`hicpp-vararg `, :doc:`cppcoreguidelines-pro-type-vararg `, :doc:`llvm-else-after-return `, :doc:`readability-else-after-return `, "Yes" - :doc:`llvm-qualified-auto `, :doc:`readability-qualified-auto `, "Yes" \ No newline at end of file + :doc:`llvm-qualified-auto `, :doc:`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 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 -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 -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 Date: Fri, 14 Nov 2025 02:07:21 +0300 Subject: [PATCH 23/29] 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 Date: Fri, 14 Nov 2025 02:12:15 +0300 Subject: [PATCH 24/29] 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 Date: Fri, 14 Nov 2025 20:04:45 +0300 Subject: [PATCH 25/29] 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()) { - if (const auto *ICE = dyn_cast(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(); + const auto *ICE = dyn_cast_if_present(S); + return ICE ? ICE->getType().getDesugaredType(*AC)->isBooleanType() : false; + }); } static constexpr std::array, 8U> From 4e7cdc4f1073d0e70f3ca533f1f1c9a35a3cf617 Mon Sep 17 00:00:00 2001 From: denzor200 Date: Thu, 20 Nov 2025 21:29:42 +0300 Subject: [PATCH 26/29] 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()) { - if (isa(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(); isa_and_nonnull(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 DummyFlag = false; - IsBooleanLHS = - IsBooleanLHS || - isBooleanBitwise( - dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), - AC, DummyFlag); - IsBooleanRHS = - IsBooleanRHS || - isBooleanBitwise( - dyn_cast(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 DummyFlag = false; + IsBooleanLHS = + IsBooleanLHS || + isBooleanBitwise( + dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), + AC, DummyFlag); + IsBooleanRHS = + IsBooleanRHS || + isBooleanBitwise( + dyn_cast(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(BinOp->getLHS()->IgnoreImpCasts())) - return DeclRefLHS; - if (const auto *MemberLHS = - dyn_cast(BinOp->getLHS()->IgnoreImpCasts())) - return MemberLHS; - - return nullptr; + const Expr *LHS = BinOp->getLHS()->IgnoreImpCasts(); + return isa(LHS) ? LHS : nullptr; } BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name, From b3af19666ca724858cd314affbde3ff38105eda5 Mon Sep 17 00:00:00 2001 From: denzor200 Date: Thu, 20 Nov 2025 21:41:10 +0300 Subject: [PATCH 27/29] 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 DummyFlag = false; - IsBooleanLHS = - IsBooleanLHS || - isBooleanBitwise( - dyn_cast(BinOp->getLHS()->IgnoreParenImpCasts()), - AC, DummyFlag); - IsBooleanRHS = - IsBooleanRHS || - isBooleanBitwise( - dyn_cast(BinOp->getRHS()->IgnoreParenImpCasts()), - AC, DummyFlag); + IsBooleanLHS = IsBooleanLHS || + isBooleanBitwise(dyn_cast( + BinOp->getLHS()->IgnoreParenImpCasts()), + AC, DummyFlag); + IsBooleanRHS = IsBooleanRHS || + isBooleanBitwise(dyn_cast( + BinOp->getRHS()->IgnoreParenImpCasts()), + AC, DummyFlag); if (IsBooleanLHS && IsBooleanRHS) { RootAssignsToBoolean = RootAssignsToBoolean.value_or(false); From d0a3b18b2d8645aa38ba06e5cabc243ece4c25fc Mon Sep 17 00:00:00 2001 From: denzor200 Date: Sat, 22 Nov 2025 00:15:00 +0300 Subject: [PATCH 28/29] 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 Date: Sat, 22 Nov 2025 00:53:02 +0300 Subject: [PATCH 29/29] 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;