================
@@ -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("*"))))))))));
----------------
vbvictor wrote:

When we have `std::swap(*this, tmp);`, we expect the first argument to be 
`*this` and second `tmp`. The matcher should be more specific about it: use 
`hasArgument(0, ...cxxThisExpr())` and `hasArgument(1, 
...equalsBoundNode("tmp_var"))`.

https://github.com/llvm/llvm-project/pull/147066
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to