1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s |
3 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s |
4 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s |
5 | |
6 | template<typename T> class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}} |
7 | |
8 | // [temp.arg.type]p1 |
9 | A<0> *a1; // expected-error{{template argument for template type parameter must be a type}} |
10 | |
11 | A<A> *a2; // expected-error{{use of class template 'A' requires template arguments}} |
12 | |
13 | A<int> *a3; |
14 | A<int()> *a4; |
15 | A<int(float)> *a5; |
16 | A<A<int> > *a6; |
17 | |
18 | // Pass an overloaded function template: |
19 | template<typename T> void function_tpl(T); |
20 | A<function_tpl> a7; // expected-error{{template argument for template type parameter must be a type}} |
21 | |
22 | // Pass a qualified name: |
23 | namespace ns { |
24 | template<typename T> class B {}; // expected-note{{template is declared here}} |
25 | } |
26 | A<ns::B> a8; // expected-error{{use of class template 'ns::B' requires template arguments}} |
27 | |
28 | // [temp.arg.type]p2 |
29 | void f() { |
30 | class X { }; |
31 | A<X> * a = 0; |
32 | #if __cplusplus <= 199711L |
33 | // expected-warning@-2 {{template argument uses local type 'X'}} |
34 | #endif |
35 | } |
36 | |
37 | struct { int x; } Unnamed; |
38 | #if __cplusplus <= 199711L |
39 | // expected-note@-2 {{unnamed type used in template argument was declared here}} |
40 | #endif |
41 | |
42 | A<__typeof__(Unnamed)> *a9; |
43 | #if __cplusplus <= 199711L |
44 | // expected-warning@-2 {{template argument uses unnamed type}} |
45 | #endif |
46 | |
47 | template<typename T, unsigned N> |
48 | struct Array { |
49 | typedef struct { T x[N]; } type; |
50 | }; |
51 | |
52 | template<typename T> struct A1 { }; |
53 | A1<Array<int, 17>::type> ax; |
54 | |
55 | // FIXME: [temp.arg.type]p3. The check doesn't really belong here (it |
56 | // belongs somewhere in the template instantiation section). |
57 | |
58 | #if __cplusplus >= 201703 |
59 | // As a defect resolution, we support deducing B in noexcept(B). |
60 | namespace deduce_noexcept { |
61 | template<typename> struct function; |
62 | template<typename R, typename ...A, bool N> |
63 | struct function<R(A...) noexcept(N)> { |
64 | static constexpr bool Noexcept = N; |
65 | }; |
66 | static_assert(function<int(float, double) noexcept>::Noexcept); |
67 | static_assert(!function<int(float, double)>::Noexcept); |
68 | |
69 | void noexcept_function() noexcept; |
70 | void throwing_function(); |
71 | |
72 | template<typename T, bool B> float &deduce_function(T(*)() noexcept(B)); // expected-note {{candidate}} |
73 | template<typename T> int &deduce_function(T(*)() noexcept); // expected-note {{candidate}} |
74 | void test_function_deduction() { |
75 | // FIXME: This should probably unambiguously select the second overload. |
76 | int &r = deduce_function(noexcept_function); // expected-error {{ambiguous}} |
77 | float &s = deduce_function(throwing_function); |
78 | } |
79 | |
80 | namespace low_priority_deduction { |
81 | template<int> struct A {}; |
82 | template<auto B> void f(A<B>, void(*)() noexcept(B)) { |
83 | using T = decltype(B); |
84 | using T = int; |
85 | } |
86 | void g() { f(A<0>(), g); } // ok, deduce B as an int |
87 | } |
88 | |
89 | // FIXME: It's not clear whether this should work. We're told to deduce with |
90 | // P being the function template type and A being the declared type, which |
91 | // would accept this, but considering the exception specification in such |
92 | // cases breaks new/delete matching. |
93 | template<bool Noexcept> void dep() noexcept(Noexcept) {} // expected-note 3{{couldn't infer template argument 'Noexcept'}} |
94 | template void dep(); // expected-error {{does not refer to a function template}} |
95 | template void dep() noexcept(true); // expected-error {{does not refer to a function template}} |
96 | template void dep() noexcept(false); // expected-error {{does not refer to a function template}} |
97 | |
98 | // FIXME: It's also not clear whether this should be valid: do we substitute |
99 | // into the function type (including the exception specification) or not? |
100 | template<typename T> typename T::type1 f() noexcept(T::a); |
101 | template<typename T> typename T::type2 f() noexcept(T::b) {} |
102 | struct X { |
103 | static constexpr bool b = true; |
104 | using type1 = void; |
105 | using type2 = void; |
106 | }; |
107 | template void f<X>(); |
108 | } |
109 | #endif |
110 | |