[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / test / SemaCXX / warn-throw-out-noexcept-func.cpp
blob646cea446c2cd7ee2ff7f29c219ac342958127c5
1 // RUN: %clang_cc1 %s -fdelayed-template-parsing -fcxx-exceptions -fsyntax-only -Wexceptions -verify -fdeclspec -std=c++17
2 struct A_ShouldDiag {
3 ~A_ShouldDiag(); // implicitly noexcept(true)
4 };
5 A_ShouldDiag::~A_ShouldDiag() { // expected-note {{destructor has a implicit non-throwing exception specification}}
6 throw 1; // expected-warning {{has a non-throwing exception specification but can still throw}}
8 struct B_ShouldDiag {
9 int i;
10 ~B_ShouldDiag() noexcept(true) {} //no disg, no throw stmt
12 struct R_ShouldDiag : A_ShouldDiag {
13 B_ShouldDiag b;
14 ~R_ShouldDiag() { // expected-note {{destructor has a implicit non-throwing exception specification}}
15 throw 1; // expected-warning {{has a non-throwing exception specification but}}
17 __attribute__((nothrow)) R_ShouldDiag() {// expected-note {{function declared non-throwing here}}
18 throw 1;// expected-warning {{has a non-throwing exception specification but}}
20 void __attribute__((nothrow)) SomeThrow() {// expected-note {{function declared non-throwing here}}
21 throw 1; // expected-warning {{has a non-throwing exception specification but}}
23 void __declspec(nothrow) SomeDeclspecThrow() {// expected-note {{function declared non-throwing here}}
24 throw 1; // expected-warning {{has a non-throwing exception specification but}}
28 struct M_ShouldNotDiag {
29 B_ShouldDiag b;
30 ~M_ShouldNotDiag() noexcept(false);
33 M_ShouldNotDiag::~M_ShouldNotDiag() noexcept(false) {
34 throw 1;
37 struct N_ShouldDiag {
38 B_ShouldDiag b;
39 ~N_ShouldDiag(); //implicitly noexcept(true)
42 N_ShouldDiag::~N_ShouldDiag() { // expected-note {{destructor has a implicit non-throwing exception specification}}
43 throw 1; // expected-warning {{has a non-throwing exception specification but}}
45 struct X_ShouldDiag {
46 B_ShouldDiag b;
47 ~X_ShouldDiag() noexcept { // expected-note {{destructor has a non-throwing exception}}
48 throw 1; // expected-warning {{has a non-throwing exception specification but}}
51 struct Y_ShouldDiag : A_ShouldDiag {
52 ~Y_ShouldDiag() noexcept(true) { // expected-note {{destructor has a non-throwing exception specification}}
53 throw 1; // expected-warning {{has a non-throwing exception specification but}}
56 struct C_ShouldNotDiag {
57 int i;
58 ~C_ShouldNotDiag() noexcept(false) {}
60 struct D_ShouldNotDiag {
61 C_ShouldNotDiag c;
62 ~D_ShouldNotDiag() { //implicitly noexcept(false)
63 throw 1;
66 struct E_ShouldNotDiag {
67 C_ShouldNotDiag c;
68 ~E_ShouldNotDiag(); //implicitly noexcept(false)
70 E_ShouldNotDiag::~E_ShouldNotDiag() //implicitly noexcept(false)
72 throw 1;
75 template <typename T>
76 class A1_ShouldDiag {
77 T b;
79 public:
80 ~A1_ShouldDiag() { // expected-note {{destructor has a implicit non-throwing exception specification}}
81 throw 1; // expected-warning {{has a non-throwing exception specification but}}
84 template <typename T>
85 struct B1_ShouldDiag {
86 T i;
87 ~B1_ShouldDiag() noexcept(true) {}
89 template <typename T>
90 struct R1_ShouldDiag : A1_ShouldDiag<T> //expected-note {{in instantiation of member function}}
92 B1_ShouldDiag<T> b;
93 ~R1_ShouldDiag() { // expected-note {{destructor has a implicit non-throwing exception specification}}
94 throw 1; // expected-warning {{has a non-throwing exception specification but}}
97 template <typename T>
98 struct S1_ShouldDiag : A1_ShouldDiag<T> {
99 B1_ShouldDiag<T> b;
100 ~S1_ShouldDiag() noexcept { // expected-note {{destructor has a non-throwing exception specification}}
101 throw 1; // expected-warning {{has a non-throwing exception specification but}}
104 void operator delete(void *ptr) noexcept { // expected-note {{deallocator has a non-throwing exception specification}}
105 throw 1; // expected-warning {{has a non-throwing exception specification but}}
107 struct except_fun {
108 static const bool i = false;
110 struct noexcept_fun {
111 static const bool i = true;
113 template <typename T>
114 struct dependent_warn {
115 ~dependent_warn() noexcept(T::i) {
116 throw 1;
119 template <typename T>
120 struct dependent_warn_noexcept {
121 ~dependent_warn_noexcept() noexcept(T::i) { // expected-note {{destructor has a non-throwing exception specification}}
122 throw 1; // expected-warning {{has a non-throwing exception specification but}}
125 template <typename T>
126 struct dependent_warn_both {
127 ~dependent_warn_both() noexcept(T::i) { // expected-note {{destructor has a non-throwing exception specification}}
128 throw 1; // expected-warning {{has a non-throwing exception specification but}}
131 void foo() noexcept { //expected-note {{function declared non-throwing here}}
132 throw 1; // expected-warning {{has a non-throwing exception specification but}}
134 struct Throws {
135 ~Throws() noexcept(false);
138 struct ShouldDiagnose {
139 Throws T;
140 ~ShouldDiagnose() noexcept { //expected-note {{destructor has a non-throwing exception specification}}
141 throw; // expected-warning {{has a non-throwing exception specification but}}
144 struct ShouldNotDiagnose {
145 Throws T;
146 ~ShouldNotDiagnose() {
147 throw;
151 void bar_ShouldNotDiag() noexcept {
152 try {
153 throw 1;
154 } catch (...) {
157 void f_ShouldNotDiag() noexcept {
158 try {
159 throw 12;
160 } catch (int) {
163 void g_ShouldNotDiag() noexcept {
164 try {
165 throw 12;
166 } catch (...) {
170 void h_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
171 try {
172 throw 12; // expected-warning {{has a non-throwing exception specification but}}
173 } catch (const char *) {
177 void i_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
178 try {
179 throw 12;
180 } catch (int) {
181 throw; // expected-warning {{has a non-throwing exception specification but}}
184 void j_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
185 try {
186 throw 12;
187 } catch (int) {
188 throw "haha"; // expected-warning {{has a non-throwing exception specification but}}
192 void k_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
193 try {
194 throw 12;
195 } catch (...) {
196 throw; // expected-warning {{has a non-throwing exception specification but}}
200 void loo_ShouldDiag(int i) noexcept { //expected-note {{function declared non-throwing here}}
201 if (i)
202 try {
203 throw 12;
204 } catch (int) {
205 throw "haha"; //expected-warning {{has a non-throwing exception specification but}}
207 i = 10;
210 void loo1_ShouldNotDiag() noexcept {
211 if (0)
212 throw 12;
215 void loo2_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
216 if (1)
217 throw 12; // expected-warning {{has a non-throwing exception specification but}}
219 struct S {};
221 void l_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
222 try {
223 throw S{}; //expected-warning {{has a non-throwing exception specification but}}
224 } catch (S *s) {
228 void m_ShouldNotDiag() noexcept {
229 try {
230 const S &s = S{};
231 throw s;
232 } catch (S s) {
235 void n_ShouldNotDiag() noexcept {
236 try {
237 S s = S{};
238 throw s;
239 } catch (const S &s) {
242 // As seen in p34973, this should not throw the warning. If there is an active
243 // exception, catch(...) catches everything.
244 void o_ShouldNotDiag() noexcept {
245 try {
246 throw;
247 } catch (...) {
251 void p_ShouldNotDiag() noexcept {
252 // Don't warn here: it's possible that the user arranges to only call this
253 // when the active exception is of type 'int'.
254 try {
255 throw;
256 } catch (int){
260 void q_ShouldNotDiag() noexcept {
261 try {
262 throw;
263 } catch (int){
264 } catch (...){
268 #define NOEXCEPT noexcept
269 void with_macro() NOEXCEPT { //expected-note {{function declared non-throwing here}}
270 throw 1; // expected-warning {{has a non-throwing exception specification but}}
273 void with_try_block() try {
274 throw 2;
275 } catch (...) {
278 void with_try_block1() noexcept try { //expected-note {{function declared non-throwing here}}
279 throw 2; // expected-warning {{has a non-throwing exception specification but}}
280 } catch (char *) {
283 namespace derived {
284 struct B {};
285 struct D: B {};
286 void goodPlain() noexcept {
287 try {
288 throw D();
289 } catch (B) {}
291 void goodReference() noexcept {
292 try {
293 throw D();
294 } catch (B &) {}
296 void goodPointer() noexcept {
297 D d;
298 try {
299 throw &d;
300 } catch (B *) {}
302 void badPlain() noexcept { //expected-note {{function declared non-throwing here}}
303 try {
304 throw B(); // expected-warning {{'badPlain' has a non-throwing exception specification but can still throw}}
305 } catch (D) {}
307 void badReference() noexcept { //expected-note {{function declared non-throwing here}}
308 try {
309 throw B(); // expected-warning {{'badReference' has a non-throwing exception specification but can still throw}}
310 } catch (D &) {}
312 void badPointer() noexcept { //expected-note {{function declared non-throwing here}}
313 B b;
314 try {
315 throw &b; // expected-warning {{'badPointer' has a non-throwing exception specification but can still throw}}
316 } catch (D *) {}
320 int main() {
321 R1_ShouldDiag<int> o; //expected-note {{in instantiation of member function}}
322 S1_ShouldDiag<int> b; //expected-note {{in instantiation of member function}}
323 dependent_warn<except_fun> f;
324 dependent_warn_noexcept<noexcept_fun> f1; //expected-note {{in instantiation of member function}}
325 dependent_warn_both<except_fun> f2;
326 dependent_warn_both<noexcept_fun> f3; //expected-note {{in instantiation of member function}}
327 ShouldDiagnose obj;
328 ShouldNotDiagnose obj1;
331 namespace ExceptionInNamespace {
332 namespace N {
333 struct E {};
335 void run() throw() {
336 try {
337 throw N::E();
338 } catch (const N::E &e) {
343 namespace HandlerSpecialCases {
344 struct A {};
345 using CA = const A;
347 struct B : A {};
348 using CB = const B;
350 struct AmbigBase {};
351 struct AmbigMiddle : AmbigBase {};
352 struct AmbigDerived : AmbigBase, AmbigMiddle {}; // expected-warning {{inaccessible}}
354 struct PrivateBase {};
355 struct PrivateDerived : private PrivateBase { friend void bad3() throw(); };
357 void good() throw() {
358 try { throw CA(); } catch (volatile A&) {}
359 try { throw B(); } catch (A&) {}
360 try { throw B(); } catch (const volatile A&) {}
361 try { throw CB(); } catch (A&) {}
362 try { throw (int*)0; } catch (void* const volatile) {}
363 try { throw (int*)0; } catch (void* const &) {}
364 try { throw (B*)0; } catch (A*) {}
365 try { throw (B*)0; } catch (A* const &) {}
366 try { throw (void(*)() noexcept)0; } catch (void (*)()) {}
367 try { throw (void(*)() noexcept)0; } catch (void (*const &)()) {}
368 try { throw (int**)0; } catch (const int * const*) {}
369 try { throw (int**)0; } catch (const int * const* const&) {}
370 try { throw nullptr; } catch (int*) {}
371 try { throw nullptr; } catch (int* const&) {}
374 void bad1() throw() { // expected-note {{here}}
375 try { throw A(); } catch (const B&) {} // expected-warning {{still throw}}
377 void bad2() throw() { // expected-note {{here}}
378 try { throw AmbigDerived(); } catch (const AmbigBase&) {} // expected-warning {{still throw}}
380 void bad3() throw() { // expected-note {{here}}
381 try { throw PrivateDerived(); } catch (const PrivateBase&) {} // expected-warning {{still throw}}
383 void bad4() throw() { // expected-note {{here}}
384 try { throw (int*)0; } catch (void* &) {} // expected-warning {{still throw}}
386 void bad5() throw() { // expected-note {{here}}
387 try { throw (int*)0; } catch (void* const volatile &) {} // expected-warning {{still throw}}
389 void bad6() throw() { // expected-note {{here}}
390 try { throw (int* volatile)0; } catch (void* const volatile &) {} // expected-warning {{still throw}}
392 void bad7() throw() { // expected-note {{here}}
393 try { throw (AmbigDerived*)0; } catch (AmbigBase*) {} // expected-warning {{still throw}}
395 void bad8() throw() { // expected-note {{here}}
396 try { throw (PrivateDerived*)0; } catch (PrivateBase*) {} // expected-warning {{still throw}}
398 void bad9() throw() { // expected-note {{here}}
399 try { throw (B*)0; } catch (A* &) {} // expected-warning {{still throw}}
401 void bad10() throw() { // expected-note {{here}}
402 try { throw (void(*)())0; } catch (void (*)() noexcept) {} // expected-warning {{still throw}}
404 void bad11() throw() { // expected-note {{here}}
405 try { throw (int**)0; } catch (const int **) {} // expected-warning {{still throw}}
407 void bad12() throw() { // expected-note {{here}}
408 try { throw nullptr; } catch (int) {} // expected-warning {{still throw}}
412 namespace NestedTry {
413 void f() noexcept {
414 try {
415 try {
416 throw 0;
417 } catch (float) {}
418 } catch (int) {}
421 struct A { [[noreturn]] ~A(); };
423 void g() noexcept { // expected-note {{here}}
424 try {
425 try {
426 throw 0; // expected-warning {{still throw}}
427 } catch (float) {}
428 } catch (const char*) {}
431 void h() noexcept { // expected-note {{here}}
432 try {
433 try {
434 throw 0;
435 } catch (float) {}
436 } catch (int) {
437 throw; // expected-warning {{still throw}}
441 // FIXME: Ideally, this should still warn; we can track which types are
442 // potentially thrown by the rethrow.
443 void i() noexcept {
444 try {
445 try {
446 throw 0;
447 } catch (int) {
448 throw;
450 } catch (float) {}
453 // FIXME: Ideally, this should not warn: the second catch block is
454 // unreachable.
455 void j() noexcept { // expected-note {{here}}
456 try {
457 try {
458 throw 0;
459 } catch (int) {}
460 } catch (float) {
461 throw; // expected-warning {{still throw}}