1 | // RUN: %clang_cc1 -fsyntax-only -verify -triple %itanium_abi_triple -std=c++11 -ftemplate-depth 16 -fcxx-exceptions -fexceptions %s |
2 | |
3 | // DR1330: an exception specification for a function template is only |
4 | // instantiated when it is needed. |
5 | |
6 | // Note: the test is Itanium-specific because it depends on key functions in the |
7 | // PR12763 namespace. |
8 | |
9 | template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'Incomplete' is not allowed in exception specification}} |
10 | struct Incomplete; // expected-note{{forward}} |
11 | |
12 | void test_f1(Incomplete *incomplete_p, int *int_p) { |
13 | f1(int_p); |
14 | f1(incomplete_p); // expected-note{{instantiation of exception spec}} |
15 | } |
16 | |
17 | template<typename T> struct A { |
18 | template<typename U> struct B { |
19 | static void f() noexcept(A<U>().n); |
20 | }; |
21 | |
22 | constexpr A() : n(true) {} |
23 | bool n; |
24 | }; |
25 | |
26 | static_assert(noexcept(A<int>::B<char>::f()), ""); |
27 | |
28 | template<unsigned N> struct S { |
29 | static void recurse() noexcept(noexcept(S<N+1>::recurse())); // \ |
30 | // expected-error {{no member named 'recurse'}} \ |
31 | // expected-note 9{{instantiation of exception spec}} |
32 | }; |
33 | |
34 | template<> struct S<10> {}; |
35 | void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of exception spec}} expected-error {{not superset}} |
36 | |
37 | |
38 | namespace dr1330_example { |
39 | template <class T> struct A { |
40 | void f(...) throw (typename T::X); |
41 | void f(int); |
42 | }; |
43 | |
44 | int main() { |
45 | A<int>().f(42); |
46 | } |
47 | |
48 | struct S { |
49 | template<typename T> static void f() throw(typename T::X); |
50 | typedef decltype(f<S>()) X; // expected-error {{exception specification is not available}} |
51 | }; |
52 | |
53 | struct T { |
54 | template<typename T> static void f() throw(T**); |
55 | typedef decltype(f<S>()) X; // expected-error {{exception specification is not available}} |
56 | }; |
57 | |
58 | template<typename T> |
59 | struct U { |
60 | void f() noexcept(T::error); |
61 | void (g)() noexcept(T::error); |
62 | }; |
63 | U<int> uint; // ok |
64 | } |
65 | |
66 | namespace core_19754_example { |
67 | template<typename T> T declval() noexcept; |
68 | |
69 | template<typename T, typename = decltype(T(declval<T&&>()))> |
70 | struct is_movable { static const bool value = true; }; |
71 | |
72 | template<typename T> |
73 | struct wrap { |
74 | T val; |
75 | void irrelevant(wrap &p) noexcept(is_movable<T>::value); |
76 | }; |
77 | |
78 | template<typename T> |
79 | struct base { |
80 | base() {} |
81 | base(const typename T::type1 &); |
82 | base(const typename T::type2 &); |
83 | }; |
84 | |
85 | template<typename T> |
86 | struct type1 { |
87 | wrap<typename T::base> base; |
88 | }; |
89 | |
90 | template<typename T> |
91 | struct type2 { |
92 | wrap<typename T::base> base; |
93 | }; |
94 | |
95 | struct types { |
96 | typedef base<types> base; |
97 | typedef type1<types> type1; |
98 | typedef type2<types> type2; |
99 | }; |
100 | |
101 | base<types> val = base<types>(); |
102 | } |
103 | |
104 | namespace pr9485 { |
105 | template <typename T> void f1(T) throw(typename T::exception); // expected-note {{candidate}} |
106 | template <typename T> void f1(T, int = 0) throw(typename T::noitpecxe); // expected-note {{candidate}} |
107 | |
108 | template <typename T> void f2(T) noexcept(T::throws); // expected-note {{candidate}} |
109 | template <typename T> void f2(T, int = 0) noexcept(T::sworht); // expected-note {{candidate}} |
110 | |
111 | void test() { |
112 | f1(0); // expected-error {{ambiguous}} |
113 | f2(0); // expected-error {{ambiguous}} |
114 | } |
115 | } |
116 | |
117 | struct Exc1 { char c[4]; }; |
118 | struct Exc2 { double x, y, z; }; |
119 | struct Base { |
120 | virtual void f() noexcept; // expected-note {{overridden}} |
121 | }; |
122 | template<typename T> struct Derived : Base { |
123 | void f() noexcept (sizeof(T) == 4); // expected-error {{is more lax}} |
124 | void g() noexcept (T::error); |
125 | }; |
126 | |
127 | Derived<Exc1> d1; // ok |
128 | Derived<Exc2> d2; // expected-note {{in instantiation of}} |
129 | |
130 | // If the vtable for a derived class is used, the exception specification of |
131 | // any member function which ends up in that vtable is needed, even if it was |
132 | // declared in a base class. |
133 | namespace PR12763 { |
134 | template<bool *B> struct T { |
135 | virtual void f() noexcept (*B); // expected-error {{constant expression}} expected-note {{read of non-const}} |
136 | }; |
137 | bool b; // expected-note {{here}} |
138 | struct X : public T<&b> { |
139 | virtual void g(); |
140 | }; |
141 | void X::g() {} // expected-note {{in instantiation of}} |
142 | } |
143 | |
144 | namespace Variadic { |
145 | template<bool B> void check() { static_assert(B, ""); } |
146 | template<bool B, bool B2, bool ...Bs> void check() { static_assert(B, ""); check<B2, Bs...>(); } |
147 | |
148 | template<typename ...T> void consume(T...); |
149 | |
150 | template<typename ...T> void f(void (*...p)() throw (T)) { |
151 | void (*q[])() = { p... }; |
152 | consume((p(),0)...); |
153 | } |
154 | template<bool ...B> void g(void (*...p)() noexcept (B)) { |
155 | consume((p(),0)...); |
156 | check<noexcept(p()) == B ...>(); |
157 | } |
158 | template<typename ...T> void i() { |
159 | consume([]() throw(T) {} ...); |
160 | consume([]() noexcept(sizeof(T) == 4) {} ...); |
161 | } |
162 | template<bool ...B> void j() { |
163 | consume([](void (*p)() noexcept(B)) { |
164 | void (*q)() noexcept = p; // expected-error {{not superset of source}} |
165 | } ...); |
166 | } |
167 | |
168 | void z() { |
169 | f<int, char, double>(nullptr, nullptr, nullptr); |
170 | g<true, false, true>(nullptr, nullptr, nullptr); |
171 | i<int, long, short>(); |
172 | j<true, true>(); |
173 | j<true, false>(); // expected-note {{in instantiation of}} |
174 | } |
175 | |
176 | } |
177 | |
178 | namespace NondefDecls { |
179 | template<typename T> void f1() { |
180 | int g1(int) noexcept(T::error); // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} |
181 | } |
182 | template void f1<int>(); // expected-note{{in instantiation of function template specialization 'NondefDecls::f1<int>' requested here}} |
183 | } |
184 | |
185 | |