Clang Project

clang_source_code/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
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
11template<typename T> 
12T pi = T(3.1415926535897932385); // expected-note 2{{declared here}}
13
14template<typename T> 
15CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}
16
17template<typename T> extern CONST T vc;
18#ifndef PRECXX11
19// expected-error@-2 {{constexpr variable declaration must be a definition}}
20#endif
21
22namespace 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
58namespace 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
67namespace 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
127namespace 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
176namespace 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
322namespace 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
331namespace use_in_structs {
332  // TODO:
333}
334
335namespace attributes {
336  // TODO:
337}
338
339#ifndef PRECXX11
340namespace 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
359namespace 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
430namespace 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
438namespace PR18530 {
439  template<typename T> int a;
440  int a<int>; // expected-error {{requires 'template<>'}}
441}
442
443namespace PR19152 {
444#ifndef PRECXX11
445  template<typename T> const auto x = 1;
446  static_assert(x<int> == 1, "");
447#endif
448}
449
450namespace 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
460template <typename... Args> struct Variadic_t { };
461template <typename... Args> Variadic_t<Args...> Variadic;
462auto variadic1 = Variadic<>;
463auto variadic2 = Variadic<int, int>;
464#endif
465
466namespace 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