-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[clang-tidy] Make bugprone-unhandled-self-assignment
check more general
#147066
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
base: main
Are you sure you want to change the base?
Changes from all commits
950b6dc
0cd33ec
3771a9c
4f576fe
9208a82
4b84a6a
6f4ec4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,6 +69,22 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) { | |
cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl( | ||
hasName("operator="), ofClass(equalsBoundNode("class")))))))); | ||
|
||
// Checking that some kind of constructor is called and followed by a `swap`: | ||
// T& operator=(const T& other) { | ||
// T tmp{this->internal_data(), some, other, args}; | ||
// swap(tmp); | ||
// return *this; | ||
// } | ||
const auto HasCopyAndSwap = cxxMethodDecl( | ||
ofClass(cxxRecordDecl(unless(hasAncestor(classTemplateDecl())))), | ||
hasDescendant( | ||
stmt(hasDescendant( | ||
varDecl(hasType(cxxRecordDecl(equalsBoundNode("class")))) | ||
.bind("tmp_var")), | ||
hasDescendant(callExpr(callee(functionDecl(hasName("swap"))), | ||
hasAnyArgument(declRefExpr(to(varDecl( | ||
equalsBoundNode("tmp_var")))))))))); | ||
Comment on lines
+84
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this matching can be a bit stronger. If
Otherwise, I could create two temporaries of the class and swap only them. |
||
|
||
DeclarationMatcher AdditionalMatcher = cxxMethodDecl(); | ||
if (WarnOnlyIfThisHasSuspiciousField) { | ||
// Matcher for standard smart pointers. | ||
|
@@ -89,14 +105,14 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) { | |
hasType(arrayType()))))))); | ||
} | ||
|
||
Finder->addMatcher(cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")), | ||
isCopyAssignmentOperator(), IsUserDefined, | ||
HasReferenceParam, HasNoSelfCheck, | ||
unless(HasNonTemplateSelfCopy), | ||
unless(HasTemplateSelfCopy), | ||
HasNoNestedSelfAssign, AdditionalMatcher) | ||
.bind("copyAssignmentOperator"), | ||
this); | ||
Finder->addMatcher( | ||
cxxMethodDecl( | ||
ofClass(cxxRecordDecl().bind("class")), isCopyAssignmentOperator(), | ||
IsUserDefined, HasReferenceParam, HasNoSelfCheck, | ||
unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy), | ||
unless(HasCopyAndSwap), HasNoNestedSelfAssign, AdditionalMatcher) | ||
.bind("copyAssignmentOperator"), | ||
this); | ||
} | ||
|
||
void UnhandledSelfAssignmentCheck::check( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -189,6 +189,12 @@ Changes in existing checks | |
calls of ``std::string`` constructor with char pointer, start position and | ||
length parameters. | ||
|
||
- Improved :doc:`bugprone-unhandled-self-assignment | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be after |
||
<clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding | ||
an additional matcher that generalizes the copy-and-swap idiom pattern | ||
detection. The checker now properly recognizes copy-and-swap implementations | ||
that use "extended" copy/move constructors. | ||
Comment on lines
+195
to
+196
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if the second sentence is needed |
||
|
||
- Improved :doc:`bugprone-unchecked-optional-access | ||
<clang-tidy/checks/bugprone/unchecked-optional-access>` fixing false | ||
positives from smart pointer accessors repeated in checking ``has_value`` | ||
|
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.
Is
hasAncestor
necessary here? Could it just behasParent
? Or why skip templates at all?