1 // RUN: %clang_cc1 -std=c++14 -verify -fexceptions -fcxx-exceptions %s 2 // RUN: %clang_cc1 -std=c++17 -verify -fexceptions -fcxx-exceptions %s -Wno-dynamic-exception-spec 3 // RUN: %clang_cc1 -std=c++14 -verify -fexceptions -fcxx-exceptions -Wno-c++1z-compat-mangling -DNO_COMPAT_MANGLING %s 4 // RUN: %clang_cc1 -std=c++14 -verify -fexceptions -fcxx-exceptions -Wno-noexcept-type -DNO_COMPAT_MANGLING %s 5 6 #if __cplusplus > 201402L 7 8 template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-note {{previous}} 9 template<typename T> void redecl1() noexcept(noexcept(T())); // ok, same type 10 template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}} 11 12 template<bool A, bool B> void redecl2() noexcept(A); // expected-note {{previous}} 13 template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{does not match previous}} 14 15 // These have the same canonical type, but are still different. 16 template<typename A, typename B> void redecl3() throw(A); // expected-note {{previous}} 17 template<typename A, typename B> void redecl3() throw(B); // expected-error {{does not match previous}} 18 19 typedef int I; 20 template<bool B> void redecl4(I) noexcept(B); 21 template<bool B> void redecl4(I) noexcept(B); // expected-note {{could not match 'void (I) noexcept(false)' (aka 'void (int) noexcept(false)') against 'void (int) noexcept'}} 22 23 void (*init_with_exact_type_a)(int) noexcept = redecl4<true>; 24 void (*init_with_mismatched_type_a)(int) = redecl4<true>; 25 auto deduce_auto_from_noexcept_function_ptr_a = redecl4<true>; 26 using DeducedType_a = decltype(deduce_auto_from_noexcept_function_ptr_a); 27 using DeducedType_a = void (*)(int) noexcept; 28 29 void (*init_with_exact_type_b)(int) = redecl4<false>; 30 void (*init_with_mismatched_type_b)(int) noexcept = redecl4<false>; // expected-error {{does not match required type}} 31 auto deduce_auto_from_noexcept_function_ptr_b = redecl4<false>; 32 using DeducedType_b = decltype(deduce_auto_from_noexcept_function_ptr_b); 33 using DeducedType_b = void (*)(int); 34 35 static_assert(noexcept(init_with_exact_type_a(0))); 36 static_assert(noexcept((+init_with_exact_type_a)(0))); 37 static_assert(!noexcept(init_with_exact_type_b(0))); 38 static_assert(!noexcept((+init_with_exact_type_b)(0))); 39 40 // Don't look through casts, use the direct type of the expression. 41 // FIXME: static_cast here would be reasonable, but is not currently permitted. 42 static_assert(noexcept(static_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0))); // expected-error {{is not allowed}} 43 static_assert(noexcept(reinterpret_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0))); 44 static_assert(!noexcept(static_cast<decltype(init_with_exact_type_b)>(init_with_exact_type_a)(0))); 45 46 template<bool B> auto get_fn() noexcept -> void (*)() noexcept(B) {} 47 static_assert(noexcept(get_fn<true>()())); 48 static_assert(!noexcept(get_fn<false>()())); 49 50 namespace DependentDefaultCtorExceptionSpec { 51 template<typename> struct T { static const bool value = true; }; 52 53 template<class A> struct map { 54 typedef A a; 55 map() noexcept(T<a>::value) {} 56 }; 57 58 template<class B> struct multimap { 59 typedef B b; 60 multimap() noexcept(T<b>::value) {} 61 }; 62 63 // Don't crash here. 64 struct A { multimap<int> Map; } a; 65 66 static_assert(noexcept(A())); 67 } 68 69 #endif 70 71 namespace CompatWarning { 72 struct X; 73 74 // These cases don't change. 75 void f0(void p() throw(int)); 76 auto f0() -> void (*)() noexcept(false); 77 78 // These cases take an ABI break in C++17 because their parameter / return types change. 79 void f1(void p() noexcept); 80 void f2(void (*p)() noexcept(true)); 81 void f3(void (&p)() throw()); 82 void f4(void (X::*p)() throw()); 83 auto f5() -> void (*)() throw(); 84 auto f6() -> void (&)() throw(); 85 auto f7() -> void (X::*)() throw(); 86 #if __cplusplus <= 201402L && !defined(NO_COMPAT_MANGLING) 87 // expected-warning@-8 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}} 88 // expected-warning@-8 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}} 89 // expected-warning@-8 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}} 90 // expected-warning@-8 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}} 91 // expected-warning@-8 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}} 92 // expected-warning@-8 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}} 93 // expected-warning@-8 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}} 94 #endif 95 96 // An instantiation-dependent exception specification needs to be mangled in 97 // all language modes, since it participates in SFINAE. 98 template<typename T> void g(void() throw(T)); // expected-note {{substitution failure}} 99 template<typename T> void g(...) = delete; // expected-note {{deleted}} 100 void test_g() { g<void>(nullptr); } // expected-error {{deleted}} 101 102 // An instantiation-dependent exception specification needs to be mangled in 103 // all language modes, since it participates in SFINAE. 104 template<typename T> void h(void() noexcept(T())); // expected-note {{substitution failure}} 105 template<typename T> void h(...) = delete; // expected-note {{deleted}} 106 void test_h() { h<void>(nullptr); } // expected-error {{deleted}} 107 } 108 109 namespace ImplicitExceptionSpec { 110 struct S { 111 ~S(); 112 void f(const S &s = S()); 113 }; 114 S::~S() {} 115 } 116 117 namespace Builtins { 118 // Pick two functions that ought to have the same noexceptness. 119 extern "C" int strcmp(const char *, const char *); 120 extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept; 121 122 // Check we recognized both as builtins. 123 typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)]; // expected-warning {{variable length array}} 124 typedef int arr[3]; 125 } 126 127 namespace ExplicitInstantiation { 128 template<typename T> void f() noexcept {} 129 template<typename T> struct X { void f() noexcept {} }; 130 template void f<int>(); 131 template void X<int>::f(); 132 } 133 134 namespace ConversionFunction { 135 struct A { template<typename T> operator T() noexcept; }; 136 int a = A().operator int(); 137 } 138 139 using size_t = decltype(sizeof(0)); 140 141 namespace OperatorDelete { 142 struct W {}; 143 struct X {}; 144 struct Y {}; 145 struct Z {}; 146 template<bool N, bool D> struct T {}; 147 } 148 void *operator new(size_t, OperatorDelete::W) noexcept(false); 149 void operator delete(void*, OperatorDelete::W) noexcept(false) = delete; // expected-note {{here}} 150 void *operator new(size_t, OperatorDelete::X) noexcept(false); 151 void operator delete(void*, OperatorDelete::X) noexcept(true) = delete; // expected-note {{here}} 152 void *operator new(size_t, OperatorDelete::Y) noexcept(true); 153 void operator delete(void*, OperatorDelete::Y) noexcept(false) = delete; // expected-note {{here}} 154 void *operator new(size_t, OperatorDelete::Z) noexcept(true); 155 void operator delete(void*, OperatorDelete::Z) noexcept(true) = delete; // expected-note {{here}} 156 template<bool N, bool D> void *operator new(size_t, OperatorDelete::T<N, D>) noexcept(N); 157 template<bool N, bool D> void operator delete(void*, OperatorDelete::T<N, D>) noexcept(D) = delete; // expected-note 4{{here}} 158 namespace OperatorDelete { 159 struct A { A(); }; 160 A *w = new (W{}) A; // expected-error {{deleted function}} 161 A *x = new (X{}) A; // expected-error {{deleted function}} 162 A *y = new (Y{}) A; // expected-error {{deleted function}} 163 A *z = new (Z{}) A; // expected-error {{deleted function}} 164 165 A *t00 = new (T<false, false>{}) A; // expected-error {{deleted function}} 166 A *t01 = new (T<false, true>{}) A; // expected-error {{deleted function}} 167 A *t10 = new (T<true, false>{}) A; // expected-error {{deleted function}} 168 A *t11 = new (T<true, true>{}) A; // expected-error {{deleted function}} 169 } 170