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
f()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}}
test_function_deduction()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 {};
f(A<B>,void (*)()noexcept (B))82     template<auto B> void f(A<B>, void(*)() noexcept(B)) {
83       using T = decltype(B);
84       using T = int;
85     }
g()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.
dep()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);
f()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