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