1// RUN: %check_clang_tidy -std=c++20 %s bugprone-exception-escape %t -- \
2// RUN: -- -fexceptions
3
4namespace std {
5
6template <class Ret, typename... T> struct coroutine_traits {
7 using promise_type = typename Ret::promise_type;
8};
9
10template <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
16template <> 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
23struct suspend_always {
24 bool await_ready() noexcept { return false; }
25 void await_suspend(coroutine_handle<>) noexcept {}
26 void await_resume() noexcept {}
27};
28
29struct 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
37template <typename Task, typename T, bool ThrowInPromiseConstructor,
38 bool ThrowInInitialSuspend, bool ThrowInGetReturnObject,
39 bool ThrowInUnhandledException, bool RethrowInUnhandledException>
40struct Promise;
41
42template <
43 typename T, bool ThrowInTaskConstructor = false,
44 bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false,
45 bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false,
46 bool RethrowInUnhandledException = false>
47struct 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
69template <bool ThrowInTaskConstructor, bool ThrowInPromiseConstructor,
70 bool ThrowInInitialSuspend, bool ThrowInGetReturnObject,
71 bool ThrowInUnhandledException, bool RethrowInUnhandledException>
72struct 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
94template <typename Task, typename T, bool ThrowInPromiseConstructor,
95 bool ThrowInInitialSuspend, bool ThrowInGetReturnObject,
96 bool ThrowInUnhandledException, bool RethrowInUnhandledException>
97struct 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
142template <typename Task, bool ThrowInPromiseConstructor,
143 bool ThrowInInitialSuspend, bool ThrowInGetReturnObject,
144 bool ThrowInUnhandledException, bool RethrowInUnhandledException>
145struct 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
184struct Evil {
185 ~Evil() noexcept(false) {
186 throw 42;
187 }
188};
189
190Task<int> returnOne() { co_return 1; }
191
192namespace function {
193
194namespace coreturn {
195
196Task<int> a_ShouldNotDiag(const int a, const int b) {
197 if (b == 0)
198 throw b;
199
200 co_return a / b;
201}
202
203Task<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
210Task<int> c_ShouldNotDiag(const int a, const int b) {
211 if (b == 0)
212 throw Evil{};
213
214 co_return a / b;
215}
216
217Task<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
225Task<int, true> d_ShouldNotDiag(const int a, const int b) {
226 co_return a / b;
227}
228
229Task<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
234Task<int, false, true> e_ShouldNotDiag(const int a, const int b) {
235 co_return a / b;
236}
237
238Task<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
243Task<int, false, false, true> f_ShouldNotDiag(const int a, const int b) {
244 co_return a / b;
245}
246
247Task<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
252Task<int, false, false, false, true> g_ShouldNotDiag(const int a, const int b) {
253 co_return a / b;
254}
255
256Task<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
262Task<int, false, false, false, false, true> h_ShouldNotDiag(const int a,
263 const int b) {
264 co_return a / b;
265}
266
267Task<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
273Task<int, false, false, false, false, false, true>
274i_ShouldNotDiag(const int a, const int b) {
275 co_return a / b;
276}
277
278Task<int, false, false, false, false, false, true>
279i_ShouldNotDiagNoexcept(const int a, const int b) noexcept {
280 co_return a / b;
281}
282
283Task<int, false, false, false, false, false, true>
284j_ShouldNotDiag(const int a, const int b) {
285 if (b == 0)
286 throw b;
287
288 co_return a / b;
289}
290
291Task<int, false, false, false, false, false, true>
292j_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
302namespace coyield {
303
304Task<int> a_ShouldNotDiag(const int a, const int b) {
305 if (b == 0)
306 throw b;
307
308 co_yield a / b;
309}
310
311Task<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
318Task<int> c_ShouldNotDiag(const int a, const int b) {
319 if (b == 0)
320 throw Evil{};
321
322 co_yield a / b;
323}
324
325Task<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
333Task<int, true> d_ShouldNotDiag(const int a, const int b) {
334 co_yield a / b;
335}
336
337Task<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
342Task<int, false, true> e_ShouldNotDiag(const int a, const int b) {
343 co_yield a / b;
344}
345
346Task<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
351Task<int, false, false, true> f_ShouldNotDiag(const int a, const int b) {
352 co_yield a / b;
353}
354
355Task<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
360Task<int, false, false, false, true> g_ShouldNotDiag(const int a, const int b) {
361 co_yield a / b;
362}
363
364Task<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
370Task<int, false, false, false, false, true> h_ShouldNotDiag(const int a,
371 const int b) {
372 co_yield a / b;
373}
374
375Task<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
381Task<int, false, false, false, false, false, true>
382i_ShouldNotDiag(const int a, const int b) {
383 co_yield a / b;
384}
385
386Task<int, false, false, false, false, false, true>
387i_ShouldNotDiagNoexcept(const int a, const int b) noexcept {
388 co_yield a / b;
389}
390
391Task<int, false, false, false, false, false, true>
392j_ShouldNotDiag(const int a, const int b) {
393 if (b == 0)
394 throw b;
395
396 co_yield a / b;
397}
398
399Task<int, false, false, false, false, false, true>
400j_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
410namespace coawait {
411
412Task<void> a_ShouldNotDiag(const int a, const int b) {
413 if (b == 0)
414 throw b;
415
416 co_await returnOne();
417}
418
419Task<void> b_ShouldNotDiag(const int a, const int b) noexcept {
420 if (b == 0)
421 throw b;
422
423 co_await returnOne();
424}
425
426Task<void> c_ShouldNotDiag(const int a, const int b) {
427 if (b == 0)
428 throw Evil{};
429
430 co_await returnOne();
431}
432
433Task<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
441Task<void, true> d_ShouldNotDiag(const int a, const int b) {
442 co_await returnOne();
443}
444
445Task<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
450Task<void, false, true> e_ShouldNotDiag(const int a, const int b) {
451 co_await returnOne();
452}
453
454Task<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
459Task<void, false, false, true> f_ShouldNotDiag(const int a, const int b) {
460 co_await returnOne();
461}
462
463Task<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
468Task<void, false, false, false, true> g_ShouldNotDiag(const int a,
469 const int b) {
470 co_await returnOne();
471}
472
473Task<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
479Task<void, false, false, false, false, true> h_ShouldNotDiag(const int a,
480 const int b) {
481 co_await returnOne();
482}
483
484Task<void, false, false, false, false, true>
485h_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
490Task<int, false, false, false, false, false, true>
491i_ShouldNotDiag(const int a, const int b) {
492 co_await returnOne();
493}
494
495Task<int, false, false, false, false, false, true>
496i_ShouldNotDiagNoexcept(const int a, const int b) noexcept {
497 co_await returnOne();
498}
499
500Task<int, false, false, false, false, false, true>
501j_ShouldNotDiag(const int a, const int b) {
502 co_await returnOne();
503 if (b == 0)
504 throw b;
505}
506
507Task<int, false, false, false, false, false, true>
508j_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
519namespace lambda {
520
521namespace coreturn {
522
523const 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
530const 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
538const 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
545const 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
553const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<int, true> {
554 co_return a / b;
555};
556
557const 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
563const auto e_ShouldNotDiag = [](const int a,
564 const int b) -> Task<int, false, true> {
565 co_return a / b;
566};
567
568const 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
574const auto f_ShouldNotDiag = [](const int a,
575 const int b) -> Task<int, false, false, true> {
576 co_return a / b;
577};
578
579const 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
585const auto g_ShouldNotDiag =
586 [](const int a, const int b) -> Task<int, false, false, false, true> {
587 co_return a / b;
588};
589
590const 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
597const 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
603const 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
610const 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
616const 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
622const 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
631const 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
643namespace coyield {
644
645const 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
652const 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
660const 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
667const 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
675const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<int, true> {
676 co_yield a / b;
677};
678
679const 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
685const auto e_ShouldNotDiag = [](const int a,
686 const int b) -> Task<int, false, true> {
687 co_yield a / b;
688};
689
690const 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
696const auto f_ShouldNotDiag = [](const int a,
697 const int b) -> Task<int, false, false, true> {
698 co_yield a / b;
699};
700
701const 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
707const auto g_ShouldNotDiag =
708 [](const int a, const int b) -> Task<int, false, false, false, true> {
709 co_yield a / b;
710};
711
712const 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
719const 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
725const 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
732const 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
738const 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
744const 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
753const 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
765namespace coawait {
766
767const 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
774const 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
782const 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
789const 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
797const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<void, true> {
798 co_await returnOne();
799};
800
801const 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
807const auto e_ShouldNotDiag = [](const int a,
808 const int b) -> Task<void, false, true> {
809 co_await returnOne();
810};
811
812const 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
818const auto f_ShouldNotDiag = [](const int a,
819 const int b) -> Task<void, false, false, true> {
820 co_await returnOne();
821};
822
823const 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
829const auto g_ShouldNotDiag =
830 [](const int a, const int b) -> Task<void, false, false, false, true> {
831 co_await returnOne();
832};
833
834const 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
841const auto h_ShouldNotDiag =
842 [](const int a,
843 const int b) -> Task<void, false, false, false, false, true> {
844 co_await returnOne();
845};
846
847const 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
854const 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
860const 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
866const 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
874const 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

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp