Skip to content

Commit 1da70ad

Browse files
authored
[clang-tidy] Fix false positive of parentheses removal for overloaded operator (llvm#192254)
Fixes llvm#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
1 parent 846bfd7 commit 1da70ad

3 files changed

Lines changed: 93 additions & 1 deletion

File tree

clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {
5555
parenExpr(), ConstantExpr,
5656
declRefExpr(to(namedDecl(unless(
5757
matchers::matchesAnyListedRegexName(AllowedDecls))))),
58-
memberExpr(), callExpr())),
58+
memberExpr(), callExpr(unless(cxxOperatorCallExpr())))),
5959
unless(anyOf(isInMacro(),
6060
// sizeof(...) is common used.
6161
hasParent(unaryExprOrTypeTraitExpr()))))

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,11 @@ Changes in existing checks
728728
`IgnoreMacros` option to suppress warnings when the initializer involves
729729
macros that may expand differently in other configurations.
730730

731+
- Improved :doc:`readability-redundant-parentheses
732+
<clang-tidy/checks/readability/redundant-parentheses>` check by fixing a
733+
false positive for parentheses present around an overloaded operator in the
734+
context of a binary operation.
735+
731736
- Improved :doc:`readability-redundant-preprocessor
732737
<clang-tidy/checks/readability/redundant-preprocessor>` check by fixing a
733738
false positive for nested ``#if`` directives using different builtin

clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,90 @@ void memberExpr() {
121121
// CHECK-FIXES: if (foo.fooBar().z) {
122122
}
123123
}
124+
125+
enum class FoldLevel {
126+
None = 0x0,
127+
HeaderFlag = 0x2000,
128+
};
129+
130+
int FoldLevelToInt(FoldLevel l) {
131+
return static_cast<int>(l);
132+
}
133+
134+
constexpr FoldLevel operator&(FoldLevel lhs, FoldLevel rhs) {
135+
return static_cast<FoldLevel>(static_cast<int>(lhs) & static_cast<int>(rhs));
136+
}
137+
138+
constexpr FoldLevel operator*(FoldLevel lhs, FoldLevel rhs) {
139+
return static_cast<FoldLevel>(static_cast<int>(lhs) * static_cast<int>(rhs));
140+
}
141+
142+
constexpr FoldLevel operator!(FoldLevel operand) {
143+
return static_cast<FoldLevel>(!static_cast<int>(operand));
144+
}
145+
146+
147+
constexpr FoldLevel operator+(FoldLevel lhs, FoldLevel rhs) {
148+
return lhs;
149+
}
150+
151+
constexpr bool UseOperatorAmpersand1(FoldLevel level) {
152+
return (level & FoldLevel::HeaderFlag) != FoldLevel::None;
153+
}
154+
155+
constexpr bool UseOperatorAmpersand2(FoldLevel level) {
156+
const FoldLevel l = level & FoldLevel::HeaderFlag;
157+
return (l != FoldLevel::None);
158+
}
159+
160+
constexpr bool UseOperatorAmpersand3(FoldLevel level) {
161+
return ((level & FoldLevel::HeaderFlag) != FoldLevel::None);
162+
}
163+
164+
constexpr bool UseOperatorAmpersand4(FoldLevel level) {
165+
return FoldLevel::None != (level & FoldLevel::HeaderFlag);
166+
}
167+
168+
constexpr bool UseOperatorAmpersand5(FoldLevel level) {
169+
FoldLevel hf = FoldLevel::HeaderFlag;
170+
// currently this check doesn't take into account order of operations, so the
171+
// parentheses around `left & rhs` is needed
172+
return ((level & hf) * hf) != FoldLevel::None;
173+
}
174+
175+
constexpr bool UseOperatorAmpersand6(FoldLevel level) {
176+
FoldLevel hf = FoldLevel::HeaderFlag;
177+
return (!(level & hf) * hf) != FoldLevel::None;
178+
}
179+
180+
constexpr FoldLevel UseOperatorAmpersand7(FoldLevel level) {
181+
FoldLevel hf = FoldLevel::HeaderFlag;
182+
return !(level & hf) * hf;
183+
}
184+
185+
constexpr FoldLevel UseOperatorAmpersand8(FoldLevel level) {
186+
FoldLevel hf = FoldLevel::HeaderFlag;
187+
return hf * !(level & hf);
188+
}
189+
190+
constexpr FoldLevel UseOperatorAmpersand9(FoldLevel level) {
191+
FoldLevel hf = FoldLevel::HeaderFlag;
192+
return !(level & hf);
193+
}
194+
195+
constexpr bool UseOperatorPlus1(FoldLevel level) {
196+
return (FoldLevelToInt(level + FoldLevel::None)) != 1;
197+
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant parentheses around expression [readability-redundant-parentheses]
198+
// CHECK-FIXES: return FoldLevelToInt(level + FoldLevel::None) != 1;
199+
}
200+
201+
constexpr bool UseOperatorPlus2(FoldLevel level) {
202+
return (FoldLevelToInt(!(level + FoldLevel::None))) != 1;
203+
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: redundant parentheses around expression [readability-redundant-parentheses]
204+
// CHECK-FIXES: return FoldLevelToInt(!(level + FoldLevel::None)) != 1;
205+
}
206+
207+
208+
const int bracket_int_plus_num = (4) + 5;
209+
// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: redundant parentheses around expression [readability-redundant-parentheses]
210+
// CHECK-FIXES: const int bracket_int_plus_num = 4 + 5;

0 commit comments

Comments
 (0)