1 | // RUN: %check_clang_tidy -std=c++20 %s bugprone-exception-escape %t -- \ |
2 | // RUN: -- -fexceptions |
3 | |
4 | namespace std { |
5 | |
6 | template <class Ret, typename... T> struct coroutine_traits { |
7 | using promise_type = typename Ret::promise_type; |
8 | }; |
9 | |
10 | template <class Promise = void> struct coroutine_handle { |
11 | static coroutine_handle from_address(void *) noexcept; |
12 | static coroutine_handle from_promise(Promise &promise); |
13 | constexpr void *address() const noexcept; |
14 | }; |
15 | |
16 | template <> struct coroutine_handle<void> { |
17 | template <class PromiseType> |
18 | coroutine_handle(coroutine_handle<PromiseType>) noexcept; |
19 | static coroutine_handle from_address(void *); |
20 | constexpr void *address() const noexcept; |
21 | }; |
22 | |
23 | struct suspend_always { |
24 | bool await_ready() noexcept { return false; } |
25 | void await_suspend(coroutine_handle<>) noexcept {} |
26 | void await_resume() noexcept {} |
27 | }; |
28 | |
29 | struct suspend_never { |
30 | bool await_ready() noexcept { return true; } |
31 | void await_suspend(coroutine_handle<>) noexcept {} |
32 | void await_resume() noexcept {} |
33 | }; |
34 | |
35 | } // namespace std |
36 | |
37 | template <typename Task, typename T, bool ThrowInPromiseConstructor, |
38 | bool ThrowInInitialSuspend, bool ThrowInGetReturnObject, |
39 | bool ThrowInUnhandledException, bool RethrowInUnhandledException> |
40 | struct Promise; |
41 | |
42 | template < |
43 | typename T, bool ThrowInTaskConstructor = false, |
44 | bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, |
45 | bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, |
46 | bool RethrowInUnhandledException = false> |
47 | struct Task { |
48 | using promise_type = |
49 | Promise<Task, T, ThrowInPromiseConstructor, ThrowInInitialSuspend, |
50 | ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; |
51 | |
52 | explicit Task(promise_type &p) { |
53 | if constexpr (ThrowInTaskConstructor) { |
54 | throw 1; |
55 | } |
56 | |
57 | p.return_val = this; |
58 | } |
59 | |
60 | bool await_ready() { return true; } |
61 | |
62 | void await_suspend(std::coroutine_handle<> h) {} |
63 | |
64 | void await_resume() {} |
65 | |
66 | T value; |
67 | }; |
68 | |
69 | template <bool ThrowInTaskConstructor, bool ThrowInPromiseConstructor, |
70 | bool ThrowInInitialSuspend, bool ThrowInGetReturnObject, |
71 | bool ThrowInUnhandledException, bool RethrowInUnhandledException> |
72 | struct Task<void, ThrowInTaskConstructor, ThrowInPromiseConstructor, |
73 | ThrowInInitialSuspend, ThrowInGetReturnObject, |
74 | ThrowInUnhandledException, RethrowInUnhandledException> { |
75 | using promise_type = |
76 | Promise<Task, void, ThrowInPromiseConstructor, ThrowInInitialSuspend, |
77 | ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; |
78 | |
79 | explicit Task(promise_type &p) { |
80 | if constexpr (ThrowInTaskConstructor) { |
81 | throw 1; |
82 | } |
83 | |
84 | p.return_val = this; |
85 | } |
86 | |
87 | bool await_ready() { return true; } |
88 | |
89 | void await_suspend(std::coroutine_handle<> h) {} |
90 | |
91 | void await_resume() {} |
92 | }; |
93 | |
94 | template <typename Task, typename T, bool ThrowInPromiseConstructor, |
95 | bool ThrowInInitialSuspend, bool ThrowInGetReturnObject, |
96 | bool ThrowInUnhandledException, bool RethrowInUnhandledException> |
97 | struct Promise { |
98 | Promise() { |
99 | if constexpr (ThrowInPromiseConstructor) { |
100 | throw 1; |
101 | } |
102 | } |
103 | |
104 | Task get_return_object() { |
105 | if constexpr (ThrowInGetReturnObject) { |
106 | throw 1; |
107 | } |
108 | |
109 | return Task{*this}; |
110 | } |
111 | |
112 | std::suspend_never initial_suspend() const { |
113 | if constexpr (ThrowInInitialSuspend) { |
114 | throw 1; |
115 | } |
116 | |
117 | return {}; |
118 | } |
119 | |
120 | std::suspend_never final_suspend() const noexcept { return {}; } |
121 | |
122 | template <typename U> void return_value(U &&val) { |
123 | return_val->value = static_cast<U &&>(val); |
124 | } |
125 | |
126 | template <typename U> std::suspend_never yield_value(U &&val) { |
127 | return_val->value = static_cast<U &&>(val); |
128 | return {}; |
129 | } |
130 | |
131 | void unhandled_exception() { |
132 | if constexpr (ThrowInUnhandledException) { |
133 | throw 1; |
134 | } else if constexpr (RethrowInUnhandledException) { |
135 | throw; |
136 | } |
137 | } |
138 | |
139 | Task *return_val; |
140 | }; |
141 | |
142 | template <typename Task, bool ThrowInPromiseConstructor, |
143 | bool ThrowInInitialSuspend, bool ThrowInGetReturnObject, |
144 | bool ThrowInUnhandledException, bool RethrowInUnhandledException> |
145 | struct Promise<Task, void, ThrowInPromiseConstructor, ThrowInInitialSuspend, |
146 | ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { |
147 | Promise() { |
148 | if constexpr (ThrowInPromiseConstructor) { |
149 | throw 1; |
150 | } |
151 | } |
152 | |
153 | Task get_return_object() { |
154 | if constexpr (ThrowInGetReturnObject) { |
155 | throw 1; |
156 | } |
157 | |
158 | return Task{*this}; |
159 | } |
160 | |
161 | std::suspend_never initial_suspend() const { |
162 | if constexpr (ThrowInInitialSuspend) { |
163 | throw 1; |
164 | } |
165 | |
166 | return {}; |
167 | } |
168 | |
169 | std::suspend_never final_suspend() const noexcept { return {}; } |
170 | |
171 | void return_void() {} |
172 | |
173 | void unhandled_exception() { |
174 | if constexpr (ThrowInUnhandledException) { |
175 | throw 1; |
176 | } else if constexpr (RethrowInUnhandledException) { |
177 | throw; |
178 | } |
179 | } |
180 | |
181 | Task *return_val; |
182 | }; |
183 | |
184 | struct Evil { |
185 | ~Evil() noexcept(false) { |
186 | throw 42; |
187 | } |
188 | }; |
189 | |
190 | Task<int> returnOne() { co_return 1; } |
191 | |
192 | namespace function { |
193 | |
194 | namespace coreturn { |
195 | |
196 | Task<int> a_ShouldNotDiag(const int a, const int b) { |
197 | if (b == 0) |
198 | throw b; |
199 | |
200 | co_return a / b; |
201 | } |
202 | |
203 | Task<int> b_ShouldNotDiag(const int a, const int b) noexcept { |
204 | if (b == 0) |
205 | throw b; |
206 | |
207 | co_return a / b; |
208 | } |
209 | |
210 | Task<int> c_ShouldNotDiag(const int a, const int b) { |
211 | if (b == 0) |
212 | throw Evil{}; |
213 | |
214 | co_return a / b; |
215 | } |
216 | |
217 | Task<int> c_ShouldDiag(const int a, const int b) noexcept { |
218 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: an exception may be thrown in function 'c_ShouldDiag' which should not throw exceptions |
219 | if (b == 0) |
220 | throw Evil{}; |
221 | |
222 | co_return a / b; |
223 | } |
224 | |
225 | Task<int, true> d_ShouldNotDiag(const int a, const int b) { |
226 | co_return a / b; |
227 | } |
228 | |
229 | Task<int, true> d_ShouldDiag(const int a, const int b) noexcept { |
230 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions |
231 | co_return a / b; |
232 | } |
233 | |
234 | Task<int, false, true> e_ShouldNotDiag(const int a, const int b) { |
235 | co_return a / b; |
236 | } |
237 | |
238 | Task<int, false, true> e_ShouldDiag(const int a, const int b) noexcept { |
239 | // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions |
240 | co_return a / b; |
241 | } |
242 | |
243 | Task<int, false, false, true> f_ShouldNotDiag(const int a, const int b) { |
244 | co_return a / b; |
245 | } |
246 | |
247 | Task<int, false, false, true> f_ShouldDiag(const int a, const int b) noexcept { |
248 | // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions |
249 | co_return a / b; |
250 | } |
251 | |
252 | Task<int, false, false, false, true> g_ShouldNotDiag(const int a, const int b) { |
253 | co_return a / b; |
254 | } |
255 | |
256 | Task<int, false, false, false, true> g_ShouldDiag(const int a, |
257 | const int b) noexcept { |
258 | // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions |
259 | co_return a / b; |
260 | } |
261 | |
262 | Task<int, false, false, false, false, true> h_ShouldNotDiag(const int a, |
263 | const int b) { |
264 | co_return a / b; |
265 | } |
266 | |
267 | Task<int, false, false, false, false, true> h_ShouldDiag(const int a, |
268 | const int b) noexcept { |
269 | // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions |
270 | co_return a / b; |
271 | } |
272 | |
273 | Task<int, false, false, false, false, false, true> |
274 | i_ShouldNotDiag(const int a, const int b) { |
275 | co_return a / b; |
276 | } |
277 | |
278 | Task<int, false, false, false, false, false, true> |
279 | i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { |
280 | co_return a / b; |
281 | } |
282 | |
283 | Task<int, false, false, false, false, false, true> |
284 | j_ShouldNotDiag(const int a, const int b) { |
285 | if (b == 0) |
286 | throw b; |
287 | |
288 | co_return a / b; |
289 | } |
290 | |
291 | Task<int, false, false, false, false, false, true> |
292 | j_ShouldDiag(const int a, const int b) noexcept { |
293 | // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions |
294 | if (b == 0) |
295 | throw b; |
296 | |
297 | co_return a / b; |
298 | } |
299 | |
300 | } // namespace coreturn |
301 | |
302 | namespace coyield { |
303 | |
304 | Task<int> a_ShouldNotDiag(const int a, const int b) { |
305 | if (b == 0) |
306 | throw b; |
307 | |
308 | co_yield a / b; |
309 | } |
310 | |
311 | Task<int> b_ShouldNotDiag(const int a, const int b) noexcept { |
312 | if (b == 0) |
313 | throw b; |
314 | |
315 | co_yield a / b; |
316 | } |
317 | |
318 | Task<int> c_ShouldNotDiag(const int a, const int b) { |
319 | if (b == 0) |
320 | throw Evil{}; |
321 | |
322 | co_yield a / b; |
323 | } |
324 | |
325 | Task<int> c_ShouldDiag(const int a, const int b) noexcept { |
326 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: an exception may be thrown in function 'c_ShouldDiag' which should not throw exceptions |
327 | if (b == 0) |
328 | throw Evil{}; |
329 | |
330 | co_yield a / b; |
331 | } |
332 | |
333 | Task<int, true> d_ShouldNotDiag(const int a, const int b) { |
334 | co_yield a / b; |
335 | } |
336 | |
337 | Task<int, true> d_ShouldDiag(const int a, const int b) noexcept { |
338 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions |
339 | co_yield a / b; |
340 | } |
341 | |
342 | Task<int, false, true> e_ShouldNotDiag(const int a, const int b) { |
343 | co_yield a / b; |
344 | } |
345 | |
346 | Task<int, false, true> e_ShouldDiag(const int a, const int b) noexcept { |
347 | // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions |
348 | co_yield a / b; |
349 | } |
350 | |
351 | Task<int, false, false, true> f_ShouldNotDiag(const int a, const int b) { |
352 | co_yield a / b; |
353 | } |
354 | |
355 | Task<int, false, false, true> f_ShouldDiag(const int a, const int b) noexcept { |
356 | // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions |
357 | co_yield a / b; |
358 | } |
359 | |
360 | Task<int, false, false, false, true> g_ShouldNotDiag(const int a, const int b) { |
361 | co_yield a / b; |
362 | } |
363 | |
364 | Task<int, false, false, false, true> g_ShouldDiag(const int a, |
365 | const int b) noexcept { |
366 | // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions |
367 | co_yield a / b; |
368 | } |
369 | |
370 | Task<int, false, false, false, false, true> h_ShouldNotDiag(const int a, |
371 | const int b) { |
372 | co_yield a / b; |
373 | } |
374 | |
375 | Task<int, false, false, false, false, true> h_ShouldDiag(const int a, |
376 | const int b) noexcept { |
377 | // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions |
378 | co_yield a / b; |
379 | } |
380 | |
381 | Task<int, false, false, false, false, false, true> |
382 | i_ShouldNotDiag(const int a, const int b) { |
383 | co_yield a / b; |
384 | } |
385 | |
386 | Task<int, false, false, false, false, false, true> |
387 | i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { |
388 | co_yield a / b; |
389 | } |
390 | |
391 | Task<int, false, false, false, false, false, true> |
392 | j_ShouldNotDiag(const int a, const int b) { |
393 | if (b == 0) |
394 | throw b; |
395 | |
396 | co_yield a / b; |
397 | } |
398 | |
399 | Task<int, false, false, false, false, false, true> |
400 | j_ShouldDiag(const int a, const int b) noexcept { |
401 | // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions |
402 | if (b == 0) |
403 | throw b; |
404 | |
405 | co_yield a / b; |
406 | } |
407 | |
408 | } // namespace coyield |
409 | |
410 | namespace coawait { |
411 | |
412 | Task<void> a_ShouldNotDiag(const int a, const int b) { |
413 | if (b == 0) |
414 | throw b; |
415 | |
416 | co_await returnOne(); |
417 | } |
418 | |
419 | Task<void> b_ShouldNotDiag(const int a, const int b) noexcept { |
420 | if (b == 0) |
421 | throw b; |
422 | |
423 | co_await returnOne(); |
424 | } |
425 | |
426 | Task<void> c_ShouldNotDiag(const int a, const int b) { |
427 | if (b == 0) |
428 | throw Evil{}; |
429 | |
430 | co_await returnOne(); |
431 | } |
432 | |
433 | Task<void> c_ShouldDiag(const int a, const int b) noexcept { |
434 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: an exception may be thrown in function 'c_ShouldDiag' which should not throw exceptions |
435 | if (b == 0) |
436 | throw Evil{}; |
437 | |
438 | co_await returnOne(); |
439 | } |
440 | |
441 | Task<void, true> d_ShouldNotDiag(const int a, const int b) { |
442 | co_await returnOne(); |
443 | } |
444 | |
445 | Task<void, true> d_ShouldDiag(const int a, const int b) noexcept { |
446 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions |
447 | co_await returnOne(); |
448 | } |
449 | |
450 | Task<void, false, true> e_ShouldNotDiag(const int a, const int b) { |
451 | co_await returnOne(); |
452 | } |
453 | |
454 | Task<void, false, true> e_ShouldDiag(const int a, const int b) noexcept { |
455 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions |
456 | co_await returnOne(); |
457 | } |
458 | |
459 | Task<void, false, false, true> f_ShouldNotDiag(const int a, const int b) { |
460 | co_await returnOne(); |
461 | } |
462 | |
463 | Task<void, false, false, true> f_ShouldDiag(const int a, const int b) noexcept { |
464 | // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions |
465 | co_await returnOne(); |
466 | } |
467 | |
468 | Task<void, false, false, false, true> g_ShouldNotDiag(const int a, |
469 | const int b) { |
470 | co_await returnOne(); |
471 | } |
472 | |
473 | Task<void, false, false, false, true> g_ShouldDiag(const int a, |
474 | const int b) noexcept { |
475 | // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions |
476 | co_await returnOne(); |
477 | } |
478 | |
479 | Task<void, false, false, false, false, true> h_ShouldNotDiag(const int a, |
480 | const int b) { |
481 | co_await returnOne(); |
482 | } |
483 | |
484 | Task<void, false, false, false, false, true> |
485 | h_ShouldDiag(const int a, const int b) noexcept { |
486 | // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions |
487 | co_await returnOne(); |
488 | } |
489 | |
490 | Task<int, false, false, false, false, false, true> |
491 | i_ShouldNotDiag(const int a, const int b) { |
492 | co_await returnOne(); |
493 | } |
494 | |
495 | Task<int, false, false, false, false, false, true> |
496 | i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { |
497 | co_await returnOne(); |
498 | } |
499 | |
500 | Task<int, false, false, false, false, false, true> |
501 | j_ShouldNotDiag(const int a, const int b) { |
502 | co_await returnOne(); |
503 | if (b == 0) |
504 | throw b; |
505 | } |
506 | |
507 | Task<int, false, false, false, false, false, true> |
508 | j_ShouldDiag(const int a, const int b) noexcept { |
509 | // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions |
510 | co_await returnOne(); |
511 | if (b == 0) |
512 | throw b; |
513 | } |
514 | |
515 | } // namespace coawait |
516 | |
517 | } // namespace function |
518 | |
519 | namespace lambda { |
520 | |
521 | namespace coreturn { |
522 | |
523 | const auto a_ShouldNotDiag = [](const int a, const int b) -> Task<int> { |
524 | if (b == 0) |
525 | throw b; |
526 | |
527 | co_return a / b; |
528 | }; |
529 | |
530 | const auto b_ShouldNotDiag = [](const int a, |
531 | const int b) noexcept -> Task<int> { |
532 | if (b == 0) |
533 | throw b; |
534 | |
535 | co_return a / b; |
536 | }; |
537 | |
538 | const auto c_ShouldNotDiag = [](const int a, const int b) -> Task<int> { |
539 | if (b == 0) |
540 | throw Evil{}; |
541 | |
542 | co_return a / b; |
543 | }; |
544 | |
545 | const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task<int> { |
546 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
547 | if (b == 0) |
548 | throw Evil{}; |
549 | |
550 | co_return a / b; |
551 | }; |
552 | |
553 | const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<int, true> { |
554 | co_return a / b; |
555 | }; |
556 | |
557 | const auto d_ShouldDiag = [](const int a, |
558 | const int b) noexcept -> Task<int, true> { |
559 | // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
560 | co_return a / b; |
561 | }; |
562 | |
563 | const auto e_ShouldNotDiag = [](const int a, |
564 | const int b) -> Task<int, false, true> { |
565 | co_return a / b; |
566 | }; |
567 | |
568 | const auto e_ShouldDiag = [](const int a, |
569 | const int b) noexcept -> Task<int, false, true> { |
570 | // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
571 | co_return a / b; |
572 | }; |
573 | |
574 | const auto f_ShouldNotDiag = [](const int a, |
575 | const int b) -> Task<int, false, false, true> { |
576 | co_return a / b; |
577 | }; |
578 | |
579 | const auto f_ShouldDiag = |
580 | [](const int a, const int b) noexcept -> Task<int, false, false, true> { |
581 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
582 | co_return a / b; |
583 | }; |
584 | |
585 | const auto g_ShouldNotDiag = |
586 | [](const int a, const int b) -> Task<int, false, false, false, true> { |
587 | co_return a / b; |
588 | }; |
589 | |
590 | const auto g_ShouldDiag = |
591 | [](const int a, |
592 | const int b) noexcept -> Task<int, false, false, false, true> { |
593 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
594 | co_return a / b; |
595 | }; |
596 | |
597 | const auto h_ShouldNotDiag = |
598 | [](const int a, |
599 | const int b) -> Task<int, false, false, false, false, true> { |
600 | co_return a / b; |
601 | }; |
602 | |
603 | const auto h_ShouldDiag = |
604 | [](const int a, |
605 | const int b) noexcept -> Task<int, false, false, false, false, true> { |
606 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
607 | co_return a / b; |
608 | }; |
609 | |
610 | const auto i_ShouldNotDiag = |
611 | [](const int a, |
612 | const int b) -> Task<int, false, false, false, false, false, true> { |
613 | co_return a / b; |
614 | }; |
615 | |
616 | const auto i_ShouldNotDiagNoexcept = |
617 | [](const int a, |
618 | const int b) noexcept -> Task<int, false, false, false, false, false, true> { |
619 | co_return a / b; |
620 | }; |
621 | |
622 | const auto j_ShouldNotDiag = |
623 | [](const int a, |
624 | const int b) -> Task<int, false, false, false, false, false, true> { |
625 | if (b == 0) |
626 | throw b; |
627 | |
628 | co_return a / b; |
629 | }; |
630 | |
631 | const auto j_ShouldDiag = |
632 | [](const int a, |
633 | const int b) noexcept -> Task<int, false, false, false, false, false, true> { |
634 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
635 | if (b == 0) |
636 | throw b; |
637 | |
638 | co_return a / b; |
639 | }; |
640 | |
641 | } // namespace coreturn |
642 | |
643 | namespace coyield { |
644 | |
645 | const auto a_ShouldNotDiag = [](const int a, const int b) -> Task<int> { |
646 | if (b == 0) |
647 | throw b; |
648 | |
649 | co_yield a / b; |
650 | }; |
651 | |
652 | const auto b_ShouldNotDiag = [](const int a, |
653 | const int b) noexcept -> Task<int> { |
654 | if (b == 0) |
655 | throw b; |
656 | |
657 | co_yield a / b; |
658 | }; |
659 | |
660 | const auto c_ShouldNotDiag = [](const int a, const int b) -> Task<int> { |
661 | if (b == 0) |
662 | throw Evil{}; |
663 | |
664 | co_yield a / b; |
665 | }; |
666 | |
667 | const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task<int> { |
668 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
669 | if (b == 0) |
670 | throw Evil{}; |
671 | |
672 | co_yield a / b; |
673 | }; |
674 | |
675 | const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<int, true> { |
676 | co_yield a / b; |
677 | }; |
678 | |
679 | const auto d_ShouldDiag = [](const int a, |
680 | const int b) noexcept -> Task<int, true> { |
681 | // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
682 | co_yield a / b; |
683 | }; |
684 | |
685 | const auto e_ShouldNotDiag = [](const int a, |
686 | const int b) -> Task<int, false, true> { |
687 | co_yield a / b; |
688 | }; |
689 | |
690 | const auto e_ShouldDiag = [](const int a, |
691 | const int b) noexcept -> Task<int, false, true> { |
692 | // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
693 | co_yield a / b; |
694 | }; |
695 | |
696 | const auto f_ShouldNotDiag = [](const int a, |
697 | const int b) -> Task<int, false, false, true> { |
698 | co_yield a / b; |
699 | }; |
700 | |
701 | const auto f_ShouldDiag = |
702 | [](const int a, const int b) noexcept -> Task<int, false, false, true> { |
703 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
704 | co_yield a / b; |
705 | }; |
706 | |
707 | const auto g_ShouldNotDiag = |
708 | [](const int a, const int b) -> Task<int, false, false, false, true> { |
709 | co_yield a / b; |
710 | }; |
711 | |
712 | const auto g_ShouldDiag = |
713 | [](const int a, |
714 | const int b) noexcept -> Task<int, false, false, false, true> { |
715 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
716 | co_yield a / b; |
717 | }; |
718 | |
719 | const auto h_ShouldNotDiag = |
720 | [](const int a, |
721 | const int b) -> Task<int, false, false, false, false, true> { |
722 | co_yield a / b; |
723 | }; |
724 | |
725 | const auto h_ShouldDiag = |
726 | [](const int a, |
727 | const int b) noexcept -> Task<int, false, false, false, false, true> { |
728 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
729 | co_yield a / b; |
730 | }; |
731 | |
732 | const auto i_ShouldNotDiag = |
733 | [](const int a, |
734 | const int b) -> Task<int, false, false, false, false, false, true> { |
735 | co_yield a / b; |
736 | }; |
737 | |
738 | const auto i_ShouldNotDiagNoexcept = |
739 | [](const int a, |
740 | const int b) noexcept -> Task<int, false, false, false, false, false, true> { |
741 | co_yield a / b; |
742 | }; |
743 | |
744 | const auto j_ShouldNotDiag = |
745 | [](const int a, |
746 | const int b) -> Task<int, false, false, false, false, false, true> { |
747 | if (b == 0) |
748 | throw b; |
749 | |
750 | co_yield a / b; |
751 | }; |
752 | |
753 | const auto j_ShouldDiag = |
754 | [](const int a, |
755 | const int b) noexcept -> Task<int, false, false, false, false, false, true> { |
756 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
757 | if (b == 0) |
758 | throw b; |
759 | |
760 | co_yield a / b; |
761 | }; |
762 | |
763 | } // namespace coyield |
764 | |
765 | namespace coawait { |
766 | |
767 | const auto a_ShouldNotDiag = [](const int a, const int b) -> Task<void> { |
768 | if (b == 0) |
769 | throw b; |
770 | |
771 | co_await returnOne(); |
772 | }; |
773 | |
774 | const auto b_ShouldNotDiag = [](const int a, |
775 | const int b) noexcept -> Task<void> { |
776 | if (b == 0) |
777 | throw b; |
778 | |
779 | co_await returnOne(); |
780 | }; |
781 | |
782 | const auto c_ShouldNotDiag = [](const int a, const int b) -> Task<void> { |
783 | if (b == 0) |
784 | throw Evil{}; |
785 | |
786 | co_await returnOne(); |
787 | }; |
788 | |
789 | const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task<void> { |
790 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
791 | if (b == 0) |
792 | throw Evil{}; |
793 | |
794 | co_await returnOne(); |
795 | }; |
796 | |
797 | const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<void, true> { |
798 | co_await returnOne(); |
799 | }; |
800 | |
801 | const auto d_ShouldDiag = [](const int a, |
802 | const int b) noexcept -> Task<void, true> { |
803 | // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
804 | co_await returnOne(); |
805 | }; |
806 | |
807 | const auto e_ShouldNotDiag = [](const int a, |
808 | const int b) -> Task<void, false, true> { |
809 | co_await returnOne(); |
810 | }; |
811 | |
812 | const auto e_ShouldDiag = [](const int a, |
813 | const int b) noexcept -> Task<void, false, true> { |
814 | // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
815 | co_await returnOne(); |
816 | }; |
817 | |
818 | const auto f_ShouldNotDiag = [](const int a, |
819 | const int b) -> Task<void, false, false, true> { |
820 | co_await returnOne(); |
821 | }; |
822 | |
823 | const auto f_ShouldDiag = |
824 | [](const int a, const int b) noexcept -> Task<void, false, false, true> { |
825 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
826 | co_await returnOne(); |
827 | }; |
828 | |
829 | const auto g_ShouldNotDiag = |
830 | [](const int a, const int b) -> Task<void, false, false, false, true> { |
831 | co_await returnOne(); |
832 | }; |
833 | |
834 | const auto g_ShouldDiag = |
835 | [](const int a, |
836 | const int b) noexcept -> Task<void, false, false, false, true> { |
837 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
838 | co_await returnOne(); |
839 | }; |
840 | |
841 | const auto h_ShouldNotDiag = |
842 | [](const int a, |
843 | const int b) -> Task<void, false, false, false, false, true> { |
844 | co_await returnOne(); |
845 | }; |
846 | |
847 | const auto h_ShouldDiag = |
848 | [](const int a, |
849 | const int b) noexcept -> Task<void, false, false, false, false, true> { |
850 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
851 | co_await returnOne(); |
852 | }; |
853 | |
854 | const auto i_ShouldNotDiag = |
855 | [](const int a, |
856 | const int b) -> Task<int, false, false, false, false, false, true> { |
857 | co_await returnOne(); |
858 | }; |
859 | |
860 | const auto i_ShouldNotDiagNoexcept = |
861 | [](const int a, |
862 | const int b) noexcept -> Task<int, false, false, false, false, false, true> { |
863 | co_await returnOne(); |
864 | }; |
865 | |
866 | const auto j_ShouldNotDiag = |
867 | [](const int a, |
868 | const int b) -> Task<int, false, false, false, false, false, true> { |
869 | co_await returnOne(); |
870 | if (b == 0) |
871 | throw b; |
872 | }; |
873 | |
874 | const auto j_ShouldDiag = |
875 | [](const int a, |
876 | const int b) noexcept -> Task<int, false, false, false, false, false, true> { |
877 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions |
878 | co_await returnOne(); |
879 | if (b == 0) |
880 | throw b; |
881 | }; |
882 | |
883 | } // namespace coawait |
884 | |
885 | } // namespace lambda |
886 | |