xref: /aosp_15_r20/external/clang/test/SemaTemplate/default-arguments.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify %s
2*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
3*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
4*67e74705SXin Li template<typename T, int N = 2> struct X; // expected-note{{template is declared here}}
5*67e74705SXin Li 
6*67e74705SXin Li X<int, 1> *x1;
7*67e74705SXin Li X<int> *x2;
8*67e74705SXin Li 
9*67e74705SXin Li X<> *x3; // expected-error{{too few template arguments for class template 'X'}}
10*67e74705SXin Li 
11*67e74705SXin Li template<typename U = float, int M> struct X;
12*67e74705SXin Li 
13*67e74705SXin Li X<> *x4;
14*67e74705SXin Li 
15*67e74705SXin Li template<typename T = int> struct Z { };
16*67e74705SXin Li template struct Z<>;
17*67e74705SXin Li 
18*67e74705SXin Li // PR4362
19*67e74705SXin Li template<class T> struct a { };
20*67e74705SXin Li template<> struct a<int> { static const bool v = true; };
21*67e74705SXin Li 
22*67e74705SXin Li template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member named 'v'}}
23*67e74705SXin Li 
24*67e74705SXin Li template struct p<bool>; // expected-note {{in instantiation of default argument for 'p<bool>' required here}}
25*67e74705SXin Li template struct p<int>;
26*67e74705SXin Li 
27*67e74705SXin Li // PR5187
28*67e74705SXin Li template<typename T, typename U>
29*67e74705SXin Li struct A;
30*67e74705SXin Li 
31*67e74705SXin Li template<typename T, typename U = T>
32*67e74705SXin Li struct A;
33*67e74705SXin Li 
34*67e74705SXin Li template<typename T, typename U>
35*67e74705SXin Li struct A {
36*67e74705SXin Li   void f(A<T>);
37*67e74705SXin Li };
38*67e74705SXin Li 
39*67e74705SXin Li template<typename T>
40*67e74705SXin Li struct B { };
41*67e74705SXin Li 
42*67e74705SXin Li template<>
43*67e74705SXin Li struct B<void> {
44*67e74705SXin Li   typedef B<void*> type;
45*67e74705SXin Li };
46*67e74705SXin Li 
47*67e74705SXin Li // Nested default arguments for template parameters.
48*67e74705SXin Li template<typename T> struct X1 { };
49*67e74705SXin Li 
50*67e74705SXin Li template<typename T>
51*67e74705SXin Li struct X2 {
52*67e74705SXin Li   template<typename U = typename X1<T>::type> // expected-error{{no type named 'type' in 'X1<int>'}} \
53*67e74705SXin Li                                               // expected-error{{no type named 'type' in 'X1<char>'}}
54*67e74705SXin Li   struct Inner1 { }; // expected-note{{template is declared here}}
55*67e74705SXin Li 
56*67e74705SXin Li   template<T Value = X1<T>::value> // expected-error{{no member named 'value' in 'X1<int>'}} \
57*67e74705SXin Li                                    // expected-error{{no member named 'value' in 'X1<char>'}}
58*67e74705SXin Li   struct NonType1 { }; // expected-note{{template is declared here}}
59*67e74705SXin Li 
60*67e74705SXin Li   template<T Value>
61*67e74705SXin Li   struct Inner2 { };
62*67e74705SXin Li 
63*67e74705SXin Li   template<typename U>
64*67e74705SXin Li   struct Inner3 {
65*67e74705SXin Li     template<typename X = T, typename V = U>
66*67e74705SXin Li     struct VeryInner { };
67*67e74705SXin Li 
68*67e74705SXin Li     template<T Value1 = sizeof(T), T Value2 = sizeof(U),
69*67e74705SXin Li              T Value3 = Value1 + Value2>
70*67e74705SXin Li     struct NonType2 { };
71*67e74705SXin Li   };
72*67e74705SXin Li };
73*67e74705SXin Li 
74*67e74705SXin Li X2<int> x2i; // expected-note{{in instantiation of template class 'X2<int>' requested here}}
75*67e74705SXin Li X2<int>::Inner1<float> x2iif;
76*67e74705SXin Li 
77*67e74705SXin Li X2<int>::Inner1<> x2bad; // expected-error{{too few template arguments for class template 'Inner1'}}
78*67e74705SXin Li 
79*67e74705SXin Li X2<int>::NonType1<'a'> x2_nontype1;
80*67e74705SXin Li X2<int>::NonType1<> x2_nontype1_bad; // expected-error{{too few template arguments for class template 'NonType1'}}
81*67e74705SXin Li 
82*67e74705SXin Li // Check multi-level substitution into template type arguments
83*67e74705SXin Li X2<int>::Inner3<float>::VeryInner<> vi;
84*67e74705SXin Li X2<char>::Inner3<int>::NonType2<> x2_deep_nontype; // expected-note{{in instantiation of template class 'X2<char>' requested here}}
85*67e74705SXin Li 
86*67e74705SXin Li template<typename T, typename U>
87*67e74705SXin Li struct is_same { static const bool value = false; };
88*67e74705SXin Li 
89*67e74705SXin Li template<typename T>
90*67e74705SXin Li struct is_same<T, T> { static const bool value = true; };
91*67e74705SXin Li 
92*67e74705SXin Li int array1[is_same<__typeof__(vi),
93*67e74705SXin Li                X2<int>::Inner3<float>::VeryInner<int, float> >::value? 1 : -1];
94*67e74705SXin Li 
95*67e74705SXin Li int array2[is_same<__typeof(x2_deep_nontype),
96*67e74705SXin Li                    X2<char>::Inner3<int>::NonType2<sizeof(char), sizeof(int),
97*67e74705SXin Li                                     sizeof(char)+sizeof(int)> >::value? 1 : -1];
98*67e74705SXin Li 
99*67e74705SXin Li // Template template parameter defaults
100*67e74705SXin Li template<template<typename T> class X = X2> struct X3 { };
101*67e74705SXin Li int array3[is_same<X3<>, X3<X2> >::value? 1 : -1];
102*67e74705SXin Li 
103*67e74705SXin Li struct add_pointer {
104*67e74705SXin Li   template<typename T>
105*67e74705SXin Li   struct apply {
106*67e74705SXin Li     typedef T* type;
107*67e74705SXin Li   };
108*67e74705SXin Li };
109*67e74705SXin Li 
110*67e74705SXin Li template<typename T, template<typename> class X = T::template apply>
111*67e74705SXin Li   struct X4;
112*67e74705SXin Li int array4[is_same<X4<add_pointer>,
113*67e74705SXin Li                    X4<add_pointer, add_pointer::apply> >::value? 1 : -1];
114*67e74705SXin Li 
115*67e74705SXin Li template<int> struct X5 {}; // expected-note{{has a different type 'int'}}
116*67e74705SXin Li template<long> struct X5b {};
117*67e74705SXin Li template<typename T,
118*67e74705SXin Li          template<T> class B = X5> // expected-error{{template template argument has different}} \
119*67e74705SXin Li                                    // expected-note{{previous non-type template parameter}}
120*67e74705SXin Li   struct X6 {};
121*67e74705SXin Li 
122*67e74705SXin Li X6<int> x6a;
123*67e74705SXin Li X6<long> x6b; // expected-note{{while checking a default template argument}}
124*67e74705SXin Li X6<long, X5b> x6c;
125*67e74705SXin Li 
126*67e74705SXin Li 
127*67e74705SXin Li template<template<class> class X = B<int> > struct X7; // expected-error{{must be a class template}}
128*67e74705SXin Li 
129*67e74705SXin Li namespace PR9643 {
130*67e74705SXin Li   template<typename T> class allocator {};
131*67e74705SXin Li   template<typename T, typename U = allocator<T> > class vector {};
132*67e74705SXin Li 
133*67e74705SXin Li   template<template<typename U, typename = allocator<U> > class container,
134*67e74705SXin Li            typename DT>
initializer(const DT & d)135*67e74705SXin Li   container<DT> initializer(const DT& d) {
136*67e74705SXin Li     return container<DT>();
137*67e74705SXin Li   }
138*67e74705SXin Li 
f()139*67e74705SXin Li   void f() {
140*67e74705SXin Li     vector<int, allocator<int> > v = initializer<vector>(5);
141*67e74705SXin Li   }
142*67e74705SXin Li }
143*67e74705SXin Li 
144*67e74705SXin Li namespace PR16288 {
145*67e74705SXin Li   template<typename X>
146*67e74705SXin Li   struct S {
147*67e74705SXin Li     template<typename T = int, typename U>
148*67e74705SXin Li #if __cplusplus <= 199711L // C++03 or earlier modes
149*67e74705SXin Li     // expected-warning@-2 {{default template arguments for a function template are a C++11 extension}}
150*67e74705SXin Li #endif
151*67e74705SXin Li     void f();
152*67e74705SXin Li   };
153*67e74705SXin Li   template<typename X>
154*67e74705SXin Li   template<typename T, typename U>
f()155*67e74705SXin Li   void S<X>::f() {}
156*67e74705SXin Li }
157*67e74705SXin Li 
158*67e74705SXin Li namespace DR1635 {
159*67e74705SXin Li   template <class T> struct X {
fDR1635::X160*67e74705SXin Li     template <class U = typename T::type> static void f(int) {} // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
161*67e74705SXin Li #if __cplusplus <= 199711L // C++03 or earlier modes
162*67e74705SXin Li     // expected-warning@-2 {{default template arguments for a function template are a C++11 extension}}
163*67e74705SXin Li #endif
fDR1635::X164*67e74705SXin Li     static void f(...) {}
165*67e74705SXin Li   };
166*67e74705SXin Li 
g()167*67e74705SXin Li   int g() { X<int>::f(0); } // expected-note {{in instantiation of template class 'DR1635::X<int>' requested here}}
168*67e74705SXin Li }
169*67e74705SXin Li 
170*67e74705SXin Li namespace NondefDecls {
f1()171*67e74705SXin Li   template<typename T> void f1() {
172*67e74705SXin Li     int g1(int defarg = T::error);  // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
173*67e74705SXin Li   }
174*67e74705SXin Li   template void f1<int>();  // expected-note{{in instantiation of function template specialization 'NondefDecls::f1<int>' requested here}}
175*67e74705SXin Li }
176*67e74705SXin Li 
177*67e74705SXin Li template <typename T>
178*67e74705SXin Li struct C {
179*67e74705SXin Li   C(T t = ); // expected-error {{expected expression}}
180*67e74705SXin Li };
181*67e74705SXin Li C<int> obj;
182*67e74705SXin Li 
183*67e74705SXin Li namespace PR26134 {
184*67e74705SXin Li // Make sure when substituting default template arguments we do it in the current context.
185*67e74705SXin Li template<class T, bool Val = T::value>
186*67e74705SXin Li struct X {};
187*67e74705SXin Li 
188*67e74705SXin Li template<bool B> struct Y {
fPR26134::Y189*67e74705SXin Li   void f() { X<Y> xy; }
190*67e74705SXin Li   static const bool value = B;
191*67e74705SXin Li };
192*67e74705SXin Li 
193*67e74705SXin Li namespace ns1 {
194*67e74705SXin Li template<class T0>
195*67e74705SXin Li struct X {
196*67e74705SXin Li   template<bool B = T0::value> struct XInner { static const bool value = B; };
197*67e74705SXin Li };
198*67e74705SXin Li template<bool B> struct S { static const bool value = B; };
199*67e74705SXin Li #if __cplusplus > 199711L
200*67e74705SXin Li template<bool B> struct Y {
fPR26134::ns1::Y201*67e74705SXin Li   static constexpr bool f() { return typename X<S<B>>::template XInner<>{}.value; }
202*67e74705SXin Li   static_assert(f() == B, "");
203*67e74705SXin Li };
204*67e74705SXin Li Y<true> y;
205*67e74705SXin Li Y<false> y2;
206*67e74705SXin Li #endif
207*67e74705SXin Li 
208*67e74705SXin Li } // end ns1
209*67e74705SXin Li } // end ns PR26134
210