Skip to content

Commit 169148a

Browse files
authored
[clang-tidy] Add option 'AllowedTypes' to bugprone-throwing-static-initialization (#192031)
1 parent d60b2b2 commit 169148a

5 files changed

Lines changed: 85 additions & 4 deletions

File tree

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,27 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "ThrowingStaticInitializationCheck.h"
10+
#include "../utils/Matchers.h"
11+
#include "../utils/OptionsUtils.h"
1012
#include "clang/AST/ASTContext.h"
1113
#include "clang/ASTMatchers/ASTMatchFinder.h"
1214

1315
using namespace clang::ast_matchers;
1416

1517
namespace clang::tidy::bugprone {
1618

19+
ThrowingStaticInitializationCheck::ThrowingStaticInitializationCheck(
20+
StringRef Name, ClangTidyContext *Context)
21+
: ClangTidyCheck(Name, Context),
22+
AllowedTypes(
23+
utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
24+
25+
void ThrowingStaticInitializationCheck::storeOptions(
26+
ClangTidyOptions::OptionMap &Opts) {
27+
Options.store(Opts, "AllowedTypes",
28+
utils::options::serializeStringList(AllowedTypes));
29+
}
30+
1731
void ThrowingStaticInitializationCheck::registerMatchers(MatchFinder *Finder) {
1832
// Match any static or thread_local variable declaration that has an
1933
// initializer that can throw.
@@ -22,8 +36,10 @@ void ThrowingStaticInitializationCheck::registerMatchers(MatchFinder *Finder) {
2236
TK_AsIs,
2337
varDecl(
2438
anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()),
25-
unless(anyOf(isConstexpr(), hasType(cxxRecordDecl(isLambda())),
26-
hasAncestor(functionDecl()))),
39+
unless(anyOf(
40+
isConstexpr(), hasType(cxxRecordDecl(isLambda())),
41+
hasAncestor(functionDecl()),
42+
hasType(matchers::matchesAnyListedTypeName(AllowedTypes)))),
2743
anyOf(hasDescendant(cxxConstructExpr(hasDeclaration(
2844
cxxConstructorDecl(unless(isNoThrow())).bind("func")))),
2945
hasDescendant(cxxNewExpr(hasDeclaration(

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@ namespace clang::tidy::bugprone {
2020
/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/throwing-static-initialization.html
2121
class ThrowingStaticInitializationCheck : public ClangTidyCheck {
2222
public:
23-
ThrowingStaticInitializationCheck(StringRef Name, ClangTidyContext *Context)
24-
: ClangTidyCheck(Name, Context) {}
23+
ThrowingStaticInitializationCheck(StringRef Name, ClangTidyContext *Context);
24+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
2525
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
2626
return LangOpts.CPlusPlus && LangOpts.CXXExceptions;
2727
}
2828
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2929
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
30+
31+
private:
32+
const std::vector<StringRef> AllowedTypes;
3033
};
3134

3235
} // namespace clang::tidy::bugprone

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ Changes in existing checks
286286
string constructor calls when the string class constructor has a default
287287
allocator argument.
288288

289+
- Improved :doc:`bugprone-throwing-static-initialization
290+
<clang-tidy/checks/bugprone/throwing-static-initialization>` check by adding
291+
the `AllowedTypes` option. With this option it is possible to exclude
292+
static declarations with specific types from the check.
293+
289294
- Improved :doc:`bugprone-unchecked-optional-access
290295
<clang-tidy/checks/bugprone/unchecked-optional-access>` to recognize common
291296
GoogleTest macros such as ``ASSERT_TRUE`` and ``ASSERT_FALSE``, reducing the

clang-tools-extra/docs/clang-tidy/checks/bugprone/throwing-static-initialization.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ bugprone-throwing-static-initialization
66
Finds all ``static`` or ``thread_local`` variable declarations where the
77
initializer for the object may throw an exception.
88

9+
Options
10+
-------
11+
12+
.. option:: AllowedTypes
13+
14+
A semicolon-separated list of names of types that will be excluded from
15+
this check (declarations with matching type will be excluded). Regular
16+
expressions are accepted, e.g. ``[Rr]ef(erence)?$`` matches every type with
17+
suffix ``Ref``, ``ref``, ``Reference`` and ``reference``. If a name in the
18+
list contains the sequence `::`, it is matched against the qualified type
19+
name (i.e. ``namespace::Type``), otherwise it is matched against only the
20+
type name (i.e. ``Type``). Default is an empty string.
21+
922
References
1023
----------
1124

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %check_clang_tidy %s bugprone-throwing-static-initialization %t -- \
2+
// RUN: -config="{CheckOptions: \
3+
// RUN: {bugprone-throwing-static-initialization.AllowedTypes: \"Allow;^ns::S1$;^ns::Template<1>$\"}}" \
4+
// RUN: -- -fexceptions
5+
6+
struct S1 {
7+
S1() noexcept(false);
8+
};
9+
10+
struct S1_Allow {
11+
S1_Allow() noexcept(false);
12+
};
13+
14+
namespace ns {
15+
struct S1 {
16+
S1();
17+
};
18+
struct S1_Allow {
19+
S1_Allow();
20+
};
21+
template<int>
22+
struct Template {
23+
Template() noexcept(false);
24+
};
25+
}
26+
27+
template<class>
28+
struct TemplateAllowed {
29+
TemplateAllowed() noexcept(false);
30+
};
31+
32+
S1_Allow getS1() noexcept(false);
33+
34+
S1 VarThrow;
35+
// CHECK-MESSAGES: :[[@LINE-1]]:4: warning: initialization of 'VarThrow' with static storage duration may throw an exception that cannot be caught
36+
ns::Template<2> VarTempl;
37+
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: initialization of 'VarTempl' with static storage duration may throw an exception that cannot be caught
38+
39+
S1_Allow VarAllowedConstr;
40+
S1_Allow VarAllowedInitF = getS1();
41+
ns::S1 VarAllowed2;
42+
ns::S1_Allow VarAllowed3;
43+
TemplateAllowed<int> VarAllowed4;
44+
ns::Template<1> VarAllowed5;

0 commit comments

Comments
 (0)