1// RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions
2
3namespace std {
4
5// std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
6template <typename T>
7class allocator {};
8template <typename T>
9class char_traits {};
10template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
11struct basic_string {
12 basic_string();
13 basic_string(const basic_string &);
14 // MSVC headers define two constructors instead of using optional arguments.
15 basic_string(const C *);
16 basic_string(const C *, const A &);
17 ~basic_string();
18};
19typedef basic_string<char> string;
20typedef basic_string<wchar_t> wstring;
21
22// std::exception and std::runtime_error declaration.
23struct exception {
24 exception();
25 exception(const exception &other);
26 virtual ~exception();
27};
28
29struct runtime_error : public exception {
30 explicit runtime_error(const std::string &what_arg);
31};
32
33} // namespace std
34
35// The usage of this class should never emit a warning.
36struct RegularClass {};
37
38// Class name contains the substring "exception", in certain cases using this class should emit a warning.
39struct RegularException {
40 RegularException() {}
41
42 // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
43 RegularException(int) {}
44};
45
46// --------------
47
48void stdExceptionNotTrownTest(int i) {
49 if (i < 0)
50 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
51 std::exception();
52
53 if (i > 0)
54 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
55 std::runtime_error("Unexpected argument");
56}
57
58void stdExceptionThrownTest(int i) {
59 if (i < 0)
60 throw std::exception();
61
62 if (i > 0)
63 throw std::runtime_error("Unexpected argument");
64}
65
66void regularClassNotThrownTest(int i) {
67 if (i < 0)
68 RegularClass();
69}
70
71void regularClassThrownTest(int i) {
72 if (i < 0)
73 throw RegularClass();
74}
75
76void nameContainsExceptionNotThrownTest(int i) {
77 if (i < 0)
78 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
79 RegularException();
80
81 if (i > 0)
82 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
83 RegularException(5);
84}
85
86void nameContainsExceptionThrownTest(int i) {
87 if (i < 0)
88 throw RegularException();
89
90 if (i > 0)
91 throw RegularException(5);
92}
93
94template <class Exception>
95void f(int i, Exception excToBeThrown) {}
96
97template <class SomeType>
98void templ(int i) {
99 if (i > 0)
100 SomeType();
101}
102
103void funcCallWithTempExcTest() {
104 f(i: 5, excToBeThrown: RegularException());
105
106 templ<RegularException>(i: 4);
107 templ<RegularClass>(i: 4);
108}
109
110// Global variable initialization test.
111RegularException exc = RegularException();
112RegularException *excptr = new RegularException();
113
114void localVariableInitTest() {
115 RegularException exc = RegularException();
116 RegularException *excptr = new RegularException();
117}
118
119class CtorInitializerListTest {
120 RegularException exc;
121 RegularException exc2{};
122
123 CtorInitializerListTest() : exc(RegularException()) {}
124
125 CtorInitializerListTest(int) try : exc(RegularException()) {
126 // Constructor body
127 } catch (...) {
128 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
129 RegularException();
130 }
131
132 CtorInitializerListTest(float);
133};
134
135CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
136 // Constructor body
137} catch (...) {
138 // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
139 RegularException();
140}
141
142RegularException funcReturningExceptionTest(int i) {
143 return RegularException();
144}
145
146void returnedValueTest() {
147 funcReturningExceptionTest(i: 3);
148}
149
150struct ClassBracedInitListTest {
151 ClassBracedInitListTest(RegularException exc) {}
152};
153
154void foo(RegularException, ClassBracedInitListTest) {}
155
156void bracedInitListTest() {
157 RegularException exc{};
158 ClassBracedInitListTest test = {RegularException()};
159 foo({}, {RegularException()});
160}
161
162typedef std::exception ERROR_BASE;
163class RegularError : public ERROR_BASE {};
164
165void typedefTest() {
166 // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
167 RegularError();
168}
169
170struct ExceptionRAII {
171 ExceptionRAII() {}
172 ~ExceptionRAII() {}
173};
174
175void exceptionRAIITest() {
176 ExceptionRAII E;
177}
178
179namespace std {
180typedef decltype(sizeof(void*)) size_t;
181}
182
183void* operator new(std::size_t, void*);
184
185void placeMentNewTest() {
186 alignas(RegularException) unsigned char expr[sizeof(RegularException)];
187 new (expr) RegularException{};
188}
189

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/throw-keyword-missing.cpp