Clang Project

clang_source_code/test/Parser/cxx1z-class-template-argument-deduction.cpp
1// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s
2
3template <typename T> struct A { // expected-note 38{{declared here}}
4  constexpr A() {}
5  constexpr A(int) {}
6  constexpr operator int() { return 0; }
7};
8A() -> A<int>;
9A(int) -> A<int>;
10
11// Make sure we still correctly parse cases where a template can appear without arguments.
12namespace template_template_arg {
13  template<template<typename> typename> struct X {};
14  template<typename> struct Y {};
15
16  X<A> xa;
17  Y<A> ya; // expected-error {{requires template arguments}}
18  X<::A> xcca;
19  Y<::A> ycca; // expected-error {{requires template arguments}}
20  X<A*> xap; // expected-error {{requires template arguments}}
21  X<const A> xca; // expected-error {{requires template arguments}}
22  X<A const> xac; // expected-error {{requires template arguments}}
23  // FIXME: This should not parse as a template template argument due to the
24  // trailing attributes.
25  X<A [[]]> xa_attr;
26
27  template<template<typename> typename = A> struct XD {};
28  template<typename = A> struct YD {}; // expected-error {{requires template arguments}}
29  template<template<typename> typename = ::A> struct XCCD {};
30  template<typename = ::A> struct YCCD {}; // expected-error {{requires template arguments}}
31
32  // FIXME: replacing the invalid type with 'int' here is horrible
33  template <A a = A<int>()> class C { }; // expected-error {{requires template arguments}}
34  template<typename T = A> struct G { }; // expected-error {{requires template arguments}}
35}
36
37namespace template_template_arg_pack {
38  template<template<typename> typename...> struct XP {};
39  template<typename...> struct YP {};
40
41  struct Z { template<typename T> struct Q {}; }; // expected-note 2{{here}}
42  
43  template<typename T> using ZId = Z;
44
45  template<typename ...Ts> struct A {
46    XP<ZId<Ts>::Q...> xe;
47    YP<ZId<Ts>::Q...> ye; // expected-error {{requires template arguments}}
48
49    XP<ZId<Ts>::Q> xp; // expected-error {{unexpanded parameter pack}}
50    YP<ZId<Ts>::Q> yp; // expected-error {{requires template arguments}}
51  };
52}
53
54namespace injected_class_name {
55  template<typename T> struct A {
56    A(T);
57    void f(int) { // expected-note {{previous}}
58      A a = 1;
59      injected_class_name::A b = 1; // expected-note {{in instantiation of template class 'injected_class_name::A<int>'}}
60    }
61    void f(T); // expected-error {{multiple overloads of 'f' instantiate to the same signature 'void (int)}}
62  };
63  A<short> ai = 1;
64  A<double>::A b(1); // expected-error {{constructor name}}
65}
66
67struct member {
68  A a; // expected-error {{requires template arguments}}
69  A *b; // expected-error {{requires template arguments}}
70  const A c; // expected-error {{requires template arguments}}
71
72  void f() throw (A); // expected-error {{requires template arguments}}
73
74  friend A; // expected-error {{requires template arguments; argument deduction not allowed in friend declaration}}
75
76  operator A(); // expected-error {{requires template arguments; argument deduction not allowed in conversion function type}}
77
78  static A x; // expected-error {{declaration of variable 'x' with deduced type 'A' requires an initializer}}
79  static constexpr A y = 0;
80};
81
82namespace in_typedef {
83  typedef A *AutoPtr; // expected-error {{requires template arguments; argument deduction not allowed in typedef}}
84  typedef A (*PFun)(int a); // expected-error{{requires template arguments; argument deduction not allowed in typedef}}
85  typedef A Fun(int a) -> decltype(a + a); // expected-error{{requires template arguments; argument deduction not allowed in function return type}}
86}
87
88namespace stmt {
89  void g(A a) { // expected-error{{requires template arguments; argument deduction not allowed in function prototype}}
90    try { }
91    catch (A &a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}}
92    catch (const A a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}}
93    try { } catch (A a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}}
94
95    // FIXME: The standard only permits class template argument deduction in a
96    // simple-declaration or cast. We also permit it in conditions,
97    // for-range-declarations, member-declarations for static data members, and
98    // new-expressions, because not doing so would be bizarre.
99    A local = 0;
100    static A local_static = 0;
101    static thread_local A thread_local_static = 0;
102    if (A a = 0) {}
103    if (A a = 0; a) {}
104    switch (A a = 0) {} // expected-warning {{no case matching constant switch condition '0'}}
105    switch (A a = 0; a) {} // expected-warning {{no case matching constant switch condition '0'}}
106    for (A a = 0; a; /**/) {}
107    for (/**/; A a = 0; /**/) {}
108    while (A a = 0) {}
109    int arr[3];
110    for (A a : arr) {}
111  }
112
113  namespace std {
114    class type_info;
115  }
116}
117
118namespace expr {
119  template<typename T> struct U {};
120  void j() {
121    (void)typeid(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
122    (void)sizeof(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
123    (void)__alignof(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
124
125    U<A> v; // expected-error {{requires template arguments}}
126
127    int n;
128    (void)dynamic_cast<A&>(n); // expected-error{{requires template arguments; argument deduction not allowed here}}
129    (void)static_cast<A*>(&n); // expected-error{{requires template arguments; argument deduction not allowed here}}
130    (void)reinterpret_cast<A*>(&n); // expected-error{{requires template arguments; argument deduction not allowed here}}
131    (void)const_cast<A>(n); // expected-error{{requires template arguments; argument deduction not allowed here}}
132    (void)*(A*)(&n); // expected-error{{requires template arguments; argument deduction not allowed here}}
133    (void)(A)(n); // expected-error{{requires template arguments; argument deduction not allowed here}}
134    (void)(A){n}; // expected-error{{requires template arguments; argument deduction not allowed here}}
135
136    (void)A(n);
137    (void)A{n};
138    (void)new A(n);
139    (void)new A{n};
140    (void)new A;
141  }
142}
143
144namespace decl {
145  enum E : A {}; // expected-error{{requires template arguments; argument deduction not allowed here}}
146  struct F : A {}; // expected-error{{expected class name}}
147
148  using B = A; // expected-error{{requires template arguments}}
149
150  auto k() -> A; // expected-error{{requires template arguments}}
151
152  A a;
153  A b = 0;
154  const A c = 0;
155  A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
156  A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
157  A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}}
158  A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}}
159  A F::*pm = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
160  A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}}
161  A [x, y] = 0; // expected-error {{cannot be declared with type 'A'}} expected-error {{type 'A<int>' decomposes into 0 elements, but 2 names were provided}}
162}
163
164namespace typename_specifier {
165  struct F {};
166
167  void e() {
168    (void) typename ::A(0);
169    (void) typename ::A{0};
170    new typename ::A(0);
171    new typename ::A{0};
172    typename ::A a = 0;
173    const typename ::A b = 0;
174    if (typename ::A a = 0) {}
175    for (typename ::A a = 0; typename ::A b = 0; /**/) {}
176
177    (void)(typename ::A)(0); // expected-error{{requires template arguments; argument deduction not allowed here}}
178    (void)(typename ::A){0}; // expected-error{{requires template arguments; argument deduction not allowed here}}
179  }
180  typename ::A a = 0;
181  const typename ::A b = 0;
182  typename ::A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
183  typename ::A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
184  typename ::A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}}
185  typename ::A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}}
186  typename ::A F::*pm = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
187  typename ::A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}}
188  typename ::A [x, y] = 0; // expected-error {{cannot be declared with type 'typename ::A'}} expected-error {{type 'typename ::A<int>' (aka 'A<int>') decomposes into 0}}
189
190  struct X { template<typename T> struct A { A(T); }; }; // expected-note 8{{declared here}}
191
192  template<typename T> void f() {
193    (void) typename T::A(0);
194    (void) typename T::A{0};
195    new typename T::A(0);
196    new typename T::A{0};
197    typename T::A a = 0;
198    const typename T::A b = 0;
199    if (typename T::A a = 0) {} // expected-error {{value of type 'typename X::A<int>' (aka 'typename_specifier::X::A<int>') is not contextually convertible to 'bool'}}
200    for (typename T::A a = 0; typename T::A b = 0; /**/) {} // expected-error {{value of type 'typename X::A<int>' (aka 'typename_specifier::X::A<int>') is not contextually convertible to 'bool'}}
201
202    {(void)(typename T::A)(0);} // expected-error{{refers to class template member}}
203    {(void)(typename T::A){0};} // expected-error{{refers to class template member}}
204    {typename T::A (parens) = 0;} // expected-error {{refers to class template member in 'typename_specifier::X'; argument deduction not allowed here}}
205    // expected-warning@-1 {{disambiguated as redundant parentheses around declaration of variable named 'parens'}} expected-note@-1 {{add a variable name}} expected-note@-1{{remove parentheses}} expected-note@-1 {{add enclosing parentheses}}
206    {typename T::A *p = 0;} // expected-error {{refers to class template member}}
207    {typename T::A &r = *p;} // expected-error {{refers to class template member}}
208    {typename T::A arr[3] = 0;} // expected-error {{refers to class template member}}
209    {typename T::A F::*pm = 0;} // expected-error {{refers to class template member}}
210    {typename T::A (*fp)() = 0;} // expected-error {{refers to class template member}}
211    {typename T::A [x, y] = 0;} // expected-error {{cannot be declared with type 'typename T::A'}} expected-error {{type 'typename X::A<int>' (aka 'typename_specifier::X::A<int>') decomposes into 0}}
212  }
213  template void f<X>(); // expected-note {{instantiation of}}
214
215  template<typename T> void g(typename T::A = 0); // expected-note {{refers to class template member}}
216  void h() { g<X>(); } // expected-error {{no matching function}}
217}
218
219namespace parenthesized {
220  template<typename T> struct X { X(T); };                    
221  auto n = (X([]{}));
222}
223
224namespace within_template_arg_list {
225  template<typename T> struct X { constexpr X(T v) : v(v) {} T v; };
226  template<int N = X(1).v> struct Y {};
227  using T = Y<>;
228  using T = Y<X(1).v>;
229  using T = Y<within_template_arg_list::X(1).v>;
230
231  template<int ...N> struct Z { Y<X(N)...> y; };
232}
233