aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp38
1 files changed, 30 insertions, 8 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
index 1f432c4..c4c4267 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -69,6 +69,28 @@ 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()),
+ hasBody(compoundStmt(
+ hasDescendant(
+ varDecl(hasType(cxxRecordDecl(equalsBoundNode("class"))))
+ .bind("tmp_var")),
+ hasDescendant(stmt(anyOf(
+ cxxMemberCallExpr(hasArgument(
+ 0, declRefExpr(to(varDecl(equalsBoundNode("tmp_var")))))),
+ callExpr(
+ callee(functionDecl(hasName("swap"))), argumentCountIs(2),
+ hasAnyArgument(
+ declRefExpr(to(varDecl(equalsBoundNode("tmp_var"))))),
+ hasAnyArgument(unaryOperator(has(cxxThisExpr()),
+ hasOperatorName("*"))))))))));
+
DeclarationMatcher AdditionalMatcher = cxxMethodDecl();
if (WarnOnlyIfThisHasSuspiciousField) {
// Matcher for standard smart pointers.
@@ -89,14 +111,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(