1 // RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-escape %t -- \
2 // RUN:     -config="{CheckOptions: [ \
3 // RUN:         {key: bugprone-exception-escape.IgnoredExceptions, value: 'ignored1,ignored2'}, \
4 // RUN:         {key: bugprone-exception-escape.FunctionsThatShouldNotThrow, value: 'enabled1,enabled2,enabled3'} \
5 // RUN:     ]}" \
6 // RUN:     -- -fexceptions
7 
8 struct throwing_destructor {
~throwing_destructorthrowing_destructor9   ~throwing_destructor() {
10     // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions
11     throw 1;
12   }
13 };
14 
15 struct throwing_move_constructor {
throwing_move_constructorthrowing_move_constructor16   throwing_move_constructor(throwing_move_constructor&&) {
17     // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions
18     throw 1;
19   }
20 };
21 
22 struct throwing_move_assignment {
operator =throwing_move_assignment23   throwing_move_assignment& operator=(throwing_move_assignment&&) {
24     // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
25     throw 1;
26   }
27 };
28 
throwing_noexcept()29 void throwing_noexcept() noexcept {
30     // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions
31   throw 1;
32 }
33 
throwing_throw_nothing()34 void throwing_throw_nothing() throw() {
35     // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions
36   throw 1;
37 }
38 
throw_and_catch()39 void throw_and_catch() noexcept {
40   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions
41   try {
42     throw 1;
43   } catch(int &) {
44   }
45 }
46 
throw_and_catch_some(int n)47 void throw_and_catch_some(int n) noexcept {
48   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions
49   try {
50     if (n) throw 1;
51     throw 1.1;
52   } catch(int &) {
53   }
54 }
55 
throw_and_catch_each(int n)56 void throw_and_catch_each(int n) noexcept {
57   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions
58   try {
59     if (n) throw 1;
60     throw 1.1;
61   } catch(int &) {
62   } catch(double &) {
63   }
64 }
65 
throw_and_catch_all(int n)66 void throw_and_catch_all(int n) noexcept {
67   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions
68   try {
69     if (n) throw 1;
70     throw 1.1;
71   } catch(...) {
72   }
73 }
74 
throw_and_rethrow()75 void throw_and_rethrow() noexcept {
76   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions
77   try {
78     throw 1;
79   } catch(int &) {
80     throw;
81   }
82 }
83 
throw_catch_throw()84 void throw_catch_throw() noexcept {
85   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions
86   try {
87     throw 1;
88   } catch(int &) {
89     throw 2;
90   }
91 }
92 
throw_catch_rethrow_the_rest(int n)93 void throw_catch_rethrow_the_rest(int n) noexcept {
94   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions
95   try {
96     if (n) throw 1;
97     throw 1.1;
98   } catch(int &) {
99   } catch(...) {
100     throw;
101   }
102 }
103 
104 class base {};
105 class derived: public base {};
106 
throw_derived_catch_base()107 void throw_derived_catch_base() noexcept {
108   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions
109   try {
110     throw derived();
111   } catch(base &) {
112   }
113 }
114 
try_nested_try(int n)115 void try_nested_try(int n) noexcept {
116   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions
117   try {
118     try {
119       if (n) throw 1;
120       throw 1.1;
121     } catch(int &) {
122     }
123   } catch(double &) {
124   }
125 }
126 
bad_try_nested_try(int n)127 void bad_try_nested_try(int n) noexcept {
128   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions
129   try {
130     if (n) throw 1;
131     try {
132       throw 1.1;
133     } catch(int &) {
134     }
135   } catch(double &) {
136   }
137 }
138 
try_nested_catch()139 void try_nested_catch() noexcept {
140   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions
141   try {
142     try {
143       throw 1;
144     } catch(int &) {
145       throw 1.1;
146     }
147   } catch(double &) {
148   }
149 }
150 
catch_nested_try()151 void catch_nested_try() noexcept {
152   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions
153   try {
154     throw 1;
155   } catch(int &) {
156     try {
157       throw 1;
158     } catch(int &) {
159     }
160   }
161 }
162 
bad_catch_nested_try()163 void bad_catch_nested_try() noexcept {
164   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions
165   try {
166     throw 1;
167   } catch(int &) {
168     try {
169       throw 1.1;
170     } catch(int &) {
171     }
172   } catch(double &) {
173   }
174 }
175 
implicit_int_thrower()176 void implicit_int_thrower() {
177   throw 1;
178 }
179 
180 void explicit_int_thrower() throw(int);
181 
indirect_implicit()182 void indirect_implicit() noexcept {
183   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions
184   implicit_int_thrower();
185 }
186 
indirect_explicit()187 void indirect_explicit() noexcept {
188   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions
189   explicit_int_thrower();
190 }
191 
indirect_catch()192 void indirect_catch() noexcept {
193   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions
194   try {
195     implicit_int_thrower();
196   } catch(int&) {
197   }
198 }
199 
200 template<typename T>
dependent_throw()201 void dependent_throw() noexcept(sizeof(T)<4) {
202   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions
203   if (sizeof(T) > 4)
204     throw 1;
205 }
206 
swap(int &,int &)207 void swap(int&, int&) {
208   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions
209   throw 1;
210 }
211 
212 namespace std {
213 class bad_alloc {};
214 }
215 
alloc()216 void alloc() {
217   throw std::bad_alloc();
218 }
219 
allocator()220 void allocator() noexcept {
221   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions
222   alloc();
223 }
224 
enabled1()225 void enabled1() {
226   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions
227   throw 1;
228 }
229 
enabled2()230 void enabled2() {
231   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions
232   enabled1();
233 }
234 
enabled3()235 void enabled3() {
236   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions
237   try {
238     enabled1();
239   } catch(...) {
240   }
241 }
242 
243 class ignored1 {};
244 class ignored2 {};
245 
this_does_not_count()246 void this_does_not_count() noexcept {
247   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions
248   throw ignored1();
249 }
250 
this_does_not_count_either(int n)251 void this_does_not_count_either(int n) noexcept {
252   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions
253   try {
254     throw 1;
255     if (n) throw ignored2();
256   } catch(int &) {
257   }
258 }
259 
this_counts(int n)260 void this_counts(int n) noexcept {
261   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions
262   if (n) throw 1;
263   throw ignored1();
264 }
265 
thrower(int n)266 void thrower(int n) {
267   throw n;
268 }
269 
directly_recursive(int n)270 int directly_recursive(int n) noexcept {
271   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions
272   if (n == 0)
273     thrower(n);
274   return directly_recursive(n);
275 }
276 
277 int indirectly_recursive(int n) noexcept;
278   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
279 
recursion_helper(int n)280 int recursion_helper(int n) {
281   indirectly_recursive(n);
282 }
283 
indirectly_recursive(int n)284 int indirectly_recursive(int n) noexcept {
285   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
286   if (n == 0)
287     thrower(n);
288   return recursion_helper(n);
289 }
290 
main()291 int main() {
292   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
293   throw 1;
294   return 0;
295 }
296