1 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-c++1y-extensions |
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 | // C++ [temp.expl.spec]p1: |
14 | // An explicit specialization of any of the following: |
15 | |
16 | // -- function template |
17 | namespace N0 { |
18 | template<typename T> void f0(T) { |
19 | T t; |
20 | } |
21 | |
22 | template<> void f0(NonDefaultConstructible) { } |
23 | |
24 | void test_f0(NonDefaultConstructible NDC) { |
25 | f0(NDC); |
26 | } |
27 | |
28 | template<> void f0(int); |
29 | template<> void f0(long); |
30 | } |
31 | |
32 | template<> void N0::f0(int) { } // okay |
33 | |
34 | namespace N1 { |
35 | template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} |
36 | } |
37 | |
38 | template<> void N0::f0(double) { } |
39 | |
40 | struct X1 { |
41 | template<typename T> void f(T); |
42 | |
43 | template<> void f(int); // OK (DR727) |
44 | }; |
45 | |
46 | // -- class template |
47 | namespace N0 { |
48 | |
49 | template<typename T> |
50 | struct X0 { // expected-note {{here}} |
51 | static T member; |
52 | |
53 | void f1(T t) { |
54 | t = 17; |
55 | } |
56 | |
57 | struct Inner : public T { }; // expected-note 2{{here}} |
58 | |
59 | template<typename U> |
60 | struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \ |
61 | // expected-error{{base specifier}} |
62 | |
63 | template<typename U> |
64 | void ft1(T t, U u); |
65 | }; |
66 | |
67 | } |
68 | |
69 | template<typename T> |
70 | template<typename U> |
71 | void N0::X0<T>::ft1(T t, U u) { |
72 | t = u; |
73 | } |
74 | |
75 | template<typename T> T N0::X0<T>::member; |
76 | |
77 | template<> struct N0::X0<void> { }; |
78 | N0::X0<void> test_X0; |
79 | |
80 | namespace N1 { |
81 | template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}} |
82 | } |
83 | |
84 | namespace N0 { |
85 | template<> struct X0<volatile void>; |
86 | } |
87 | |
88 | template<> struct N0::X0<volatile void> { |
89 | void f1(void *); |
90 | }; |
91 | |
92 | // -- variable template [C++1y] |
93 | namespace N0 { |
94 | template<typename T> int v0; // expected-note 4{{explicitly specialized declaration is here}} |
95 | template<> extern int v0<char[1]>; |
96 | template<> extern int v0<char[2]>; |
97 | template<> extern int v0<char[5]>; |
98 | template<> extern int v0<char[6]>; |
99 | } |
100 | using N0::v0; |
101 | |
102 | template<typename T> int v1; // expected-note 4{{explicitly specialized declaration is here}} |
103 | template<> extern int v1<char[3]>; |
104 | template<> extern int v1<char[4]>; |
105 | template<> extern int v1<char[7]>; |
106 | template<> extern int v1<char[8]>; |
107 | |
108 | template<> int N0::v0<int[1]>; |
109 | template<> int v0<int[2]>; |
110 | template<> int ::v1<int[3]>; // expected-warning {{extra qualification}} |
111 | template<> int v1<int[4]>; |
112 | |
113 | template<> int N0::v0<char[1]>; |
114 | template<> int v0<char[2]>; |
115 | template<> int ::v1<char[3]>; // expected-warning {{extra qualification}} |
116 | template<> int v1<char[4]>; |
117 | |
118 | namespace N1 { |
119 | template<> int N0::v0<int[5]>; // expected-error {{not in a namespace enclosing 'N0'}} |
120 | template<> int v0<int[6]>; // expected-error {{not in a namespace enclosing 'N0'}} |
121 | template<> int ::v1<int[7]>; // expected-error {{must occur at global scope}} |
122 | template<> int v1<int[8]>; // expected-error {{must occur at global scope}} |
123 | |
124 | template<> int N0::v0<char[5]>; // expected-error {{not in a namespace enclosing 'N0'}} |
125 | template<> int v0<char[6]>; // expected-error {{not in a namespace enclosing 'N0'}} |
126 | template<> int ::v1<char[7]>; // expected-error {{must occur at global scope}} |
127 | template<> int v1<char[8]>; // expected-error {{must occur at global scope}} |
128 | } |
129 | |
130 | // -- member function of a class template |
131 | template<> void N0::X0<void*>::f1(void *) { } |
132 | |
133 | void test_spec(N0::X0<void*> xvp, void *vp) { |
134 | xvp.f1(vp); |
135 | } |
136 | |
137 | namespace N0 { |
138 | template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}} |
139 | |
140 | template<> void X0<const volatile void*>::f1(const volatile void*); |
141 | } |
142 | |
143 | void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) { |
144 | x0.f1(cvp); // okay: we've explicitly specialized |
145 | } |
146 | |
147 | // -- static data member of a class template |
148 | namespace N0 { |
149 | // This actually tests p15; the following is a declaration, not a definition. |
150 | template<> |
151 | NonDefaultConstructible X0<NonDefaultConstructible>::member; |
152 | |
153 | template<> long X0<long>::member = 17; |
154 | |
155 | template<> float X0<float>::member; |
156 | |
157 | template<> double X0<double>::member; |
158 | } |
159 | |
160 | NonDefaultConstructible &get_static_member() { |
161 | return N0::X0<NonDefaultConstructible>::member; |
162 | } |
163 | |
164 | template<> int N0::X0<int>::member; |
165 | |
166 | template<> float N0::X0<float>::member = 3.14f; |
167 | |
168 | namespace N1 { |
169 | template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}} |
170 | } |
171 | |
172 | // -- member class of a class template |
173 | namespace N0 { |
174 | |
175 | template<> |
176 | struct X0<void*>::Inner { }; |
177 | |
178 | template<> |
179 | struct X0<int>::Inner { }; |
180 | |
181 | template<> |
182 | struct X0<unsigned>::Inner; |
183 | |
184 | template<> |
185 | struct X0<float>::Inner; |
186 | |
187 | template<> |
188 | struct X0<double>::Inner; // expected-note{{forward declaration}} |
189 | } |
190 | |
191 | template<> |
192 | struct N0::X0<long>::Inner { }; |
193 | |
194 | template<> |
195 | struct N0::X0<float>::Inner { }; |
196 | |
197 | namespace N1 { |
198 | template<> |
199 | struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}} |
200 | |
201 | template<> |
202 | struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}} |
203 | }; |
204 | |
205 | N0::X0<void*>::Inner inner0; |
206 | N0::X0<int>::Inner inner1; |
207 | N0::X0<long>::Inner inner2; |
208 | N0::X0<float>::Inner inner3; |
209 | N0::X0<double>::Inner inner4; // expected-error{{incomplete}} |
210 | |
211 | // -- member class template of a class template |
212 | namespace N0 { |
213 | template<> |
214 | template<> |
215 | struct X0<void*>::InnerTemplate<int> { }; |
216 | |
217 | template<> template<> |
218 | struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}} |
219 | |
220 | template<> template<> |
221 | struct X0<int>::InnerTemplate<long>; |
222 | |
223 | template<> template<> |
224 | struct X0<int>::InnerTemplate<double>; |
225 | } |
226 | |
227 | template<> template<> |
228 | struct N0::X0<int>::InnerTemplate<long> { }; // okay |
229 | |
230 | template<> template<> |
231 | struct N0::X0<int>::InnerTemplate<float> { }; |
232 | |
233 | namespace N1 { |
234 | template<> template<> |
235 | struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}} |
236 | } |
237 | |
238 | N0::X0<void*>::InnerTemplate<int> inner_template0; |
239 | N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}} |
240 | N0::X0<int>::InnerTemplate<long> inner_template2; |
241 | N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}} |
242 | |
243 | // -- member function template of a class template |
244 | namespace N0 { |
245 | template<> |
246 | template<> |
247 | void X0<void*>::ft1(void*, const void*) { } |
248 | |
249 | template<> template<> |
250 | void X0<void*>::ft1(void *, int); |
251 | |
252 | template<> template<> |
253 | void X0<void*>::ft1(void *, unsigned); |
254 | |
255 | template<> template<> |
256 | void X0<void*>::ft1(void *, long); |
257 | } |
258 | |
259 | template<> template<> |
260 | void N0::X0<void*>::ft1(void *, unsigned) { } // okay |
261 | |
262 | template<> template<> |
263 | void N0::X0<void*>::ft1(void *, float) { } |
264 | |
265 | namespace N1 { |
266 | template<> template<> |
267 | void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} |
268 | } |
269 | |
270 | |
271 | void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp, |
272 | int i, unsigned u) { |
273 | xvp.ft1(vp, cvp); |
274 | xvp.ft1(vp, i); |
275 | xvp.ft1(vp, u); |
276 | } |
277 | |
278 | namespace has_inline_namespaces { |
279 | inline namespace inner { |
280 | template<class T> void f(T&); |
281 | |
282 | template<class T> |
283 | struct X0 { |
284 | struct MemberClass; |
285 | |
286 | void mem_func(); |
287 | |
288 | template<typename U> |
289 | struct MemberClassTemplate; |
290 | |
291 | template<typename U> |
292 | void mem_func_template(U&); |
293 | |
294 | static int value; |
295 | }; |
296 | } |
297 | |
298 | struct X1; |
299 | struct X2; |
300 | |
301 | // An explicit specialization whose declarator-id is not qualified |
302 | // shall be declared in the nearest enclosing namespace of the |
303 | // template, or, if the namespace is inline (7.3.1), any namespace |
304 | // from its enclosing namespace set. |
305 | template<> void f(X1&); |
306 | template<> void f<X2>(X2&); |
307 | |
308 | template<> struct X0<X1> { }; |
309 | |
310 | template<> struct X0<X2>::MemberClass { }; |
311 | |
312 | template<> void X0<X2>::mem_func(); |
313 | |
314 | template<> template<typename T> struct X0<X2>::MemberClassTemplate { }; |
315 | |
316 | template<> template<typename T> void X0<X2>::mem_func_template(T&) { } |
317 | |
318 | template<> int X0<X2>::value = 12; |
319 | } |
320 | |
321 | struct X3; |
322 | struct X4; |
323 | |
324 | template<> void has_inline_namespaces::f(X3&); |
325 | template<> void has_inline_namespaces::f<X4>(X4&); |
326 | |
327 | template<> struct has_inline_namespaces::X0<X3> { }; |
328 | |
329 | template<> struct has_inline_namespaces::X0<X4>::MemberClass { }; |
330 | |
331 | template<> void has_inline_namespaces::X0<X4>::mem_func(); |
332 | |
333 | template<> template<typename T> |
334 | struct has_inline_namespaces::X0<X4>::MemberClassTemplate { }; |
335 | |
336 | template<> template<typename T> |
337 | void has_inline_namespaces::X0<X4>::mem_func_template(T&) { } |
338 | |
339 | template<> int has_inline_namespaces::X0<X4>::value = 13; |
340 | |
341 | namespace PR12938 { |
342 | template<typename> [[noreturn]] void func(); |
343 | template<> void func<int>(); |
344 | } |
345 | |