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
6 #if __cplusplus > 201402L
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}}
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}}
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}}
20 template<bool B
> void redecl4(I
) noexcept(B
);
21 template<bool B
> void redecl4(I
) noexcept(B
);
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
;
29 void (*init_with_exact_type_b
)(int) = redecl4
<false>;
30 void (*init_with_mismatched_type_b
)(int) noexcept
= redecl4
<false>; // expected-error {{cannot initialize a variable of 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);
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)));
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)));
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>()()));
50 namespace DependentDefaultCtorExceptionSpec
{
51 template<typename
> struct T
{ static const bool value
= true; };
53 template<class A
> struct map
{
55 map() noexcept(T
<a
>::value
) {}
58 template<class B
> struct multimap
{
60 multimap() noexcept(T
<b
>::value
) {}
64 struct A
{ multimap
<int> Map
; } a
;
66 static_assert(noexcept(A()));
68 template <class> struct NoexceptWithThis
{
70 template <class T
> auto foo(T
) noexcept(ca
) { return true; }
71 // expected-error@-1 {{noexcept specifier argument is not a constant expression}}
72 // expected-note@-2 {{in instantiation of exception specification}}
73 // expected-note@-3 {{implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}}
75 struct InstantiateFromAnotherClass
{
76 template <class B
, class T
= decltype(static_cast<bool (B::*)(int)>(&B::foo
))> // expected-note {{in instantiation of function template specialization}}
77 InstantiateFromAnotherClass(B
*) {} // expected-note {{in instantiation of default argument}}
79 NoexceptWithThis
<int> f
{};
81 InstantiateFromAnotherClass b
{&f
}; // expected-note {{while substituting deduced template arguments into function template}}
86 namespace CompatWarning
{
89 // These cases don't change.
90 void f0(void p() throw(int));
91 auto f0() -> void (*)() noexcept(false);
93 // These cases take an ABI break in C++17 because their parameter / return types change.
94 void f1(void p() noexcept
);
95 void f2(void (*p
)() noexcept(true));
96 void f3(void (&p
)() throw());
97 void f4(void (X::*p
)() throw());
98 auto f5() -> void (*)() throw();
99 auto f6() -> void (&)() throw();
100 auto f7() -> void (X::*)() throw();
101 #if __cplusplus <= 201402L && !defined(NO_COMPAT_MANGLING)
102 // expected-warning@-8 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}}
103 // expected-warning@-8 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}}
104 // expected-warning@-8 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}}
105 // expected-warning@-8 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}}
106 // expected-warning@-8 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}}
107 // expected-warning@-8 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}}
108 // expected-warning@-8 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}}
111 // An instantiation-dependent exception specification needs to be mangled in
112 // all language modes, since it participates in SFINAE.
113 template<typename T
> void g(void() throw(T
)); // expected-note {{substitution failure}}
114 template<typename T
> void g(...) = delete; // expected-note {{deleted}}
115 void test_g() { g
<void>(nullptr); } // expected-error {{deleted}}
117 // An instantiation-dependent exception specification needs to be mangled in
118 // all language modes, since it participates in SFINAE.
119 template<typename T
> void h(void() noexcept(T())); // expected-note {{substitution failure}}
120 template<typename T
> void h(...) = delete; // expected-note {{deleted}}
121 void test_h() { h
<void>(nullptr); } // expected-error {{deleted}}
124 namespace ImplicitExceptionSpec
{
127 void f(const S
&s
= S());
133 // Pick two functions that ought to have the same noexceptness.
134 extern "C" int strcmp(const char *, const char *);
135 extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept
;
137 // Check we recognized both as builtins.
138 typedef int arr
[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)]; // expected-warning {{variable length array folded to constant array as an extension}} \
139 expected
-warning
{{variable length arrays in C
++ are a Clang extension
}} \
140 expected
-note
{{non
-constexpr function
'strcmp' cannot be used in a constant expression
}}
144 namespace ExplicitInstantiation
{
145 template<typename T
> void f() noexcept
{}
146 template<typename T
> struct X
{ void f() noexcept
{} };
147 template void f
<int>();
148 template void X
<int>::f();
151 namespace ConversionFunction
{
152 struct A
{ template<typename T
> operator T() noexcept
; };
153 int a
= A().operator int();
156 using size_t = decltype(sizeof(0));
158 namespace OperatorDelete
{
163 template<bool N
, bool D
> struct T
{};
165 void *operator new(size_t, OperatorDelete::W
) noexcept(false);
166 void operator delete(void*, OperatorDelete::W
) noexcept(false) = delete; // expected-note {{here}}
167 void *operator new(size_t, OperatorDelete::X
) noexcept(false);
168 void operator delete(void*, OperatorDelete::X
) noexcept(true) = delete; // expected-note {{here}}
169 void *operator new(size_t, OperatorDelete::Y
) noexcept(true);
170 void operator delete(void*, OperatorDelete::Y
) noexcept(false) = delete; // expected-note {{here}}
171 void *operator new(size_t, OperatorDelete::Z
) noexcept(true);
172 void operator delete(void*, OperatorDelete::Z
) noexcept(true) = delete; // expected-note {{here}}
173 template<bool N
, bool D
> void *operator new(size_t, OperatorDelete::T
<N
, D
>) noexcept(N
);
174 template<bool N
, bool D
> void operator delete(void*, OperatorDelete::T
<N
, D
>) noexcept(D
) = delete; // expected-note 4{{here}}
175 namespace OperatorDelete
{
177 A
*w
= new (W
{}) A
; // expected-error {{deleted function}}
178 A
*x
= new (X
{}) A
; // expected-error {{deleted function}}
179 A
*y
= new (Y
{}) A
; // expected-error {{deleted function}}
180 A
*z
= new (Z
{}) A
; // expected-error {{deleted function}}
182 A
*t00
= new (T
<false, false>{}) A
; // expected-error {{deleted function}}
183 A
*t01
= new (T
<false, true>{}) A
; // expected-error {{deleted function}}
184 A
*t10
= new (T
<true, false>{}) A
; // expected-error {{deleted function}}
185 A
*t11
= new (T
<true, true>{}) A
; // expected-error {{deleted function}}