1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2
3 // This test creates cases where implicit instantiations of various entities
4 // would cause a diagnostic, but provides expliict specializations for those
5 // entities that avoid the diagnostic. The specializations are alternately
6 // declarations and definitions, and the intent of this test is to verify
7 // that we allow specializations only in the appropriate namespaces (and
8 // nowhere else).
9 struct NonDefaultConstructible {
10 NonDefaultConstructible(int);
11 };
12
13
14 // C++ [temp.expl.spec]p1:
15 // An explicit specialization of any of the following:
16
17 // -- function template
18 namespace N0 {
f0(T)19 template<typename T> void f0(T) { // expected-note{{here}}
20 T t;
21 }
22
f0(NonDefaultConstructible)23 template<> void f0(NonDefaultConstructible) { }
24
test_f0(NonDefaultConstructible NDC)25 void test_f0(NonDefaultConstructible NDC) {
26 f0(NDC);
27 }
28
29 template<> void f0(int);
30 template<> void f0(long);
31 }
32
f0(int)33 template<> void N0::f0(int) { } // okay
34
35 namespace N1 {
f0(long)36 template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
37 }
38
39 template<> void N0::f0(double); // expected-warning{{C++11 extension}}
f0(double)40 template<> void N0::f0(double) { }
41
42 struct X1 {
43 template<typename T> void f(T);
44
45 template<> void f(int); // expected-error{{in class scope}}
46 };
47
48 // -- class template
49 namespace N0 {
50
51 template<typename T>
52 struct X0 { // expected-note 2{{here}}
53 static T member; // expected-note{{here}}
54
f1N0::X055 void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
56 t = 17;
57 }
58
59 struct Inner : public T { }; // expected-note 3{{here}}
60
61 template<typename U>
62 struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \
63 // expected-error{{base specifier}}
64
65 template<typename U>
66 void ft1(T t, U u); // expected-note{{explicitly specialized}}
67 };
68
69 }
70
71 template<typename T>
72 template<typename U>
ft1(T t,U u)73 void N0::X0<T>::ft1(T t, U u) {
74 t = u;
75 }
76
77 template<typename T> T N0::X0<T>::member;
78
79 template<> struct N0::X0<void> { }; // expected-warning{{C++11 extension}}
80 N0::X0<void> test_X0;
81
82 namespace N1 {
83 template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}}
84 }
85
86 namespace N0 {
87 template<> struct X0<volatile void>;
88 }
89
90 template<> struct N0::X0<volatile void> {
91 void f1(void *);
92 };
93
94 // -- member function of a class template
f1(void *)95 template<> void N0::X0<void*>::f1(void *) { } // expected-warning{{member function specialization}}
96
test_spec(N0::X0<void * > xvp,void * vp)97 void test_spec(N0::X0<void*> xvp, void *vp) {
98 xvp.f1(vp);
99 }
100
101 namespace N0 {
f1(void *)102 template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
103
104 template<> void X0<const volatile void*>::f1(const volatile void*);
105 }
106
test_x0_cvvoid(N0::X0<const volatile void * > x0,const volatile void * cvp)107 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
108 x0.f1(cvp); // okay: we've explicitly specialized
109 }
110
111 // -- static data member of a class template
112 namespace N0 {
113 // This actually tests p15; the following is a declaration, not a definition.
114 template<>
115 NonDefaultConstructible X0<NonDefaultConstructible>::member;
116
117 template<> long X0<long>::member = 17;
118
119 template<> float X0<float>::member;
120
121 template<> double X0<double>::member;
122 }
123
get_static_member()124 NonDefaultConstructible &get_static_member() {
125 return N0::X0<NonDefaultConstructible>::member;
126 }
127
128 template<> int N0::X0<int>::member; // expected-warning{{C++11 extension}}
129
130 template<> float N0::X0<float>::member = 3.14f;
131
132 namespace N1 {
133 template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
134 }
135
136 // -- member class of a class template
137 namespace N0 {
138
139 template<>
140 struct X0<void*>::Inner { };
141
142 template<>
143 struct X0<int>::Inner { };
144
145 template<>
146 struct X0<unsigned>::Inner;
147
148 template<>
149 struct X0<float>::Inner;
150
151 template<>
152 struct X0<double>::Inner; // expected-note{{forward declaration}}
153 }
154
155 template<>
156 struct N0::X0<long>::Inner { }; // expected-warning{{C++11 extension}}
157
158 template<>
159 struct N0::X0<float>::Inner { };
160
161 namespace N1 {
162 template<>
163 struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
164
165 template<>
166 struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
167 };
168
169 N0::X0<void*>::Inner inner0;
170 N0::X0<int>::Inner inner1;
171 N0::X0<long>::Inner inner2;
172 N0::X0<float>::Inner inner3;
173 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
174
175 // -- member class template of a class template
176 namespace N0 {
177 template<>
178 template<>
179 struct X0<void*>::InnerTemplate<int> { };
180
181 template<> template<>
182 struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
183
184 template<> template<>
185 struct X0<int>::InnerTemplate<long>;
186
187 template<> template<>
188 struct X0<int>::InnerTemplate<double>;
189 }
190
191 template<> template<>
192 struct N0::X0<int>::InnerTemplate<long> { }; // okay
193
194 template<> template<>
195 struct N0::X0<int>::InnerTemplate<float> { }; // expected-warning{{class template specialization}}
196
197 namespace N1 {
198 template<> template<>
199 struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
200 }
201
202 N0::X0<void*>::InnerTemplate<int> inner_template0;
203 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
204 N0::X0<int>::InnerTemplate<long> inner_template2;
205 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
206
207 // -- member function template of a class template
208 namespace N0 {
209 template<>
210 template<>
ft1(void *,const void *)211 void X0<void*>::ft1(void*, const void*) { }
212
213 template<> template<>
214 void X0<void*>::ft1(void *, int);
215
216 template<> template<>
217 void X0<void*>::ft1(void *, unsigned);
218
219 template<> template<>
220 void X0<void*>::ft1(void *, long);
221 }
222
223 template<> template<>
ft1(void *,unsigned)224 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
225
226 template<> template<>
ft1(void *,float)227 void N0::X0<void*>::ft1(void *, float) { } // expected-warning{{function template specialization}}
228
229 namespace N1 {
230 template<> template<>
ft1(void *,long)231 void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
232 }
233
234
test_func_template(N0::X0<void * > xvp,void * vp,const void * cvp,int i,unsigned u)235 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
236 int i, unsigned u) {
237 xvp.ft1(vp, cvp);
238 xvp.ft1(vp, i);
239 xvp.ft1(vp, u);
240 }
241
242 namespace PR8979 {
243 template<typename Z>
244 struct X0 {
245 template <class T, class U> class Inner;
246 struct OtherInner;
247 template<typename T, typename U> void f(Inner<T, U>&);
248
249 typedef Inner<OtherInner, OtherInner> MyInner;
250 template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}}
251 };
252 }
253