Skip to content

Commit 9dbd360

Browse files
committed
[clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape'
1 parent 700b77b commit 9dbd360

File tree

5 files changed

+113
-11
lines changed

5 files changed

+113
-11
lines changed

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

Lines changed: 29 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,30 @@ 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+
ast_matchers::internal::Matcher<FunctionDecl> Nothing = unless(anything());
6075
Finder->addMatcher(
6176
functionDecl(
6277
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)))
78+
anyOf(
79+
CheckNothrowFunctions ? isNoThrow() : Nothing,
80+
allOf(anyOf(CheckDestructors ? cxxDestructorDecl() : Nothing,
81+
CheckMoveMemberFunctions
82+
? anyOf(cxxConstructorDecl(isMoveConstructor()),
83+
cxxMethodDecl(isMoveAssignmentOperator()))
84+
: Nothing,
85+
CheckMain ? isMain() : Nothing,
86+
allOf(isEnabled(CheckedSwapFunctions),
87+
hasAtLeastOneParameter())),
88+
unless(isExplicitThrow())),
89+
isEnabled(FunctionsThatShouldNotThrow)))
7190
.bind("thrower"),
7291
this);
7392
}

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
@@ -302,7 +302,9 @@ Changes in existing checks
302302
exceptions from captures are now diagnosed, exceptions in the bodies of
303303
lambdas that aren't actually invoked are not. Additionally, fixed an issue
304304
where the check wouldn't diagnose throws in arguments to functions or
305-
constructors.
305+
constructors. Added fine-grained configuration via options
306+
`CheckDestructors`, `CheckMoveMemberFunctions`, `CheckMain`,
307+
`CheckedSwapFunctions`, and `CheckNothrowFunctions`.
306308

307309
- Improved :doc:`bugprone-infinite-loop
308310
<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`, ``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: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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(const move&) { throw 42; }
21+
move(move&&) { throw 42; }
22+
move& operator=(const move&) { throw 42; }
23+
move& operator=(move&&) { throw 42; }
24+
};
25+
26+
void swap(int&, int&) {
27+
throw 1;
28+
}
29+
30+
void iter_swap(int&, int&) {
31+
throw 1;
32+
}
33+
34+
void iter_move(int&) {
35+
throw 1;
36+
}
37+
38+
void nothrow_func() throw() {
39+
throw 1;
40+
}
41+
42+
void noexcept_func() noexcept {
43+
throw 1;
44+
}
45+
46+
int main() {
47+
throw 1;
48+
return 0;
49+
}

0 commit comments

Comments
 (0)