-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang-tidy]bugprone-unused-return-value ignore ++
and --
operator overloading
#84922
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang-tidy]bugprone-unused-return-value ignore ++
and --
operator overloading
#84922
Conversation
…r overloading Fixes: llvm#84705
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Congcong Cai (HerrCai0907) ChangesFixes: #84705 Full diff: https://github.com/llvm/llvm-project/pull/84922.diff 2 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
index 243fe47c2036b6..83b332fba1e2da 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
@@ -165,20 +165,20 @@ void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) {
auto MatchedDirectCallExpr = expr(
- callExpr(
- callee(functionDecl(
- // Don't match void overloads of checked functions.
- unless(returns(voidType())),
- // Don't match copy or move assignment operator.
- unless(cxxMethodDecl(isOperatorOverloading(
- {OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual,
- OO_SlashEqual, OO_PercentEqual, OO_CaretEqual, OO_AmpEqual,
- OO_PipeEqual, OO_LessLessEqual, OO_GreaterGreaterEqual}))),
- anyOf(
- isInstantiatedFrom(
- matchers::matchesAnyListedName(CheckedFunctions)),
- returns(hasCanonicalType(hasDeclaration(namedDecl(
- matchers::matchesAnyListedName(CheckedReturnTypes)))))))))
+ callExpr(callee(functionDecl(
+ // Don't match void overloads of checked functions.
+ unless(returns(voidType())),
+ // Don't match copy or move assignment operator.
+ unless(cxxMethodDecl(isOperatorOverloading(
+ {OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual,
+ OO_SlashEqual, OO_PercentEqual, OO_CaretEqual,
+ OO_AmpEqual, OO_PipeEqual, OO_LessLessEqual,
+ OO_GreaterGreaterEqual, OO_PlusPlus, OO_MinusMinus}))),
+ anyOf(isInstantiatedFrom(
+ matchers::matchesAnyListedName(CheckedFunctions)),
+ returns(hasCanonicalType(hasDeclaration(
+ namedDecl(matchers::matchesAnyListedName(
+ CheckedReturnTypes)))))))))
.bind("match"));
auto CheckCastToVoid =
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp
index b4a41004adf894..5809da9ec27b38 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp
@@ -10,6 +10,10 @@ struct S {
S &operator=(S const &);
S &operator=(S &&);
S &operator+=(S);
+ S &operator++();
+ S &operator++(int);
+ S &operator--();
+ S &operator--(int);
};
S returnValue();
@@ -27,4 +31,8 @@ void bar() {
a.operator=(returnRef());
a += returnRef();
+ a++;
+ ++a;
+ a--;
+ --a;
}
|
Please mention changes in Release Notes. |
release notes already includes this change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall change is fine.
There is only one usage of isOperatorOverloading, so you could consider changing this into:
isOverloadAssigmentOperator and put all those operator kinds in a matcher instead of messing with SmallVector.
// Don't match void overloads of checked functions. | ||
unless(returns(voidType())), | ||
// Don't match copy or move assignment operator. | ||
unless(cxxMethodDecl(isOperatorOverloading( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curios, what about operators outside class, like:
struct S {
S(){};
S(S const &);
S(S &&);
};
S &operator+=(S& s, S s2);
void test()
{
S s;
S s2;
s += s2;
operator+=(s, s2);
}
in AST those are functions, not methods:
-FunctionDecl <line:7:3, col:27> col:6 used operator+= 'S &(S &, S)'
| |-ParmVarDecl <col:17, col:20> col:20 s 'S &'
| `-ParmVarDecl <col:23, col:25> col:25 s2 'S':'S'
clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few more tests would be also nice, with free standing operators.
Node.getOperator()); | ||
} | ||
AST_MATCHER(CXXMethodDecl, isAssignmentOverloadedOperatorMethod) { | ||
return llvm::is_contained(AssignmentOverloadedOperatorKinds, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getOverloadedOperator belongs to FunctionDecl, change this from Method to Function, and same in calee, in such case you will also cover calls to free standing operators called directly.
unless(cxxOperatorCallExpr(isAssignmentOverloadedOperatorCall())), | ||
unless(callee(cxxMethodDecl(isAssignmentOverloadedOperatorMethod())))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try changing this code in a way so callee woudn't be checked if cxxOperatorCallExpr were already checked.
you could do it like this:
anyOf(cxxOperatorCallExpr(unless(isAssignmentOverloadedOperatorCall()),
unless(callee(functionDecl(isAssignmentOverloadedOperatorFunction()))))
You may also consider moving this before all those matchers::matchesAnyListedName, so names woudn't be checked for operators at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this check really ignore postfix increment/decrement? Or maybe this check ignores it and a new check diagnoses it++
vs ++it
(where possible). What are your thoughts on this?
clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
Outdated
Show resolved
Hide resolved
@5chmidti What does |
I mean this pattern: void foo(std::string str) {
auto iter = str.begin();
iter++; // prefer ++iter;
++iter;
sink(iter++);
sink(++iter);
for (auto i = str.begin(); i != str.end(); ++i) {}
for (auto i = str.begin(); i != str.end(); i++) {} // prefer ++i
} Where people write |
It should be another check in maybe performance, since this check wants to detect unused return instead of iterator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM from my side, please wait for @PiotrZSL to reconfirm approval/finish review
…r overloading (llvm#84922) Fixes: llvm#84705 Further fix for llvm#84489
Fixes: #84705
Further fix for #84489