summaryrefslogtreecommitdiff
path: root/test/SemaCXX/warn-throw-out-noexcept-func.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX/warn-throw-out-noexcept-func.cpp')
-rw-r--r--test/SemaCXX/warn-throw-out-noexcept-func.cpp143
1 files changed, 140 insertions, 3 deletions
diff --git a/test/SemaCXX/warn-throw-out-noexcept-func.cpp b/test/SemaCXX/warn-throw-out-noexcept-func.cpp
index a6c23ddc6c8f..646cea446c2c 100644
--- a/test/SemaCXX/warn-throw-out-noexcept-func.cpp
+++ b/test/SemaCXX/warn-throw-out-noexcept-func.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fdelayed-template-parsing -fcxx-exceptions -fsyntax-only -Wexceptions -verify -fdeclspec -std=c++11
+// RUN: %clang_cc1 %s -fdelayed-template-parsing -fcxx-exceptions -fsyntax-only -Wexceptions -verify -fdeclspec -std=c++17
struct A_ShouldDiag {
~A_ShouldDiag(); // implicitly noexcept(true)
};
@@ -248,9 +248,11 @@ void o_ShouldNotDiag() noexcept {
}
}
-void p_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
+void p_ShouldNotDiag() noexcept {
+ // Don't warn here: it's possible that the user arranges to only call this
+ // when the active exception is of type 'int'.
try {
- throw; //expected-warning {{has a non-throwing exception specification but}}
+ throw;
} catch (int){
}
}
@@ -325,3 +327,138 @@ int main() {
ShouldDiagnose obj;
ShouldNotDiagnose obj1;
}
+
+namespace ExceptionInNamespace {
+ namespace N {
+ struct E {};
+ }
+ void run() throw() {
+ try {
+ throw N::E();
+ } catch (const N::E &e) {
+ }
+ }
+}
+
+namespace HandlerSpecialCases {
+ struct A {};
+ using CA = const A;
+
+ struct B : A {};
+ using CB = const B;
+
+ struct AmbigBase {};
+ struct AmbigMiddle : AmbigBase {};
+ struct AmbigDerived : AmbigBase, AmbigMiddle {}; // expected-warning {{inaccessible}}
+
+ struct PrivateBase {};
+ struct PrivateDerived : private PrivateBase { friend void bad3() throw(); };
+
+ void good() throw() {
+ try { throw CA(); } catch (volatile A&) {}
+ try { throw B(); } catch (A&) {}
+ try { throw B(); } catch (const volatile A&) {}
+ try { throw CB(); } catch (A&) {}
+ try { throw (int*)0; } catch (void* const volatile) {}
+ try { throw (int*)0; } catch (void* const &) {}
+ try { throw (B*)0; } catch (A*) {}
+ try { throw (B*)0; } catch (A* const &) {}
+ try { throw (void(*)() noexcept)0; } catch (void (*)()) {}
+ try { throw (void(*)() noexcept)0; } catch (void (*const &)()) {}
+ try { throw (int**)0; } catch (const int * const*) {}
+ try { throw (int**)0; } catch (const int * const* const&) {}
+ try { throw nullptr; } catch (int*) {}
+ try { throw nullptr; } catch (int* const&) {}
+ }
+
+ void bad1() throw() { // expected-note {{here}}
+ try { throw A(); } catch (const B&) {} // expected-warning {{still throw}}
+ }
+ void bad2() throw() { // expected-note {{here}}
+ try { throw AmbigDerived(); } catch (const AmbigBase&) {} // expected-warning {{still throw}}
+ }
+ void bad3() throw() { // expected-note {{here}}
+ try { throw PrivateDerived(); } catch (const PrivateBase&) {} // expected-warning {{still throw}}
+ }
+ void bad4() throw() { // expected-note {{here}}
+ try { throw (int*)0; } catch (void* &) {} // expected-warning {{still throw}}
+ }
+ void bad5() throw() { // expected-note {{here}}
+ try { throw (int*)0; } catch (void* const volatile &) {} // expected-warning {{still throw}}
+ }
+ void bad6() throw() { // expected-note {{here}}
+ try { throw (int* volatile)0; } catch (void* const volatile &) {} // expected-warning {{still throw}}
+ }
+ void bad7() throw() { // expected-note {{here}}
+ try { throw (AmbigDerived*)0; } catch (AmbigBase*) {} // expected-warning {{still throw}}
+ }
+ void bad8() throw() { // expected-note {{here}}
+ try { throw (PrivateDerived*)0; } catch (PrivateBase*) {} // expected-warning {{still throw}}
+ }
+ void bad9() throw() { // expected-note {{here}}
+ try { throw (B*)0; } catch (A* &) {} // expected-warning {{still throw}}
+ }
+ void bad10() throw() { // expected-note {{here}}
+ try { throw (void(*)())0; } catch (void (*)() noexcept) {} // expected-warning {{still throw}}
+ }
+ void bad11() throw() { // expected-note {{here}}
+ try { throw (int**)0; } catch (const int **) {} // expected-warning {{still throw}}
+ }
+ void bad12() throw() { // expected-note {{here}}
+ try { throw nullptr; } catch (int) {} // expected-warning {{still throw}}
+ }
+}
+
+namespace NestedTry {
+ void f() noexcept {
+ try {
+ try {
+ throw 0;
+ } catch (float) {}
+ } catch (int) {}
+ }
+
+ struct A { [[noreturn]] ~A(); };
+
+ void g() noexcept { // expected-note {{here}}
+ try {
+ try {
+ throw 0; // expected-warning {{still throw}}
+ } catch (float) {}
+ } catch (const char*) {}
+ }
+
+ void h() noexcept { // expected-note {{here}}
+ try {
+ try {
+ throw 0;
+ } catch (float) {}
+ } catch (int) {
+ throw; // expected-warning {{still throw}}
+ }
+ }
+
+ // FIXME: Ideally, this should still warn; we can track which types are
+ // potentially thrown by the rethrow.
+ void i() noexcept {
+ try {
+ try {
+ throw 0;
+ } catch (int) {
+ throw;
+ }
+ } catch (float) {}
+ }
+
+ // FIXME: Ideally, this should not warn: the second catch block is
+ // unreachable.
+ void j() noexcept { // expected-note {{here}}
+ try {
+ try {
+ throw 0;
+ } catch (int) {}
+ } catch (float) {
+ throw; // expected-warning {{still throw}}
+ }
+ }
+}