| 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 | |