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