Clang Project

clang_source_code/test/SemaTemplate/temp_arg_type.cpp
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
6template<typename T> class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}}
7
8// [temp.arg.type]p1
9A<0> *a1; // expected-error{{template argument for template type parameter must be a type}}
10
11A<A> *a2; // expected-error{{use of class template 'A' requires template arguments}}
12
13A<int> *a3;
14A<int()> *a4; 
15A<int(float)> *a5;
16A<A<int> > *a6;
17
18// Pass an overloaded function template:
19template<typename T> void function_tpl(T);
20A<function_tpl> a7;  // expected-error{{template argument for template type parameter must be a type}}
21
22// Pass a qualified name:
23namespace ns {
24template<typename T> class B {};  // expected-note{{template is declared here}}
25}
26A<ns::B> a8; // expected-error{{use of class template 'ns::B' requires template arguments}}
27
28// [temp.arg.type]p2
29void 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
37struct { int x; } Unnamed;
38#if __cplusplus <= 199711L
39// expected-note@-2 {{unnamed type used in template argument was declared here}}
40#endif
41
42A<__typeof__(Unnamed)> *a9;
43#if __cplusplus <= 199711L
44// expected-warning@-2 {{template argument uses unnamed type}}
45#endif
46
47template<typename T, unsigned N>
48struct Array {
49  typedef struct { T x[N]; } type;
50};
51
52template<typename T> struct A1 { };
53A1<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).
60namespace 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