xref: /llvm-project/clang/test/SemaTemplate/default-arguments.cpp (revision e29c085812e259910a3d8b6c2d2f471d1c3eede4)
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 template<typename T, int N = 2> struct X; // expected-note{{template is declared here}}
5 
6 X<int, 1> *x1;
7 X<int> *x2;
8 
9 X<> *x3; // expected-error{{too few template arguments for class template 'X'}}
10 
11 template<typename U = float, int M> struct X;
12 
13 X<> *x4;
14 
15 template<typename T = int> struct Z { };
16 template struct Z<>;
17 
18 // PR4362
19 template<class T> struct a { };
20 template<> struct a<int> { static const bool v = true; };
21 
22 template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member named 'v'}}
23 
24 template struct p<bool>; // expected-note {{in instantiation of default argument for 'p<bool>' required here}}
25 template struct p<int>;
26 
27 // PR5187
28 template<typename T, typename U>
29 struct A;
30 
31 template<typename T, typename U = T>
32 struct A;
33 
34 template<typename T, typename U>
35 struct A {
36   void f(A<T>);
37 };
38 
39 template<typename T>
40 struct B { };
41 
42 template<>
43 struct B<void> {
44   typedef B<void*> type;
45 };
46 
47 // Nested default arguments for template parameters.
48 template<typename T> struct X1 { };
49 
50 template<typename T>
51 struct X2 {
52   template<typename U = typename X1<T>::type> // expected-error{{no type named 'type' in 'X1<int>'}} \
53                                               // expected-error{{no type named 'type' in 'X1<char>'}}
54   struct Inner1 { }; // expected-note{{template is declared here}}
55 
56   template<T Value = X1<T>::value> // expected-error{{no member named 'value' in 'X1<int>'}} \
57                                    // expected-error{{no member named 'value' in 'X1<char>'}}
58   struct NonType1 { }; // expected-note{{template is declared here}}
59 
60   template<T Value>
61   struct Inner2 { };
62 
63   template<typename U>
64   struct Inner3 {
65     template<typename X = T, typename V = U>
66     struct VeryInner { };
67 
68     template<T Value1 = sizeof(T), T Value2 = sizeof(U),
69              T Value3 = Value1 + Value2>
70     struct NonType2 { };
71   };
72 };
73 
74 X2<int> x2i; // expected-note{{in instantiation of template class 'X2<int>' requested here}}
75 X2<int>::Inner1<float> x2iif;
76 
77 X2<int>::Inner1<> x2bad; // expected-error{{too few template arguments for class template 'Inner1'}}
78 
79 X2<int>::NonType1<'a'> x2_nontype1;
80 X2<int>::NonType1<> x2_nontype1_bad; // expected-error{{too few template arguments for class template 'NonType1'}}
81 
82 // Check multi-level substitution into template type arguments
83 X2<int>::Inner3<float>::VeryInner<> vi;
84 X2<char>::Inner3<int>::NonType2<> x2_deep_nontype; // expected-note{{in instantiation of template class 'X2<char>' requested here}}
85 
86 template<typename T, typename U>
87 struct is_same { static const bool value = false; };
88 
89 template<typename T>
90 struct is_same<T, T> { static const bool value = true; };
91 
92 int array1[is_same<__typeof__(vi),
93                X2<int>::Inner3<float>::VeryInner<int, float> >::value? 1 : -1];
94 
95 int array2[is_same<__typeof(x2_deep_nontype),
96                    X2<char>::Inner3<int>::NonType2<sizeof(char), sizeof(int),
97                                     sizeof(char)+sizeof(int)> >::value? 1 : -1];
98 
99 // Template template parameter defaults
100 template<template<typename T> class X = X2> struct X3 { };
101 int array3[is_same<X3<>, X3<X2> >::value? 1 : -1];
102 
103 struct add_pointer {
104   template<typename T>
105   struct apply {
106     typedef T* type;
107   };
108 };
109 
110 template<typename T, template<typename> class X = T::template apply>
111   struct X4;
112 int array4[is_same<X4<add_pointer>,
113                    X4<add_pointer, add_pointer::apply> >::value? 1 : -1];
114 
115 template<int> struct X5 {};
116 template<long long> struct X5b {};
117 template<typename T,
118          template<T> class B = X5> // expected-error {{cannot be narrowed from type 'long long' to 'int'}}
119                                    // expected-note@-1 {{has different template parameters}}
120                                    // expected-note@-2 {{previous template template parameter is here}}
121   struct X6 {};
122 
123 X6<int> x6a;
124 X6<long long> x6b; // expected-note {{while checking a default template argument used here}}
125 X6<long long, X5b> x6c;
126 
127 
128 template<template<class> class X = B<int> > struct X7; // expected-error{{must be a class template}}
129 
130 namespace PR9643 {
131   template<typename T> class allocator {};
132   template<typename T, typename U = allocator<T> > class vector {};
133 
134   template<template<typename U, typename = allocator<U> > class container,
135            typename DT>
136   container<DT> initializer(const DT& d) {
137     return container<DT>();
138   }
139 
140   void f() {
141     vector<int, allocator<int> > v = initializer<vector>(5);
142   }
143 }
144 
145 namespace PR16288 {
146   template<typename X>
147   struct S {
148     template<typename T = int, typename U>
149 #if __cplusplus <= 199711L // C++03 or earlier modes
150     // expected-warning@-2 {{default template arguments for a function template are a C++11 extension}}
151 #endif
152     void f();
153   };
154   template<typename X>
155   template<typename T, typename U>
156   void S<X>::f() {}
157 }
158 
159 namespace DR1635 {
160   template <class T> struct X {
161     template <class U = typename T::type> static void f(int) {} // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
162 #if __cplusplus <= 199711L // C++03 or earlier modes
163     // expected-warning@-2 {{default template arguments for a function template are a C++11 extension}}
164 #endif
165     static void f(...) {}
166   };
167 
168   int g() { X<int>::f(0); } // expected-note {{in instantiation of template class 'DR1635::X<int>' requested here}}
169 }
170 
171 namespace NondefDecls {
172   template<typename T> void f1() {
173     int g1(int defarg = T::error);  // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} \
174                                     // expected-note {{in instantiation of default function argument expression for 'g1<int>' required here}}
175   }
176   template void f1<int>();  // expected-note{{in instantiation of function template specialization 'NondefDecls::f1<int>' requested here}}
177 }
178 
179 template <typename T>
180 struct C {
181   C(T t = ); // expected-error {{expected expression}}
182 };
183 C<int> obj;
184 
185 namespace PR26134 {
186 // Make sure when substituting default template arguments we do it in the current context.
187 template<class T, bool Val = T::value>
188 struct X {};
189 
190 template<bool B> struct Y {
191   void f() { X<Y> xy; }
192   static const bool value = B;
193 };
194 
195 namespace ns1 {
196 template<class T0>
197 struct X {
198   template<bool B = T0::value> struct XInner { static const bool value = B; };
199 };
200 template<bool B> struct S { static const bool value = B; };
201 #if __cplusplus > 199711L
202 template<bool B> struct Y {
203   static constexpr bool f() { return typename X<S<B>>::template XInner<>{}.value; }
204   static_assert(f() == B, "");
205 };
206 Y<true> y;
207 Y<false> y2;
208 #endif
209 
210 } // end ns1
211 } // end ns PR26134
212 
213 namespace friends {
214   namespace ns {
215     template<typename> struct A {
216       template<typename> friend void f();
217       template<typename> friend struct X;
218     };
219     template<typename = int> void f(); // expected-warning 0-1{{extension}}
220     template<typename = int> struct X;
221     A<int> a;
222   }
223   namespace ns {
224     void g() { f(); }
225     X<int> *p;
226   }
227 }
228 
229 namespace unevaluated {
230   int a;
231   template<int = 0> int f(int = a); // expected-warning 0-1{{extension}}
232   int k = sizeof(f());
233 }
234 
235 #if __cplusplus >= 201103L
236 namespace GH68490 {
237 
238 template <typename T> struct S {
239   template <typename U>
240   constexpr int SizeOfU(int param = sizeof(U)) const;
241 
242   template <typename U>
243   constexpr int SizeOfT(int param = sizeof(T)) const;
244 };
245 
246 template <typename T> struct S<T *> {
247   template <typename U>
248   constexpr int SizeOfU(int param = sizeof(U)) const;
249 
250   template <typename U>
251   constexpr int SizeOfT(int param = sizeof(T *)) const;
252 };
253 
254 template <typename T>
255 template <typename U>
256 constexpr int S<T *>::SizeOfU(int param) const {
257   return param;
258 }
259 
260 template <typename T>
261 template <typename U>
262 constexpr int S<T *>::SizeOfT(int param) const {
263   return param;
264 }
265 
266 template <>
267 template <typename T>
268 constexpr int S<int>::SizeOfU(int param) const {
269   return param;
270 }
271 
272 template <>
273 template <typename T>
274 constexpr int S<int>::SizeOfT(int param) const {
275   return param;
276 }
277 
278 static_assert(S<int>().SizeOfU<char>() == sizeof(char), "");
279 static_assert(S<int>().SizeOfT<char>() == sizeof(int), "");
280 static_assert(S<short *>().SizeOfU<char>() == sizeof(char), "");
281 static_assert(S<short *>().SizeOfT<char>() == sizeof(short *), "");
282 
283 } // namespace GH68490
284 
285 #endif
286