diff --git a/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp @@ -17,9 +17,32 @@ namespace clang::tidy::performance { void NoexceptSwapCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher( - functionDecl(unless(isDeleted()), hasName("swap")).bind(BindFuncDeclName), - this); + + // Match non-const method with single argument that is non-const reference to + // a class type that owns method and return void. + // Matches: void Class::swap(Class&) + auto MethodMatcher = cxxMethodDecl( + parameterCountIs(1U), unless(isConst()), returns(voidType()), + hasParameter(0, hasType(qualType(hasCanonicalType( + qualType(unless(isConstQualified()), + references(namedDecl().bind("class"))))))), + ofClass(equalsBoundNode("class"))); + + // Match function with 2 arguments, both are non-const references to same type + // and return void. + // Matches: void swap(Type&, Type&) + auto FunctionMatcher = allOf( + unless(cxxMethodDecl()), parameterCountIs(2U), returns(voidType()), + hasParameter( + 0, hasType(qualType(hasCanonicalType( + qualType(unless(isConstQualified()), references(qualType())) + .bind("type"))))), + hasParameter(1, hasType(qualType(hasCanonicalType( + qualType(equalsBoundNode("type"))))))); + Finder->addMatcher(functionDecl(unless(isDeleted()), hasName("swap"), + anyOf(MethodMatcher, FunctionMatcher)) + .bind(BindFuncDeclName), + this); } DiagnosticBuilder diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -180,6 +180,10 @@ ` to support for-loops with iterators initialized by free functions like ``begin``, ``end``, or ``size``. +- Improved :doc:`performanc-noexcept-swap + ` check to enforce a stricter + match with the swap function signature, eliminating false-positives. + - Improved the :doc:`readability-identifier-naming ` check to emit proper warnings when a type forward declaration precedes its definition. diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-swap.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-swap.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-swap.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-swap.cpp @@ -201,3 +201,20 @@ template void swap(OK21 &, OK21 &) noexcept(noexcept(TemplateNoexceptWithInt::f())); void swap(OK21 &, OK21 &) noexcept(noexcept(TemplateNoexceptWithInt::f())); + +namespace PR64303 { + void swap(); + void swap(int&, bool&); + void swap(int&, int&, int&); + void swap(int&); + + struct Test { + void swap(); + void swap(Test&, Test&); + void swap(int&); + static void swap(int&, int&); + + friend void swap(Test&, Test&); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: swap functions should be marked noexcept [performance-noexcept-swap] + }; +}