diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 90bf523ffb00b..620a57194acb8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -28,6 +28,10 @@ AST_MATCHER(FunctionDecl, isExplicitThrow) { Node.getExceptionSpecSourceRange().isValid(); } +AST_MATCHER(FunctionDecl, hasAtLeastOneParameter) { + return Node.getNumParams() > 0; +} + } // namespace ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name, @@ -58,14 +62,16 @@ void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - functionDecl(isDefinition(), - anyOf(isNoThrow(), - allOf(anyOf(cxxDestructorDecl(), - cxxConstructorDecl(isMoveConstructor()), - cxxMethodDecl(isMoveAssignmentOperator()), - isMain(), hasName("swap")), - unless(isExplicitThrow())), - isEnabled(FunctionsThatShouldNotThrow))) + functionDecl( + isDefinition(), + anyOf(isNoThrow(), + allOf(anyOf(cxxDestructorDecl(), + cxxConstructorDecl(isMoveConstructor()), + cxxMethodDecl(isMoveAssignmentOperator()), isMain(), + allOf(hasAnyName("swap", "iter_swap", "iter_move"), + hasAtLeastOneParameter())), + unless(isExplicitThrow())), + isEnabled(FunctionsThatShouldNotThrow))) .bind("thrower"), this); } diff --git a/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp index 25a58af74f7ee..e7cba6e54e86a 100644 --- a/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp @@ -39,7 +39,8 @@ void NoexceptSwapCheck::registerMatchers(MatchFinder *Finder) { .bind("type"))))), hasParameter(1, hasType(qualType(hasCanonicalType( qualType(equalsBoundNode("type"))))))); - Finder->addMatcher(functionDecl(unless(isDeleted()), hasName("swap"), + Finder->addMatcher(functionDecl(unless(isDeleted()), + hasAnyName("swap", "iter_swap"), anyOf(MethodMatcher, FunctionMatcher)) .bind(BindFuncDeclName), this); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 07d788851f8d1..0144bf44c0479 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -260,6 +260,10 @@ Changes in existing checks casting during type conversions at variable initialization, now with improved compatibility for C++17 and later versions. +- Improved :doc:`bugprone-exception-escape + ` check by extending the default + check function names to include ``iter_swap`` and ``iter_move``. + - Improved :doc:`bugprone-implicit-widening-of-multiplication-result ` check to correctly emit fixes. @@ -445,7 +449,8 @@ Changes in existing checks - Improved :doc:`performance-noexcept-swap ` check to enforce a stricter match with the swap function signature and better handling of condition - noexcept expressions, eliminating false-positives. + noexcept expressions, eliminating false-positives. ``iter_swap`` function name + is checked by default. - Improved :doc:`readability-braces-around-statements ` check to diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst index e6aa8e001492a..182fade7f47a0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst @@ -11,6 +11,8 @@ should not. The functions which should not throw exceptions are the following: * Move assignment operators * The ``main()`` functions * ``swap()`` functions +* ``iter_swap()`` functions +* ``iter_move()`` functions * Functions marked with ``throw()`` or ``noexcept`` * Other functions given as option diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst index fa4007618ba0f..2901d721706c8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst @@ -3,11 +3,11 @@ performance-noexcept-swap ========================= -The check flags user-defined swap functions not marked with ``noexcept`` or +The check flags user-defined swap and iter_swap functions not marked with ``noexcept`` or marked with ``noexcept(expr)`` where ``expr`` evaluates to ``false`` (but is not a ``false`` literal itself). -When a swap function is marked as ``noexcept``, it assures the compiler that +When a swap or iter_swap function is marked as ``noexcept``, it assures the compiler that no exceptions will be thrown during the swapping of two objects, which allows the compiler to perform certain optimizations such as omitting exception handling code. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp index 4a7149e81ce7e..f5e74df1621ce 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp @@ -586,6 +586,16 @@ void swap(int&, int&) { throw 1; } +void iter_swap(int&, int&) { + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions + throw 1; +} + +void iter_move(int&) { + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions + throw 1; +} + namespace std { class bad_alloc {}; } 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 index dfc71a2bb9ab3..6b266707d77f8 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-swap.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-swap.cpp @@ -32,6 +32,10 @@ void swap(A &, A &); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: swap functions should be marked noexcept [performance-noexcept-swap] // CHECK-FIXES: void swap(A &, A &) noexcept ; +void iter_swap(A &, A &); +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: swap functions should be marked noexcept [performance-noexcept-swap] +// CHECK-FIXES: void iter_swap(A &, A &) noexcept ; + struct B { static constexpr bool kFalse = false; void swap(B &) noexcept(kFalse);