https://github.com/vbvictor updated https://github.com/llvm/llvm-project/pull/164081
>From fb25544a0a090272018fb97e41fee902d23cd0ef Mon Sep 17 00:00:00 2001 From: Victor Baranov <[email protected]> Date: Sat, 18 Oct 2025 15:52:12 +0300 Subject: [PATCH 1/2] [clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape' --- .../bugprone/ExceptionEscapeCheck.cpp | 39 +++++++++++---- .../bugprone/ExceptionEscapeCheck.h | 7 +++ clang-tools-extra/docs/ReleaseNotes.rst | 4 +- .../checks/bugprone/exception-escape.rst | 25 ++++++++++ .../bugprone/exception-escape-options.cpp | 49 +++++++++++++++++++ 5 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 837a86ff8655e..b07aad09ed2af 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -36,13 +36,22 @@ ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get( "FunctionsThatShouldNotThrow", "")), - RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) { + RawIgnoredExceptions(Options.get("IgnoredExceptions", "")), + RawCheckedSwapFunctions( + Options.get("CheckedSwapFunctions", "swap,iter_swap,iter_move")), + CheckDestructors(Options.get("CheckDestructors", true)), + CheckMoveMemberFunctions(Options.get("CheckMoveMemberFunctions", true)), + CheckMain(Options.get("CheckMain", true)), + CheckNothrowFunctions(Options.get("CheckNothrowFunctions", true)) { llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec, - IgnoredExceptionsVec; + IgnoredExceptionsVec, CheckedSwapFunctionsVec; RawFunctionsThatShouldNotThrow.split(FunctionsThatShouldNotThrowVec, ",", -1, false); FunctionsThatShouldNotThrow.insert_range(FunctionsThatShouldNotThrowVec); + RawCheckedSwapFunctions.split(CheckedSwapFunctionsVec, ",", -1, false); + CheckedSwapFunctions.insert_range(CheckedSwapFunctionsVec); + llvm::StringSet<> IgnoredExceptions; RawIgnoredExceptions.split(IgnoredExceptionsVec, ",", -1, false); IgnoredExceptions.insert_range(IgnoredExceptionsVec); @@ -54,20 +63,30 @@ void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "FunctionsThatShouldNotThrow", RawFunctionsThatShouldNotThrow); Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions); + Options.store(Opts, "CheckedSwapFunctions", RawCheckedSwapFunctions); + Options.store(Opts, "CheckDestructors", CheckDestructors); + Options.store(Opts, "CheckMoveMemberFunctions", CheckMoveMemberFunctions); + Options.store(Opts, "CheckMain", CheckMain); + Options.store(Opts, "CheckNothrowFunctions", CheckNothrowFunctions); } void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) { + ast_matchers::internal::Matcher<FunctionDecl> Nothing = unless(anything()); Finder->addMatcher( functionDecl( isDefinition(), - anyOf(isNoThrow(), - allOf(anyOf(cxxDestructorDecl(), - cxxConstructorDecl(isMoveConstructor()), - cxxMethodDecl(isMoveAssignmentOperator()), isMain(), - allOf(hasAnyName("swap", "iter_swap", "iter_move"), - hasAtLeastOneParameter())), - unless(isExplicitThrow())), - isEnabled(FunctionsThatShouldNotThrow))) + anyOf( + CheckNothrowFunctions ? isNoThrow() : Nothing, + allOf(anyOf(CheckDestructors ? cxxDestructorDecl() : Nothing, + CheckMoveMemberFunctions + ? anyOf(cxxConstructorDecl(isMoveConstructor()), + cxxMethodDecl(isMoveAssignmentOperator())) + : Nothing, + CheckMain ? isMain() : Nothing, + allOf(isEnabled(CheckedSwapFunctions), + hasAtLeastOneParameter())), + unless(isExplicitThrow())), + isEnabled(FunctionsThatShouldNotThrow))) .bind("thrower"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h index bd1e7bae57f5d..db5e71901962e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h @@ -35,8 +35,15 @@ class ExceptionEscapeCheck : public ClangTidyCheck { private: StringRef RawFunctionsThatShouldNotThrow; StringRef RawIgnoredExceptions; + StringRef RawCheckedSwapFunctions; + + const bool CheckDestructors; + const bool CheckMoveMemberFunctions; + const bool CheckMain; + const bool CheckNothrowFunctions; llvm::StringSet<> FunctionsThatShouldNotThrow; + llvm::StringSet<> CheckedSwapFunctions; utils::ExceptionAnalyzer Tracer; }; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a94dd9737468c..c5247074244d2 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -260,7 +260,9 @@ Changes in existing checks - Improved :doc:`bugprone-exception-escape <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: exceptions from captures are now diagnosed, exceptions in the bodies of - lambdas that aren't actually invoked are not. + lambdas that aren't actually invoked are not. Added fine-grained configuration + via options `CheckDestructors`, `CheckMoveMemberFunctions`, `CheckMain`, + `CheckedSwapFunctions`, and `CheckNothrowFunctions`. - Improved :doc:`bugprone-infinite-loop <clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for 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 182fade7f47a0..07abbedd109b0 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 @@ -35,6 +35,31 @@ WARNING! This check may be expensive on large source files. Options ------- +.. option:: CheckDestructors + + When `true`, destructors are analyzed to not throw exceptions. + Default value is `true`. + +.. option:: CheckMoveMemberFunctions + + When `true`, move constructors and move assignment operators are analyzed + to not throw exceptions. Default value is `true`. + +.. option:: CheckMain + + When `true`, ``main()`` function is analyzed to not throw exceptions. + Default value is `true`. + +.. option:: CheckNothrowFunctions + + When `true`, functions marked with ``noexcept`` or ``throw()`` exception + specifications are analyzed to not throw exceptions. Default value is `true`. + +.. option:: CheckedSwapFunctions + + Comma separated list of swap function names which should not throw exceptions. + Default value is `swap,iter_swap,iter_move`. + .. option:: FunctionsThatShouldNotThrow Comma separated list containing function names which should not throw. An diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp new file mode 100644 index 0000000000000..b448770561dbb --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp @@ -0,0 +1,49 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-exception-escape %t -- \ +// RUN: -config="{CheckOptions: { \ +// RUN: bugprone-exception-escape.CheckDestructors: false, \ +// RUN: bugprone-exception-escape.CheckMoveMemberFunctions: false, \ +// RUN: bugprone-exception-escape.CheckMain: false, \ +// RUN: bugprone-exception-escape.CheckedSwapFunctions: '', \ +// RUN: bugprone-exception-escape.CheckNothrowFunctions: false \ +// RUN: }}" \ +// RUN: -- -fexceptions + +// CHECK-MESSAGES-NOT: warning: + +struct destructor { + ~destructor() { + throw 1; + } +}; + +struct move { + move(const move&) { throw 42; } + move(move&&) { throw 42; } + move& operator=(const move&) { throw 42; } + move& operator=(move&&) { throw 42; } +}; + +void swap(int&, int&) { + throw 1; +} + +void iter_swap(int&, int&) { + throw 1; +} + +void iter_move(int&) { + throw 1; +} + +void nothrow_func() throw() { + throw 1; +} + +void noexcept_func() noexcept { + throw 1; +} + +int main() { + throw 1; + return 0; +} >From 1ee861b1f4b6c19748d8ec1bb14421ba1be2f715 Mon Sep 17 00:00:00 2001 From: Baranov Victor <[email protected]> Date: Sat, 18 Oct 2025 17:40:29 +0300 Subject: [PATCH 2/2] Update clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst Co-authored-by: EugeneZelenko <[email protected]> --- .../docs/clang-tidy/checks/bugprone/exception-escape.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 07abbedd109b0..2e0b37f7e2e8b 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 @@ -57,7 +57,7 @@ Options .. option:: CheckedSwapFunctions - Comma separated list of swap function names which should not throw exceptions. + Comma-separated list of swap function names which should not throw exceptions. Default value is `swap,iter_swap,iter_move`. .. option:: FunctionsThatShouldNotThrow _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
