================ @@ -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:
Oh yes, I had in mind `std::swap` as a function that will place value of 2nd argument inside 1st like `std::move`. Yes it isn't needed here, sorry for the noise. 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