Clang Project

clang_source_code/test/SemaCXX/cxx1z-noexcept-function-type.cpp
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
8template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-note {{previous}}
9template<typename T> void redecl1() noexcept(noexcept(T())); // ok, same type
10template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}}
11
12template<bool A, bool B> void redecl2() noexcept(A); // expected-note {{previous}}
13template<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.
16template<typename A, typename B> void redecl3() throw(A); // expected-note {{previous}}
17template<typename A, typename B> void redecl3() throw(B); // expected-error {{does not match previous}}
18
19typedef int I;
20template<bool B> void redecl4(I) noexcept(B);
21template<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
23void (*init_with_exact_type_a)(int) noexcept = redecl4<true>;
24void (*init_with_mismatched_type_a)(int) = redecl4<true>;
25auto deduce_auto_from_noexcept_function_ptr_a = redecl4<true>;
26using DeducedType_a = decltype(deduce_auto_from_noexcept_function_ptr_a);
27using DeducedType_a = void (*)(int) noexcept;
28
29void (*init_with_exact_type_b)(int) = redecl4<false>;
30void (*init_with_mismatched_type_b)(int) noexcept = redecl4<false>; // expected-error {{does not match required type}}
31auto deduce_auto_from_noexcept_function_ptr_b = redecl4<false>;
32using DeducedType_b = decltype(deduce_auto_from_noexcept_function_ptr_b);
33using DeducedType_b = void (*)(int);
34
35static_assert(noexcept(init_with_exact_type_a(0)));
36static_assert(noexcept((+init_with_exact_type_a)(0)));
37static_assert(!noexcept(init_with_exact_type_b(0)));
38static_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.
42static_assert(noexcept(static_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0))); // expected-error {{is not allowed}}
43static_assert(noexcept(reinterpret_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0)));
44static_assert(!noexcept(static_cast<decltype(init_with_exact_type_b)>(init_with_exact_type_a)(0)));
45
46template<bool B> auto get_fn() noexcept -> void (*)() noexcept(B) {}
47static_assert(noexcept(get_fn<true>()()));
48static_assert(!noexcept(get_fn<false>()()));
49
50namespace 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
71namespace 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
109namespace ImplicitExceptionSpec {
110  struct S {
111    ~S();
112    void f(const S &s = S());
113  };
114  S::~S() {}
115}
116
117namespace 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)];
124  typedef int arr[3];
125}
126
127namespace 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
134namespace ConversionFunction {
135  struct A { template<typename T> operator T() noexcept; };
136  int a = A().operator int();
137}
138
139using size_t = decltype(sizeof(0));
140
141namespace OperatorDelete {
142  struct W {};
143  struct X {};
144  struct Y {};
145  struct Z {};
146  template<bool N, bool D> struct T {};
147}
148void *operator new(size_t, OperatorDelete::W) noexcept(false);
149void operator delete(void*, OperatorDelete::W) noexcept(false) = delete; // expected-note {{here}}
150void *operator new(size_t, OperatorDelete::X) noexcept(false);
151void operator delete(void*, OperatorDelete::X) noexcept(true) = delete; // expected-note {{here}}
152void *operator new(size_t, OperatorDelete::Y) noexcept(true);
153void operator delete(void*, OperatorDelete::Y) noexcept(false) = delete; // expected-note {{here}}
154void *operator new(size_t, OperatorDelete::Z) noexcept(true);
155void operator delete(void*, OperatorDelete::Z) noexcept(true) = delete; // expected-note {{here}}
156template<bool N, bool D> void *operator new(size_t, OperatorDelete::T<N, D>) noexcept(N);
157template<bool N, bool D> void operator delete(void*, OperatorDelete::T<N, D>) noexcept(D) = delete; // expected-note 4{{here}}
158namespace 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