1 | // RUN: %clang_cc1 -std=c++98 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11 |
2 | // RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s |
3 | // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s |
4 | |
5 | #ifdef PRECXX11 |
6 | #define CONST const |
7 | #else |
8 | #define CONST constexpr |
9 | #endif |
10 | |
11 | template<typename T> |
12 | T pi = T(3.1415926535897932385); // expected-note 2{{declared here}} |
13 | |
14 | template<typename T> |
15 | CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}} |
16 | |
17 | template<typename T> extern CONST T vc; |
18 | #ifndef PRECXX11 |
19 | // expected-error@-2 {{constexpr variable declaration must be a definition}} |
20 | #endif |
21 | |
22 | namespace use_in_top_level_funcs { |
23 | |
24 | void good() { |
25 | int ipi = pi<int>; |
26 | int icpi = cpi<int>; |
27 | double dpi = pi<double>; |
28 | double dcpi = cpi<double>; |
29 | } |
30 | |
31 | void no_deduce() { |
32 | // template arguments are not deduced for uses of variable templates. |
33 | int ipi = pi; // expected-error {{use of variable template 'pi' requires template arguments}} |
34 | int icpi = cpi; // expected-error {{use of variable template 'cpi' requires template arguments}} |
35 | } |
36 | |
37 | template<typename T> |
38 | T circular_area(T r) { |
39 | return pi<T> * r * r; |
40 | } |
41 | |
42 | template<typename T> |
43 | CONST T const_circular_area(T r) { |
44 | return cpi<T> * r * r; |
45 | } |
46 | |
47 | double use_circular_area(double r) { |
48 | CONST float t = const_circular_area(2.0) - 12; |
49 | #ifndef PRECXX11 |
50 | static_assert(const_circular_area(2) == 12, ""); |
51 | CONST int test = (t > 0) && (t < 1); |
52 | static_assert(test, ""); |
53 | #endif |
54 | return circular_area(r); |
55 | } |
56 | } |
57 | |
58 | namespace shadow { |
59 | void foo() { |
60 | int ipi0 = pi<int>; |
61 | int pi; // expected-note {{found}} |
62 | int a = pi; |
63 | int ipi = pi<int>; // expected-error {{'pi' does not name a template but is followed by template arguments; did you mean '::pi'?}} |
64 | } |
65 | } |
66 | |
67 | namespace odr_tmpl { |
68 | namespace pv_cvt { |
69 | int v; // expected-note {{previous definition is here}} |
70 | template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}} |
71 | } |
72 | namespace pvt_cv { |
73 | template<typename T> T v; // expected-note {{previous definition is here}} |
74 | int v; // expected-error {{redefinition of 'v' as different kind of symbol}} |
75 | } |
76 | namespace pvt_cvt { |
77 | template<typename T> T v0; // expected-note {{previous definition is here}} |
78 | template<typename T> T v0; // expected-error {{redefinition of 'v0'}} |
79 | |
80 | template<typename T> T v; // expected-note {{previous definition is here}} |
81 | template<typename T> int v; // expected-error {{redefinition of 'v'}} |
82 | |
83 | template<typename T> extern int v1; // expected-note {{previous template declaration is here}} |
84 | template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}} |
85 | } |
86 | namespace pvt_use { |
87 | template<typename T> T v; |
88 | v = 10; // expected-error {{C++ requires a type specifier for all declarations}} |
89 | } |
90 | |
91 | namespace pvt_diff_params { |
92 | template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}} |
93 | template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} |
94 | template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}} |
95 | } |
96 | |
97 | namespace pvt_extern { |
98 | template<typename T> T v = T(); |
99 | template<typename T> extern T v; // redeclaration is allowed \ |
100 | // expected-note {{previous declaration is here}} |
101 | template<typename T> extern int v; // expected-error {{redeclaration of 'v' with a different type: 'int' vs 'T'}} |
102 | |
103 | #ifndef PRECXX11 |
104 | template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with deduced type 'auto' requires an initializer}} |
105 | #endif |
106 | |
107 | template<typename T> T var = T(); // expected-note {{previous definition is here}} |
108 | extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}} |
109 | } |
110 | |
111 | #ifndef PRECXX11 |
112 | namespace pvt_auto { |
113 | template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with deduced type 'auto' requires an initializer}} |
114 | template<typename T> auto v1 = T(); // expected-note {{previous definition is here}} |
115 | template<typename T> int v1; // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}} |
116 | template<typename T> auto v2 = T(); // expected-note {{previous definition is here}} |
117 | template<typename T> T v2; // expected-error {{redefinition of 'v2'}} |
118 | template<typename T> auto v3 = T(); // expected-note {{previous definition is here}} |
119 | template<typename T> extern T v3; // expected-error {{redeclaration of 'v3' with a different type: 'T' vs 'auto'}} |
120 | template<typename T> auto v4 = T(); |
121 | template<typename T> extern auto v4; // expected-error {{declaration of variable 'v4' with deduced type 'auto' requires an initializer}} |
122 | } |
123 | #endif |
124 | |
125 | } |
126 | |
127 | namespace explicit_instantiation { |
128 | template<typename T> |
129 | T pi0a = T(3.1415926535897932385); // expected-note {{variable template 'pi0a' declared here}} |
130 | template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}} |
131 | |
132 | template<typename T> |
133 | T pi0b = T(3.1415926535897932385); // expected-note {{variable template 'pi0b' declared here}} |
134 | template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}} |
135 | |
136 | template<typename T> |
137 | T pi0c = T(3.1415926535897932385); // expected-note {{variable template 'pi0c' declared here}} |
138 | template int pi0c<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}} |
139 | |
140 | template<typename T> |
141 | T pi0 = T(3.1415926535897932385); |
142 | template int pi0<int>; // expected-note {{previous explicit instantiation is here}} |
143 | template int pi0<int>; // expected-error {{duplicate explicit instantiation of 'pi0<int>'}} |
144 | |
145 | template<typename T> |
146 | CONST T pi1a = T(3.1415926535897932385); // expected-note {{variable template 'pi1a' declared here}} |
147 | template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}} |
148 | |
149 | template<typename T> |
150 | CONST T pi1b = T(3.1415926535897932385); // expected-note {{variable template 'pi1b' declared here}} |
151 | template int pi1b<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}} |
152 | |
153 | template<typename T> |
154 | CONST T pi1 = T(3.1415926535897932385); |
155 | template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}} |
156 | template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}} |
157 | |
158 | #ifndef PRECXX11 |
159 | namespace auto_var { |
160 | template<typename T> auto var0 = T(); |
161 | template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}} |
162 | |
163 | template<typename T> auto var = T(); |
164 | template int var<int>; |
165 | } |
166 | #endif |
167 | |
168 | template<typename=int> int missing_args; // expected-note {{here}} |
169 | template int missing_args; // expected-error {{must specify a template argument list}} |
170 | |
171 | namespace extern_var { |
172 | // TODO: |
173 | } |
174 | } |
175 | |
176 | namespace explicit_specialization { |
177 | |
178 | namespace good { |
179 | template<typename T1, typename T2> |
180 | CONST int pi2 = 1; |
181 | |
182 | template<typename T> |
183 | CONST int pi2<T,int> = 2; |
184 | |
185 | template<typename T> |
186 | CONST int pi2<int,T> = 3; |
187 | |
188 | template<> CONST int pi2<int,int> = 4; |
189 | |
190 | #ifndef PRECXX11 |
191 | void foo() { |
192 | static_assert(pi2<int,int> == 4, ""); |
193 | static_assert(pi2<float,int> == 2, ""); |
194 | static_assert(pi2<int,float> == 3, ""); |
195 | static_assert(pi2<int,float> == pi2<int,double>, ""); |
196 | static_assert(pi2<float,float> == 1, ""); |
197 | static_assert(pi2<float,float> == pi2<float,double>, ""); |
198 | } |
199 | #endif |
200 | } |
201 | |
202 | namespace ambiguous { |
203 | |
204 | template<typename T1, typename T2> |
205 | CONST int pi2 = 1; |
206 | |
207 | template<typename T> |
208 | CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}} |
209 | |
210 | template<typename T> |
211 | CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}} |
212 | |
213 | void foo() { |
214 | int a = pi2<int,int>; // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}} |
215 | } |
216 | } |
217 | |
218 | namespace type_changes { |
219 | |
220 | template<typename T> |
221 | T pi0 = T(3.1415926535897932385); |
222 | |
223 | template<> float pi0<int> = 10; |
224 | template<> int pi0<const int> = 10; |
225 | |
226 | template<typename T> |
227 | T pi1 = T(3.1415926535897932385); |
228 | template<> CONST int pi1<int> = 10; |
229 | |
230 | template<typename T> |
231 | T pi2 = T(3.1415926535897932385); |
232 | template<> int pi2<const int> = 10; |
233 | |
234 | template<typename T> |
235 | CONST T pi4 = T(3.1415926535897932385); |
236 | template<> int pi4<int> = 10; |
237 | } |
238 | |
239 | namespace redefinition { |
240 | template<typename T> |
241 | T pi0 = T(3.1415926535897932385); |
242 | |
243 | template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}} |
244 | #ifndef PRECXX11 |
245 | // expected-note@-2 {{previous definition is here}} |
246 | #endif |
247 | template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} |
248 | template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}} |
249 | template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}} |
250 | #ifndef PRECXX11 |
251 | template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} |
252 | #endif |
253 | |
254 | |
255 | template<typename T> |
256 | CONST T pi1 = T(3.1415926535897932385); |
257 | |
258 | template<> CONST int pi1<int> = 10; // expected-note {{previous definition is here}} |
259 | template<> CONST int pi1<int> = 10; // expected-error {{redefinition of 'pi1<int>'}} |
260 | } |
261 | |
262 | namespace before_instantiation { |
263 | template<typename T> |
264 | T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}} |
265 | |
266 | template<> int pi0<int> = 10; // expected-note 2{{previous template specialization is here}} |
267 | template int pi0<int>; // expected-warning {{has no effect}} |
268 | template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} expected-warning {{has no effect}} |
269 | |
270 | template<typename T1, typename T2> |
271 | CONST int pi2 = 1; |
272 | |
273 | template<typename T> CONST int pi2<T,int> = 2; |
274 | template CONST int pi2<int,int>; |
275 | } |
276 | namespace after_instantiation { |
277 | template<typename T> |
278 | T pi0 = T(3.1415926535897932385); |
279 | |
280 | template int pi0<int>; // expected-note 2{{explicit instantiation first required here}} |
281 | template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}} |
282 | template<> float pi0<int>; // expected-error {{explicit specialization of 'pi0' after instantiation}} |
283 | |
284 | template<typename T1, typename T2> |
285 | CONST int pi2 = 1; |
286 | |
287 | template CONST int pi2<int,int>; |
288 | template<typename T> CONST int pi2<T,int> = 2; |
289 | } |
290 | |
291 | #ifndef PRECXX11 |
292 | namespace auto_var { |
293 | template<typename T, typename> auto var0 = T(); |
294 | template<typename T> auto var0<T,int> = T(); |
295 | template<> auto var0<int,int> = 7; |
296 | |
297 | template<typename T, typename> auto var = T(); |
298 | template<typename T> T var<T,int> = T(5); |
299 | template<> int var<int,int> = 7; |
300 | |
301 | void foo() { |
302 | int i0 = var0<int,int>; |
303 | int b = var<int,int>; |
304 | } |
305 | } |
306 | #endif |
307 | |
308 | namespace extern_var { |
309 | // TODO: |
310 | } |
311 | |
312 | namespace diff_type { |
313 | // TODO: |
314 | template<typename T> T* var = new T(); |
315 | #ifndef PRECXX11 |
316 | template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}} |
317 | template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}} |
318 | #endif |
319 | } |
320 | } |
321 | |
322 | namespace narrowing { |
323 | template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}} |
324 | #ifndef PRECXX11 |
325 | // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\ |
326 | // expected-note@-2 {{insert an explicit cast to silence this issue}} |
327 | #endif |
328 | int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}} |
329 | } |
330 | |
331 | namespace use_in_structs { |
332 | // TODO: |
333 | } |
334 | |
335 | namespace attributes { |
336 | // TODO: |
337 | } |
338 | |
339 | #ifndef PRECXX11 |
340 | namespace arrays { |
341 | template<typename T> |
342 | T* arr = new T[10]{T(10), T(23)}; |
343 | |
344 | float f = 10.5; |
345 | template<> float* arr<float> = &f; |
346 | |
347 | void bar() { |
348 | int *iarr = arr<int>; |
349 | iarr[0] = 1; |
350 | iarr[2] = 3; |
351 | iarr[6] = -2; |
352 | |
353 | float ff = *arr<float>; |
354 | float nof = arr<float>[3]; // No bounds-check in C++ |
355 | } |
356 | } |
357 | #endif |
358 | |
359 | namespace nested { |
360 | |
361 | namespace n0a { |
362 | template<typename T> |
363 | T pi0a = T(3.1415926535897932385); |
364 | } |
365 | |
366 | using namespace n0a; |
367 | int i0a = pi0a<int>; |
368 | |
369 | template float pi0a<float>; |
370 | float f0a = pi0a<float>; |
371 | |
372 | template<> double pi0a<double> = 5.2; |
373 | double d0a = pi0a<double>; |
374 | |
375 | namespace n0b { |
376 | template<typename T> |
377 | T pi0b = T(3.1415926535897932385); |
378 | } |
379 | |
380 | int i0b = n0b::pi0b<int>; |
381 | |
382 | template float n0b::pi0b<float>; |
383 | float f0b = n0b::pi0b<float>; |
384 | |
385 | template<> double n0b::pi0b<double> = 5.2; |
386 | double d0b = n0b::pi0b<double>; |
387 | |
388 | namespace n1 { |
389 | template<typename T> |
390 | T pi1a = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} |
391 | #ifndef PRECXX11 |
392 | // expected-note@-2 {{explicit instantiation refers here}} |
393 | #endif |
394 | |
395 | template<typename T> |
396 | T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} |
397 | #ifndef PRECXX11 |
398 | // expected-note@-2 {{explicit instantiation refers here}} |
399 | #endif |
400 | } |
401 | |
402 | namespace use_n1a { |
403 | using namespace n1; |
404 | int i1 = pi1a<int>; |
405 | |
406 | template float pi1a<float>; |
407 | #ifndef PRECXX11 |
408 | // expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}} |
409 | #endif |
410 | float f1 = pi1a<float>; |
411 | |
412 | template<> double pi1a<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}} |
413 | double d1 = pi1a<double>; |
414 | } |
415 | |
416 | namespace use_n1b { |
417 | int i1 = n1::pi1b<int>; |
418 | |
419 | template float n1::pi1b<float>; |
420 | #ifndef PRECXX11 |
421 | // expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}} |
422 | #endif |
423 | float f1 = n1::pi1b<float>; |
424 | |
425 | template<> double n1::pi1b<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}} |
426 | double d1 = n1::pi1b<double>; |
427 | } |
428 | } |
429 | |
430 | namespace nested_name { |
431 | template<typename T> int a; // expected-note {{variable template 'a' declared here}} |
432 | a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}} |
433 | |
434 | class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}} |
435 | enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}} |
436 | } |
437 | |
438 | namespace PR18530 { |
439 | template<typename T> int a; |
440 | int a<int>; // expected-error {{requires 'template<>'}} |
441 | } |
442 | |
443 | namespace PR19152 { |
444 | #ifndef PRECXX11 |
445 | template<typename T> const auto x = 1; |
446 | static_assert(x<int> == 1, ""); |
447 | #endif |
448 | } |
449 | |
450 | namespace PR19169 { |
451 | template <typename T> int* f(); |
452 | template <typename T> void f(); |
453 | template<> int f<double>; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}} |
454 | |
455 | template <typename T> void g(); |
456 | template<> int g<double>; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} |
457 | } |
458 | |
459 | #ifndef PRECXX11 |
460 | template <typename... Args> struct Variadic_t { }; |
461 | template <typename... Args> Variadic_t<Args...> Variadic; |
462 | auto variadic1 = Variadic<>; |
463 | auto variadic2 = Variadic<int, int>; |
464 | #endif |
465 | |
466 | namespace VexingParse { |
467 | template <typename> int var; // expected-note {{declared here}} |
468 | int x(var); // expected-error {{use of variable template 'var' requires template arguments}} |
469 | } |
470 | |