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