[clang-tools-extra] [clang-tidy] fix false positive of parentheses removal for overloaded operator (PR #192254)
Gaurav Dhingra via cfe-commits
cfe-commits at lists.llvm.org
Sat May 16 06:41:20 PDT 2026
https://github.com/gxyd updated https://github.com/llvm/llvm-project/pull/192254
>From f2f9d99a2abad3e592d66181bba61ca953479981 Mon Sep 17 00:00:00 2001
From: Gaurav Dhingra <gauravdhingra.gxyd at gmail.com>
Date: Wed, 15 Apr 2026 18:23:01 +0530
Subject: [PATCH 1/3] [clang-tidy] fix false positive of parentheses removal
for overloaded operator
Fixes #189217
don't remove necessary parentheses for an overloaded operator, when
the parenthese occurs in the context of a binary operation
E.g. (E1 & E2) != E3 // the brackets aren't redundant here
E.g. (E1 & E2) // brackets are redundant here
---
.../readability/RedundantParenthesesCheck.cpp | 4 ++-
.../readability/redundant-parentheses.cpp | 33 +++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp
index 9b3948a1c50c0..f1056ad3712e3 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp
@@ -58,7 +58,9 @@ void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {
memberExpr(), callExpr())),
unless(anyOf(isInMacro(),
// sizeof(...) is common used.
- hasParent(unaryExprOrTypeTraitExpr()))))
+ hasParent(unaryExprOrTypeTraitExpr()),
+ allOf(hasDescendant(cxxOperatorCallExpr()),
+ hasParent(binaryOperator())))))
.bind("dup"),
this);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp
index 9a8a0d4d73483..6dad9ef1086e3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp
@@ -121,3 +121,36 @@ void memberExpr() {
// CHECK-FIXES: if (foo.fooBar().z) {
}
}
+
+enum class FoldLevel {
+ None = 0x0,
+ HeaderFlag = 0x2000,
+};
+
+constexpr FoldLevel operator&(FoldLevel lhs, FoldLevel rhs) {
+ return static_cast<FoldLevel>(static_cast<int>(lhs) & static_cast<int>(rhs));
+}
+
+constexpr bool UseOperatorAmpersand1(FoldLevel level) {
+ return (level & FoldLevel::HeaderFlag) != FoldLevel::None;
+}
+
+constexpr bool UseOperatorAmpersand2(FoldLevel level) {
+ const FoldLevel l = (level & FoldLevel::HeaderFlag);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant parentheses around expression [readability-redundant-parentheses]
+ // CHECK-FIXES: const FoldLevel l = level & FoldLevel::HeaderFlag;
+ return l != FoldLevel::None;
+}
+
+constexpr bool UseOperatorAmpersand3(FoldLevel level) {
+ const FoldLevel l = level & FoldLevel::HeaderFlag;
+ return (l != FoldLevel::None);
+}
+
+constexpr bool UseOperatorAmpersand4(FoldLevel level) {
+ return ((level & FoldLevel::HeaderFlag) != FoldLevel::None);
+}
+
+const int bracket_int_plus_num = (4) + 5;
+// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: redundant parentheses around expression [readability-redundant-parentheses]
+// CHECK-FIXES: const int bracket_int_plus_num = 4 + 5;
>From 6bf46161304862e6c259a434c9164c998ade01ae Mon Sep 17 00:00:00 2001
From: Gaurav Dhingra <gauravdhingra.gxyd at gmail.com>
Date: Wed, 15 Apr 2026 18:32:19 +0530
Subject: [PATCH 2/3] add release notes entry
---
clang-tools-extra/docs/ReleaseNotes.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index d2db3dc2b3e78..da9a409ad322e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -577,6 +577,11 @@ Changes in existing checks
`IgnoreMacros` option to suppress warnings when the initializer involves
macros that may expand differently in other configurations.
+- Improved :doc:`readability-redundant-parentheses
+ <clang-tidy/checks/readability/redundant-parentheses>` check by fixing a
+ false positive for parentheses present around an overloaded operator in the
+ context of a binary operation.
+
- Improved :doc:`readability-redundant-preprocessor
<clang-tidy/checks/readability/redundant-preprocessor>` check by fixing a
false positive for nested ``#if`` directives using different builtin
>From 7e2da417c3ecd24f9a676c8e20feeb23c309296e Mon Sep 17 00:00:00 2001
From: Gaurav Dhingra <gauravdhingra.gxyd at gmail.com>
Date: Fri, 15 May 2026 19:03:18 +0530
Subject: [PATCH 3/3] use 'has' instead of 'hasDescendant', add more tests
---
.../readability/RedundantParenthesesCheck.cpp | 2 +-
.../readability/redundant-parentheses.cpp | 30 +++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp
index f1056ad3712e3..22b94cdc93d20 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp
@@ -59,7 +59,7 @@ void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {
unless(anyOf(isInMacro(),
// sizeof(...) is common used.
hasParent(unaryExprOrTypeTraitExpr()),
- allOf(hasDescendant(cxxOperatorCallExpr()),
+ allOf(has(cxxOperatorCallExpr()),
hasParent(binaryOperator())))))
.bind("dup"),
this);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp
index 6dad9ef1086e3..8557591f6254b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp
@@ -127,10 +127,23 @@ enum class FoldLevel {
HeaderFlag = 0x2000,
};
+int FoldLevelToInt(FoldLevel l) {
+ return static_cast<int>(l);
+}
+
constexpr FoldLevel operator&(FoldLevel lhs, FoldLevel rhs) {
return static_cast<FoldLevel>(static_cast<int>(lhs) & static_cast<int>(rhs));
}
+constexpr FoldLevel operator*(FoldLevel lhs, FoldLevel rhs) {
+ return static_cast<FoldLevel>(static_cast<int>(lhs) * static_cast<int>(rhs));
+}
+
+
+constexpr FoldLevel operator+(FoldLevel lhs, FoldLevel rhs) {
+ return lhs;
+}
+
constexpr bool UseOperatorAmpersand1(FoldLevel level) {
return (level & FoldLevel::HeaderFlag) != FoldLevel::None;
}
@@ -151,6 +164,23 @@ constexpr bool UseOperatorAmpersand4(FoldLevel level) {
return ((level & FoldLevel::HeaderFlag) != FoldLevel::None);
}
+constexpr bool UseOperatorAmpersand5(FoldLevel level) {
+ return FoldLevel::None != (level & FoldLevel::HeaderFlag);
+}
+
+constexpr bool UseOperatorAmpersand6(FoldLevel level) {
+ FoldLevel hf = FoldLevel::HeaderFlag;
+ return (((level & hf) * hf) != FoldLevel::None);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant parentheses around expression [readability-redundant-parentheses]
+ // CHECK-FIXES: return ((level & hf * hf) != FoldLevel::None);
+}
+
+constexpr bool UseOperatorPlus1(FoldLevel level) {
+ return (FoldLevelToInt(level + FoldLevel::None)) != 1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant parentheses around expression [readability-redundant-parentheses]
+ // CHECK-FIXES: return FoldLevelToInt(level + FoldLevel::None) != 1;
+}
+
const int bracket_int_plus_num = (4) + 5;
// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: redundant parentheses around expression [readability-redundant-parentheses]
// CHECK-FIXES: const int bracket_int_plus_num = 4 + 5;
More information about the cfe-commits
mailing list