Skip to content

Commit fb25544

Browse files
committed
[clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape'
1 parent b4b7aae commit fb25544

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
@@ -260,7 +260,9 @@ Changes in existing checks
260260
- Improved :doc:`bugprone-exception-escape
261261
<clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas:
262262
exceptions from captures are now diagnosed, exceptions in the bodies of
263-
lambdas that aren't actually invoked are not.
263+
lambdas that aren't actually invoked are not. Added fine-grained configuration
264+
via options `CheckDestructors`, `CheckMoveMemberFunctions`, `CheckMain`,
265+
`CheckedSwapFunctions`, and `CheckNothrowFunctions`.
264266

265267
- Improved :doc:`bugprone-infinite-loop
266268
<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)