1// RUN: %check_clang_tidy -std=c++20-or-later %s bugprone-exception-escape %t -- \
2// RUN: -- -fexceptions -Wno-error=return-type
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// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here
225// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #1: function 'c_ShouldDiag' calls function '~Evil'
226
227Task<int, true> d_ShouldNotDiag(const int a, const int b) {
228 co_return a / b;
229}
230
231Task<int, true> d_ShouldDiag(const int a, const int b) noexcept {
232 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions
233 co_return a / b;
234}
235// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here
236// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here
237// CHECK-MESSAGES: :[[@LINE-6]]:17: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here
238
239Task<int, false, true> e_ShouldNotDiag(const int a, const int b) {
240 co_return a / b;
241}
242
243Task<int, false, true> e_ShouldDiag(const int a, const int b) noexcept {
244 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions
245 co_return a / b;
246}
247// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here
248// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here
249
250Task<int, false, false, true> f_ShouldNotDiag(const int a, const int b) {
251 co_return a / b;
252}
253
254Task<int, false, false, true> f_ShouldDiag(const int a, const int b) noexcept {
255 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions
256 co_return a / b;
257}
258// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here
259// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here
260
261Task<int, false, false, false, true> g_ShouldNotDiag(const int a, const int b) {
262 co_return a / b;
263}
264
265Task<int, false, false, false, true> g_ShouldDiag(const int a,
266 const int b) noexcept {
267 // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions
268 co_return a / b;
269}
270// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here
271// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here
272
273Task<int, false, false, false, false, true> h_ShouldNotDiag(const int a,
274 const int b) {
275 co_return a / b;
276}
277
278Task<int, false, false, false, false, true> h_ShouldDiag(const int a,
279 const int b) noexcept {
280 // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions
281 co_return a / b;
282}
283// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here
284// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here
285
286Task<int, false, false, false, false, false, true>
287i_ShouldNotDiag(const int a, const int b) {
288 co_return a / b;
289}
290
291Task<int, false, false, false, false, false, true>
292i_ShouldNotDiagNoexcept(const int a, const int b) noexcept {
293 co_return a / b;
294}
295
296Task<int, false, false, false, false, false, true>
297j_ShouldNotDiag(const int a, const int b) {
298 if (b == 0)
299 throw b;
300
301 co_return a / b;
302}
303
304Task<int, false, false, false, false, false, true>
305j_ShouldDiag(const int a, const int b) noexcept {
306 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions
307 if (b == 0)
308 throw b;
309
310 co_return a / b;
311}
312// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'j_ShouldDiag' here
313
314} // namespace coreturn
315
316namespace coyield {
317
318Task<int> a_ShouldNotDiag(const int a, const int b) {
319 if (b == 0)
320 throw b;
321
322 co_yield a / b;
323}
324
325Task<int> b_ShouldNotDiag(const int a, const int b) noexcept {
326 if (b == 0)
327 throw b;
328
329 co_yield a / b;
330}
331
332Task<int> c_ShouldNotDiag(const int a, const int b) {
333 if (b == 0)
334 throw Evil{};
335
336 co_yield a / b;
337}
338
339Task<int> c_ShouldDiag(const int a, const int b) noexcept {
340 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: an exception may be thrown in function 'c_ShouldDiag' which should not throw exceptions
341 if (b == 0)
342 throw Evil{};
343
344 co_yield a / b;
345}
346// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here
347// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #1: function 'c_ShouldDiag' calls function '~Evil'
348
349Task<int, true> d_ShouldNotDiag(const int a, const int b) {
350 co_yield a / b;
351}
352
353Task<int, true> d_ShouldDiag(const int a, const int b) noexcept {
354 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions
355 co_yield a / b;
356}
357// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here
358// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here
359// CHECK-MESSAGES: :[[@LINE-6]]:17: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here
360
361Task<int, false, true> e_ShouldNotDiag(const int a, const int b) {
362 co_yield a / b;
363}
364
365Task<int, false, true> e_ShouldDiag(const int a, const int b) noexcept {
366 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions
367 co_yield a / b;
368}
369// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here
370// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here
371
372Task<int, false, false, true> f_ShouldNotDiag(const int a, const int b) {
373 co_yield a / b;
374}
375
376Task<int, false, false, true> f_ShouldDiag(const int a, const int b) noexcept {
377 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions
378 co_yield a / b;
379}
380// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here
381// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here
382
383Task<int, false, false, false, true> g_ShouldNotDiag(const int a, const int b) {
384 co_yield a / b;
385}
386
387Task<int, false, false, false, true> g_ShouldDiag(const int a,
388 const int b) noexcept {
389 // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions
390 co_yield a / b;
391}
392// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here
393// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here
394
395Task<int, false, false, false, false, true> h_ShouldNotDiag(const int a,
396 const int b) {
397 co_yield a / b;
398}
399
400Task<int, false, false, false, false, true> h_ShouldDiag(const int a,
401 const int b) noexcept {
402 // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions
403 co_yield a / b;
404}
405// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here
406// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here
407
408Task<int, false, false, false, false, false, true>
409i_ShouldNotDiag(const int a, const int b) {
410 co_yield a / b;
411}
412
413Task<int, false, false, false, false, false, true>
414i_ShouldNotDiagNoexcept(const int a, const int b) noexcept {
415 co_yield a / b;
416}
417
418Task<int, false, false, false, false, false, true>
419j_ShouldNotDiag(const int a, const int b) {
420 if (b == 0)
421 throw b;
422
423 co_yield a / b;
424}
425
426Task<int, false, false, false, false, false, true>
427j_ShouldDiag(const int a, const int b) noexcept {
428 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions
429 if (b == 0)
430 throw b;
431
432 co_yield a / b;
433}
434// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'j_ShouldDiag' here
435
436} // namespace coyield
437
438namespace coawait {
439
440Task<void> a_ShouldNotDiag(const int a, const int b) {
441 if (b == 0)
442 throw b;
443
444 co_await returnOne();
445}
446
447Task<void> b_ShouldNotDiag(const int a, const int b) noexcept {
448 if (b == 0)
449 throw b;
450
451 co_await returnOne();
452}
453
454Task<void> c_ShouldNotDiag(const int a, const int b) {
455 if (b == 0)
456 throw Evil{};
457
458 co_await returnOne();
459}
460
461Task<void> c_ShouldDiag(const int a, const int b) noexcept {
462 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: an exception may be thrown in function 'c_ShouldDiag' which should not throw exceptions
463 if (b == 0)
464 throw Evil{};
465
466 co_await returnOne();
467}
468// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here
469// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #1: function 'c_ShouldDiag' calls function '~Evil'
470
471Task<void, true> d_ShouldNotDiag(const int a, const int b) {
472 co_await returnOne();
473}
474
475Task<void, true> d_ShouldDiag(const int a, const int b) noexcept {
476 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions
477 co_await returnOne();
478}
479// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here
480// CHECK-MESSAGES: :158:12: note: frame #1: function 'get_return_object' calls function 'Task' here
481// CHECK-MESSAGES: :[[@LINE-6]]:18: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here
482
483Task<void, false, true> e_ShouldNotDiag(const int a, const int b) {
484 co_await returnOne();
485}
486
487Task<void, false, true> e_ShouldDiag(const int a, const int b) noexcept {
488 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions
489 co_await returnOne();
490}
491// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here
492// CHECK-MESSAGES: :[[@LINE-5]]:25: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here
493
494Task<void, false, false, true> f_ShouldNotDiag(const int a, const int b) {
495 co_await returnOne();
496}
497
498Task<void, false, false, true> f_ShouldDiag(const int a, const int b) noexcept {
499 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions
500 co_await returnOne();
501}
502// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here
503// CHECK-MESSAGES: :[[@LINE-5]]:32: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here
504
505Task<void, false, false, false, true> g_ShouldNotDiag(const int a,
506 const int b) {
507 co_await returnOne();
508}
509
510Task<void, false, false, false, true> g_ShouldDiag(const int a,
511 const int b) noexcept {
512 // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions
513 co_await returnOne();
514}
515// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here
516// CHECK-MESSAGES: :[[@LINE-6]]:39: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here
517
518Task<void, false, false, false, false, true> h_ShouldNotDiag(const int a,
519 const int b) {
520 co_await returnOne();
521}
522
523Task<void, false, false, false, false, true>
524h_ShouldDiag(const int a, const int b) noexcept {
525 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions
526 co_await returnOne();
527}
528// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here
529// CHECK-MESSAGES: :[[@LINE-5]]:1: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here
530
531Task<int, false, false, false, false, false, true>
532i_ShouldNotDiag(const int a, const int b) {
533 co_await returnOne();
534}
535
536Task<int, false, false, false, false, false, true>
537i_ShouldNotDiagNoexcept(const int a, const int b) noexcept {
538 co_await returnOne();
539}
540
541Task<int, false, false, false, false, false, true>
542j_ShouldNotDiag(const int a, const int b) {
543 co_await returnOne();
544 if (b == 0)
545 throw b;
546}
547
548Task<int, false, false, false, false, false, true>
549j_ShouldDiag(const int a, const int b) noexcept {
550 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions
551 co_await returnOne();
552 if (b == 0)
553 throw b;
554}
555// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'j_ShouldDiag' here
556
557} // namespace coawait
558
559} // namespace function
560
561namespace lambda {
562
563namespace coreturn {
564
565const auto a_ShouldNotDiag = [](const int a, const int b) -> Task<int> {
566 if (b == 0)
567 throw b;
568
569 co_return a / b;
570};
571
572const auto b_ShouldNotDiag = [](const int a,
573 const int b) noexcept -> Task<int> {
574 if (b == 0)
575 throw b;
576
577 co_return a / b;
578};
579
580const auto c_ShouldNotDiag = [](const int a, const int b) -> Task<int> {
581 if (b == 0)
582 throw Evil{};
583
584 co_return a / b;
585};
586
587const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task<int> {
588 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
589 if (b == 0)
590 throw Evil{};
591
592 co_return a / b;
593};
594// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here
595// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil'
596
597const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<int, true> {
598 co_return a / b;
599};
600
601const auto d_ShouldDiag = [](const int a,
602 const int b) noexcept -> Task<int, true> {
603 // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
604 co_return a / b;
605};
606// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here
607// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here
608// CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here
609
610const auto e_ShouldNotDiag = [](const int a,
611 const int b) -> Task<int, false, true> {
612 co_return a / b;
613};
614
615const auto e_ShouldDiag = [](const int a,
616 const int b) noexcept -> Task<int, false, true> {
617 // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
618 co_return a / b;
619};
620// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here
621// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here
622
623const auto f_ShouldNotDiag = [](const int a,
624 const int b) -> Task<int, false, false, true> {
625 co_return a / b;
626};
627
628const auto f_ShouldDiag =
629 [](const int a, const int b) noexcept -> Task<int, false, false, true> {
630 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
631 co_return a / b;
632};
633// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here
634// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here
635
636const auto g_ShouldNotDiag =
637 [](const int a, const int b) -> Task<int, false, false, false, true> {
638 co_return a / b;
639};
640
641const auto g_ShouldDiag =
642 [](const int a,
643 const int b) noexcept -> Task<int, false, false, false, true> {
644 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
645 co_return a / b;
646};
647// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here
648// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here
649
650const auto h_ShouldNotDiag =
651 [](const int a,
652 const int b) -> Task<int, false, false, false, false, true> {
653 co_return a / b;
654};
655
656const auto h_ShouldDiag =
657 [](const int a,
658 const int b) noexcept -> Task<int, false, false, false, false, true> {
659 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
660 co_return a / b;
661};
662// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here
663// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here
664
665const auto i_ShouldNotDiag =
666 [](const int a,
667 const int b) -> Task<int, false, false, false, false, false, true> {
668 co_return a / b;
669};
670
671const auto i_ShouldNotDiagNoexcept =
672 [](const int a,
673 const int b) noexcept -> Task<int, false, false, false, false, false, true> {
674 co_return a / b;
675};
676
677const auto j_ShouldNotDiag =
678 [](const int a,
679 const int b) -> Task<int, false, false, false, false, false, true> {
680 if (b == 0)
681 throw b;
682
683 co_return a / b;
684};
685
686const auto j_ShouldDiag =
687 [](const int a,
688 const int b) noexcept -> Task<int, false, false, false, false, false, true> {
689 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
690 if (b == 0)
691 throw b;
692
693 co_return a / b;
694};
695// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here
696
697} // namespace coreturn
698
699namespace coyield {
700
701const auto a_ShouldNotDiag = [](const int a, const int b) -> Task<int> {
702 if (b == 0)
703 throw b;
704
705 co_yield a / b;
706};
707
708const auto b_ShouldNotDiag = [](const int a,
709 const int b) noexcept -> Task<int> {
710 if (b == 0)
711 throw b;
712
713 co_yield a / b;
714};
715
716const auto c_ShouldNotDiag = [](const int a, const int b) -> Task<int> {
717 if (b == 0)
718 throw Evil{};
719
720 co_yield a / b;
721};
722
723const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task<int> {
724 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
725 if (b == 0)
726 throw Evil{};
727
728 co_yield a / b;
729};
730// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here
731// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil'
732
733const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<int, true> {
734 co_yield a / b;
735};
736
737const auto d_ShouldDiag = [](const int a,
738 const int b) noexcept -> Task<int, true> {
739 // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
740 co_yield a / b;
741};
742// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here
743// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here
744// CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here
745
746const auto e_ShouldNotDiag = [](const int a,
747 const int b) -> Task<int, false, true> {
748 co_yield a / b;
749};
750
751const auto e_ShouldDiag = [](const int a,
752 const int b) noexcept -> Task<int, false, true> {
753 // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
754 co_yield a / b;
755};
756// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here
757// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here
758
759const auto f_ShouldNotDiag = [](const int a,
760 const int b) -> Task<int, false, false, true> {
761 co_yield a / b;
762};
763
764const auto f_ShouldDiag =
765 [](const int a, const int b) noexcept -> Task<int, false, false, true> {
766 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
767 co_yield a / b;
768};
769// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here
770// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here
771
772const auto g_ShouldNotDiag =
773 [](const int a, const int b) -> Task<int, false, false, false, true> {
774 co_yield a / b;
775};
776
777const auto g_ShouldDiag =
778 [](const int a,
779 const int b) noexcept -> Task<int, false, false, false, true> {
780 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
781 co_yield a / b;
782};
783// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here
784// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here
785
786const auto h_ShouldNotDiag =
787 [](const int a,
788 const int b) -> Task<int, false, false, false, false, true> {
789 co_yield a / b;
790};
791
792const auto h_ShouldDiag =
793 [](const int a,
794 const int b) noexcept -> Task<int, false, false, false, false, true> {
795 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
796 co_yield a / b;
797};
798// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here
799// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here
800
801const auto i_ShouldNotDiag =
802 [](const int a,
803 const int b) -> Task<int, false, false, false, false, false, true> {
804 co_yield a / b;
805};
806
807const auto i_ShouldNotDiagNoexcept =
808 [](const int a,
809 const int b) noexcept -> Task<int, false, false, false, false, false, true> {
810 co_yield a / b;
811};
812
813const auto j_ShouldNotDiag =
814 [](const int a,
815 const int b) -> Task<int, false, false, false, false, false, true> {
816 if (b == 0)
817 throw b;
818
819 co_yield a / b;
820};
821
822const auto j_ShouldDiag =
823 [](const int a,
824 const int b) noexcept -> Task<int, false, false, false, false, false, true> {
825 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
826 if (b == 0)
827 throw b;
828
829 co_yield a / b;
830};
831// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here
832
833} // namespace coyield
834
835namespace coawait {
836
837const auto a_ShouldNotDiag = [](const int a, const int b) -> Task<void> {
838 if (b == 0)
839 throw b;
840
841 co_await returnOne();
842};
843
844const auto b_ShouldNotDiag = [](const int a,
845 const int b) noexcept -> Task<void> {
846 if (b == 0)
847 throw b;
848
849 co_await returnOne();
850};
851
852const auto c_ShouldNotDiag = [](const int a, const int b) -> Task<void> {
853 if (b == 0)
854 throw Evil{};
855
856 co_await returnOne();
857};
858
859const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task<void> {
860 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
861 if (b == 0)
862 throw Evil{};
863
864 co_await returnOne();
865};
866// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here
867// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil'
868
869const auto d_ShouldNotDiag = [](const int a, const int b) -> Task<void, true> {
870 co_await returnOne();
871};
872
873const auto d_ShouldDiag = [](const int a,
874 const int b) noexcept -> Task<void, true> {
875 // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
876 co_await returnOne();
877};
878// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here
879// CHECK-MESSAGES: :158:12: note: frame #1: function 'get_return_object' calls function 'Task' here
880// CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here
881
882const auto e_ShouldNotDiag = [](const int a,
883 const int b) -> Task<void, false, true> {
884 co_await returnOne();
885};
886
887const auto e_ShouldDiag = [](const int a,
888 const int b) noexcept -> Task<void, false, true> {
889 // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
890 co_await returnOne();
891};
892// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here
893// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here
894
895const auto f_ShouldNotDiag = [](const int a,
896 const int b) -> Task<void, false, false, true> {
897 co_await returnOne();
898};
899
900const auto f_ShouldDiag =
901 [](const int a, const int b) noexcept -> Task<void, false, false, true> {
902 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
903 co_await returnOne();
904};
905// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here
906// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here
907
908const auto g_ShouldNotDiag =
909 [](const int a, const int b) -> Task<void, false, false, false, true> {
910 co_await returnOne();
911};
912
913const auto g_ShouldDiag =
914 [](const int a,
915 const int b) noexcept -> Task<void, false, false, false, true> {
916 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
917 co_await returnOne();
918};
919// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here
920// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here
921
922const auto h_ShouldNotDiag =
923 [](const int a,
924 const int b) -> Task<void, false, false, false, false, true> {
925 co_await returnOne();
926};
927
928const auto h_ShouldDiag =
929 [](const int a,
930 const int b) noexcept -> Task<void, false, false, false, false, true> {
931 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
932 co_await returnOne();
933};
934// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here
935// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here
936
937const auto i_ShouldNotDiag =
938 [](const int a,
939 const int b) -> Task<int, false, false, false, false, false, true> {
940 co_await returnOne();
941};
942
943const auto i_ShouldNotDiagNoexcept =
944 [](const int a,
945 const int b) noexcept -> Task<int, false, false, false, false, false, true> {
946 co_await returnOne();
947};
948
949const auto j_ShouldNotDiag =
950 [](const int a,
951 const int b) -> Task<int, false, false, false, false, false, true> {
952 co_await returnOne();
953 if (b == 0)
954 throw b;
955};
956
957const auto j_ShouldDiag =
958 [](const int a,
959 const int b) noexcept -> Task<int, false, false, false, false, false, true> {
960 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
961 co_await returnOne();
962 if (b == 0)
963 throw b;
964};
965// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here
966
967} // namespace coawait
968
969} // namespace lambda
970

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