Skip to content

Commit eaa889a

Browse files
vbvictorEugeneZelenkolocalspook
authored
[clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape' (#164081)
Need these options to complete #160825, but I think it's generally beneficial to fine-tune this check. --------- Co-authored-by: EugeneZelenko <[email protected]> Co-authored-by: Victor Chernyakin <[email protected]>
1 parent d0081aa commit eaa889a

File tree

5 files changed

+114
-11
lines changed

5 files changed

+114
-11
lines changed

clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,22 @@ ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
3636
ClangTidyContext *Context)
3737
: ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get(
3838
"FunctionsThatShouldNotThrow", "")),
39-
RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) {
39+
RawIgnoredExceptions(Options.get("IgnoredExceptions", "")),
40+
RawCheckedSwapFunctions(
41+
Options.get("CheckedSwapFunctions", "swap,iter_swap,iter_move")),
42+
CheckDestructors(Options.get("CheckDestructors", true)),
43+
CheckMoveMemberFunctions(Options.get("CheckMoveMemberFunctions", true)),
44+
CheckMain(Options.get("CheckMain", true)),
45+
CheckNothrowFunctions(Options.get("CheckNothrowFunctions", true)) {
4046
llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec,
41-
IgnoredExceptionsVec;
47+
IgnoredExceptionsVec, CheckedSwapFunctionsVec;
4248
RawFunctionsThatShouldNotThrow.split(FunctionsThatShouldNotThrowVec, ",", -1,
4349
false);
4450
FunctionsThatShouldNotThrow.insert_range(FunctionsThatShouldNotThrowVec);
4551

52+
RawCheckedSwapFunctions.split(CheckedSwapFunctionsVec, ",", -1, false);
53+
CheckedSwapFunctions.insert_range(CheckedSwapFunctionsVec);
54+
4655
llvm::StringSet<> IgnoredExceptions;
4756
RawIgnoredExceptions.split(IgnoredExceptionsVec, ",", -1, false);
4857
IgnoredExceptions.insert_range(IgnoredExceptionsVec);
@@ -54,20 +63,33 @@ void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
5463
Options.store(Opts, "FunctionsThatShouldNotThrow",
5564
RawFunctionsThatShouldNotThrow);
5665
Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions);
66+
Options.store(Opts, "CheckedSwapFunctions", RawCheckedSwapFunctions);
67+
Options.store(Opts, "CheckDestructors", CheckDestructors);
68+
Options.store(Opts, "CheckMoveMemberFunctions", CheckMoveMemberFunctions);
69+
Options.store(Opts, "CheckMain", CheckMain);
70+
Options.store(Opts, "CheckNothrowFunctions", CheckNothrowFunctions);
5771
}
5872

5973
void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
74+
auto MatchIf = [](bool Enabled, const auto &Matcher) {
75+
ast_matchers::internal::Matcher<FunctionDecl> Nothing = unless(anything());
76+
return Enabled ? Matcher : Nothing;
77+
};
6078
Finder->addMatcher(
6179
functionDecl(
6280
isDefinition(),
63-
anyOf(isNoThrow(),
64-
allOf(anyOf(cxxDestructorDecl(),
65-
cxxConstructorDecl(isMoveConstructor()),
66-
cxxMethodDecl(isMoveAssignmentOperator()), isMain(),
67-
allOf(hasAnyName("swap", "iter_swap", "iter_move"),
68-
hasAtLeastOneParameter())),
69-
unless(isExplicitThrow())),
70-
isEnabled(FunctionsThatShouldNotThrow)))
81+
anyOf(
82+
MatchIf(CheckNothrowFunctions, isNoThrow()),
83+
allOf(anyOf(MatchIf(CheckDestructors, cxxDestructorDecl()),
84+
MatchIf(
85+
CheckMoveMemberFunctions,
86+
anyOf(cxxConstructorDecl(isMoveConstructor()),
87+
cxxMethodDecl(isMoveAssignmentOperator()))),
88+
MatchIf(CheckMain, isMain()),
89+
allOf(isEnabled(CheckedSwapFunctions),
90+
hasAtLeastOneParameter())),
91+
unless(isExplicitThrow())),
92+
isEnabled(FunctionsThatShouldNotThrow)))
7193
.bind("thrower"),
7294
this);
7395
}

clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,15 @@ class ExceptionEscapeCheck : public ClangTidyCheck {
3535
private:
3636
StringRef RawFunctionsThatShouldNotThrow;
3737
StringRef RawIgnoredExceptions;
38+
StringRef RawCheckedSwapFunctions;
39+
40+
const bool CheckDestructors;
41+
const bool CheckMoveMemberFunctions;
42+
const bool CheckMain;
43+
const bool CheckNothrowFunctions;
3844

3945
llvm::StringSet<> FunctionsThatShouldNotThrow;
46+
llvm::StringSet<> CheckedSwapFunctions;
4047
utils::ExceptionAnalyzer Tracer;
4148
};
4249

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,9 @@ Changes in existing checks
306306
exceptions from captures are now diagnosed, exceptions in the bodies of
307307
lambdas that aren't actually invoked are not. Additionally, fixed an issue
308308
where the check wouldn't diagnose throws in arguments to functions or
309-
constructors.
309+
constructors. Added fine-grained configuration via options
310+
`CheckDestructors`, `CheckMoveMemberFunctions`, `CheckMain`,
311+
`CheckedSwapFunctions`, and `CheckNothrowFunctions`.
310312

311313
- Improved :doc:`bugprone-infinite-loop
312314
<clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for

clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,31 @@ WARNING! This check may be expensive on large source files.
3535
Options
3636
-------
3737

38+
.. option:: CheckDestructors
39+
40+
When `true`, destructors are analyzed to not throw exceptions.
41+
Default value is `true`.
42+
43+
.. option:: CheckMoveMemberFunctions
44+
45+
When `true`, move constructors and move assignment operators are analyzed
46+
to not throw exceptions. Default value is `true`.
47+
48+
.. option:: CheckMain
49+
50+
When `true`, the ``main()`` function is analyzed to not throw exceptions.
51+
Default value is `true`.
52+
53+
.. option:: CheckNothrowFunctions
54+
55+
When `true`, functions marked with ``noexcept`` or ``throw()`` exception
56+
specifications are analyzed to not throw exceptions. Default value is `true`.
57+
58+
.. option:: CheckedSwapFunctions
59+
60+
Comma-separated list of swap function names which should not throw exceptions.
61+
Default value is `swap,iter_swap,iter_move`.
62+
3863
.. option:: FunctionsThatShouldNotThrow
3964

4065
Comma separated list containing function names which should not throw. An
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-exception-escape %t -- \
2+
// RUN: -config="{CheckOptions: { \
3+
// RUN: bugprone-exception-escape.CheckDestructors: false, \
4+
// RUN: bugprone-exception-escape.CheckMoveMemberFunctions: false, \
5+
// RUN: bugprone-exception-escape.CheckMain: false, \
6+
// RUN: bugprone-exception-escape.CheckedSwapFunctions: '', \
7+
// RUN: bugprone-exception-escape.CheckNothrowFunctions: false \
8+
// RUN: }}" \
9+
// RUN: -- -fexceptions
10+
11+
// CHECK-MESSAGES-NOT: warning:
12+
13+
struct destructor {
14+
~destructor() {
15+
throw 1;
16+
}
17+
};
18+
19+
struct move {
20+
move(move&&) { throw 42; }
21+
move& operator=(move&&) { throw 42; }
22+
};
23+
24+
void swap(int&, int&) {
25+
throw 1;
26+
}
27+
28+
void iter_swap(int&, int&) {
29+
throw 1;
30+
}
31+
32+
void iter_move(int&) {
33+
throw 1;
34+
}
35+
36+
void nothrow_func() throw() {
37+
throw 1;
38+
}
39+
40+
void noexcept_func() noexcept {
41+
throw 1;
42+
}
43+
44+
int main() {
45+
throw 1;
46+
return 0;
47+
}

0 commit comments

Comments
 (0)