https://github.com/irishrover updated https://github.com/llvm/llvm-project/pull/221432
>From 0bd7cd30f578eb32b234a59a64165e6ab8e3fe99 Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Sat, 5 Sep 2026 13:59:09 +0300 Subject: [PATCH] [clang-tidy] Fix DeMorgan for overloaded comparisons Before my patch for Chromium's base/trace_event/memory_allocator_dump.cc: - if (!(name == rhs.name && units == rhs.units && - entry_type == rhs.entry_type)) { + if (!name == rhs.name || !units == rhs.units || + entry_type != rhs.entry_type) { With the patch: - if (!(name == rhs.name && units == rhs.units && - entry_type == rhs.entry_type)) { + if (name != rhs.name || units != rhs.units || + entry_type != rhs.entry_type) { --- .../readability/SimplifyBooleanExprCheck.cpp | 12 ++++++ .../simplify-boolean-expr-demorgan.cpp | 41 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp index 3a63b6f84eed3..50ec10ca0cc24 100644 --- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp @@ -916,6 +916,18 @@ static bool flipDemorganSide(SmallVectorImpl<FixItHint> &Fixes, } if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) return flipDemorganBinaryOperator(Fixes, Ctx, BinOp, OuterBO); + // Overloaded comparisons are represented as CXXOperatorCallExpr rather than + // BinaryOperator, so negate them by replacing their operator location. + if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) { + const StringRef NegatedOperator = negatedOperator(OpCall); + if (!NegatedOperator.empty()) { + if (OpCall->getOperatorLoc().isMacroID()) + return true; + Fixes.push_back(FixItHint::CreateReplacement(OpCall->getOperatorLoc(), + NegatedOperator)); + return false; + } + } if (const auto *Paren = dyn_cast<ParenExpr>(E)) { if (const auto *BinOp = dyn_cast<BinaryOperator>(Paren->getSubExpr())) return flipDemorganBinaryOperator(Fixes, Ctx, BinOp, OuterBO, Paren); diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-boolean-expr-demorgan.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-boolean-expr-demorgan.cpp index bab9e17a7775b..4f3660b4a1c46 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-boolean-expr-demorgan.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-boolean-expr-demorgan.cpp @@ -106,3 +106,44 @@ void foo(bool A1, bool A2, bool A3, bool A4) { // CHECK-FIXES-NEXT: X = A1 || (A2 && A3); // CHECK-FIXES-NEXT: X = A1 && (A2 || A3); } + +// Equality on a user-defined type is an overloaded operator, so its negation +// must replace `==` with `!=`, rather than insert `!` before the left operand. +namespace overloaded_comparisons { +struct Entry { + struct String { + bool operator==(const String &) const; + bool operator!=(const String &) const; + bool operator<(const String &) const; + bool operator>(const String &) const; + bool operator<=(const String &) const; + bool operator>=(const String &) const; + }; + + String name; + String units; + int entry_type; + + bool matches(const Entry &rhs) const { + return !(name == rhs.name && units == rhs.units && + entry_type == rhs.entry_type); + } + // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: boolean expression can be simplified by DeMorgan's theorem [readability-simplify-boolean-expr] + // CHECK-FIXES: return name != rhs.name || units != rhs.units || + // CHECK-FIXES-NEXT: entry_type != rhs.entry_type; + + bool differsFrom(const Entry &rhs) const { + return !(name != rhs.name || entry_type != rhs.entry_type); + } + // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: boolean expression can be simplified by DeMorgan's theorem [readability-simplify-boolean-expr] + // CHECK-FIXES: return name == rhs.name && entry_type == rhs.entry_type; + + bool comparesTo(const Entry &rhs) const { + return !(name < rhs.name && units > rhs.units && name <= rhs.name && + units >= rhs.units && entry_type < rhs.entry_type); + } + // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: boolean expression can be simplified by DeMorgan's theorem [readability-simplify-boolean-expr] + // CHECK-FIXES: return name >= rhs.name || units <= rhs.units || name > rhs.name || + // CHECK-FIXES-NEXT: units < rhs.units || entry_type >= rhs.entry_type; +}; +} // namespace overloaded_comparisons _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
