xref: /minix3/external/bsd/llvm/dist/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (revision 0b98e8aad89f2bd4ba80b523d73cf29e9dd82ce1)
1 // RUN: %clang_cc1 -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 {{template is 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 {{cannot refer to variable template 'pi' without a template argument list}}
34     int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}}
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;
62     int a = pi;
63     int ipi = pi<int>;  // expected-error {{expected '(' for function-style cast or type construction}} \
64                         // expected-error {{expected expression}}
65   }
66 }
67 
68 namespace odr_tmpl {
69   namespace pv_cvt {
70     int v;   // expected-note {{previous definition is here}}
71     template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}}
72   }
73   namespace pvt_cv {
74     template<typename T> T v; // expected-note {{previous definition is here}}
75     int v;   // expected-error {{redefinition of 'v' as different kind of symbol}}
76   }
77   namespace pvt_cvt {
78     template<typename T> T v0; // expected-note {{previous definition is here}}
79     template<typename T> T v0; // expected-error {{redefinition of 'v0'}}
80 
81     template<typename T> T v; // expected-note {{previous definition is here}}
82     template<typename T> int v; // expected-error {{redefinition of 'v'}}
83 
84     template<typename T> int v1; // expected-note {{previous template declaration is here}}
85     template<int I> int v1;      // expected-error {{template parameter has a different kind in template redeclaration}}
86   }
87   namespace pvt_use {
88     template<typename T> T v;
89     v = 10;  // expected-error {{C++ requires a type specifier for all declarations}}
90   }
91 
92   namespace pvt_diff_params {
93     // FIXME: (?) Redefinitions should simply be not allowed, whether the
94     // template parameters match or not. However, this current behaviour also
95     // matches that of class templates...
96     template<typename T, typename> T v;   // expected-note 2{{previous template declaration is here}}
97     template<typename T> T v;   // expected-error {{too few template parameters in template redeclaration}}
98     template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}}
99   }
100 
101   namespace pvt_extern {
102     template<typename T> T v = T();
103     template<typename T> extern T v;      // redeclaration is allowed \
104                                           // expected-note {{previous definition is here}}
105     template<typename T> extern int v;    // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}}
106 
107 #ifndef PRECXX11
108     template<typename T> extern auto v;   // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}}
109 #endif
110 
111     template<typename T> T var = T();     // expected-note {{previous definition is here}}
112     extern int var;                       // expected-error {{redefinition of 'var' as different kind of symbol}}
113   }
114 
115 #ifndef PRECXX11
116   namespace pvt_auto {
117     template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}}
118     template<typename T> auto v1 = T();  // expected-note {{previous definition is here}}
119     template<typename T> int v1;   // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}}
120     template<typename T> auto v2 = T();  // expected-note {{previous definition is here}}
121     template<typename T> T v2;   // expected-error {{redefinition of 'v2'}}
122     template<typename T> auto v3 = T();   // expected-note {{previous definition is here}}
123     template<typename T> extern T v3;     // expected-error {{redefinition of 'v3' with a different type: 'T' vs 'auto'}}
124     template<typename T> auto v4 = T();
125     template<typename T> extern auto v4;   // expected-error {{declaration of variable 'v4' with type 'auto' requires an initializer}}
126   }
127 #endif
128 
129 }
130 
131 namespace explicit_instantiation {
132   template<typename T>
133   T pi0a = T(3.1415926535897932385);  // expected-note {{variable template 'pi0a' declared here}}
134   template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}}
135 
136   template<typename T>
137   T pi0b = T(3.1415926535897932385);  // expected-note {{variable template 'pi0b' declared here}}
138   template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}}
139 
140   template<typename T>
141   T pi0c = T(3.1415926535897932385);  // expected-note {{variable template 'pi0c' declared here}}
142   template int pi0c<const int>;  // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}}
143 
144   template<typename T>
145   T pi0 = T(3.1415926535897932385);
146   template int pi0<int>;   // expected-note {{previous explicit instantiation is here}}
147   template int pi0<int>;   // expected-error {{duplicate explicit instantiation of 'pi0<int>'}}
148 
149   template<typename T>
150   CONST T pi1a = T(3.1415926535897932385);  // expected-note {{variable template 'pi1a' declared here}}
151   template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}}
152 
153   template<typename T>
154   CONST T pi1b = T(3.1415926535897932385);  // expected-note {{variable template 'pi1b' declared here}}
155   template int pi1b<const int>;  // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}}
156 
157   template<typename T>
158   CONST T pi1 = T(3.1415926535897932385);
159   template CONST int pi1<int>;   // expected-note {{previous explicit instantiation is here}}
160   template CONST int pi1<int>;   // expected-error {{duplicate explicit instantiation of 'pi1<int>'}}
161 
162 #ifndef PRECXX11
163   namespace auto_var {
164     template<typename T> auto var0 = T();
165     template auto var0<int>;    // expected-error {{'auto' variable template instantiation is not allowed}}
166 
167     template<typename T> auto var = T();
168     template int var<int>;
169   }
170 #endif
171 
172   template<typename=int> int missing_args; // expected-note {{here}}
173   template int missing_args; // expected-error {{must specify a template argument list}}
174 
175   namespace extern_var {
176     // TODO:
177   }
178 }
179 
180 namespace explicit_specialization {
181 
182   namespace good {
183     template<typename T1, typename T2>
184     CONST int pi2 = 1;
185 
186     template<typename T>
187     CONST int pi2<T,int> = 2;
188 
189     template<typename T>
190     CONST int pi2<int,T> = 3;
191 
192     template<> CONST int pi2<int,int> = 4;
193 
194 #ifndef PRECXX11
195     void foo() {
196       static_assert(pi2<int,int> == 4, "");
197       static_assert(pi2<float,int> == 2, "");
198       static_assert(pi2<int,float> == 3, "");
199       static_assert(pi2<int,float> == pi2<int,double>, "");
200       static_assert(pi2<float,float> == 1, "");
201       static_assert(pi2<float,float> == pi2<float,double>, "");
202     }
203 #endif
204   }
205 
206   namespace ambiguous {
207 
208     template<typename T1, typename T2>
209     CONST int pi2 = 1;
210 
211     template<typename T>
212     CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}}
213 
214     template<typename T>
215     CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}}
216 
217     void foo() {
218       int a = pi2<int,int>;  // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}}
219     }
220   }
221 
222   namespace type_changes {
223 
224     template<typename T>
225     T pi0 = T(3.1415926535897932385);
226 
227     template<> float pi0<int> = 10;
228     template<> int pi0<const int> = 10;
229 
230     template<typename T>
231     T pi1 = T(3.1415926535897932385);
232     template<> CONST int pi1<int> = 10;
233 
234     template<typename T>
235     T pi2 = T(3.1415926535897932385);
236     template<> int pi2<const int> = 10;
237 
238     template<typename T>
239     CONST T pi4 = T(3.1415926535897932385);
240     template<> int pi4<int> = 10;
241   }
242 
243   namespace redefinition {
244     template<typename T>
245     T pi0 = T(3.1415926535897932385);
246 
247     template<> int pi0<int> = 10;   // expected-note 3{{previous definition is here}}
248 #ifndef PRECXX11
249 // expected-note@-2 {{previous definition is here}}
250 #endif
251     template<> int pi0<int> = 10;   // expected-error {{redefinition of 'pi0<int>'}}
252     template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}}
253     template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}}
254 #ifndef PRECXX11
255     template<> auto pi0<int> = 10;  // expected-error {{redefinition of 'pi0<int>'}}
256 #endif
257 
258 
259     template<typename T>
260     CONST T pi1 = T(3.1415926535897932385);
261 
262     template<> CONST int pi1<int> = 10;   // expected-note {{previous definition is here}}
263     template<> CONST int pi1<int> = 10;   // expected-error {{redefinition of 'pi1<int>'}}
264   }
265 
266   namespace before_instantiation {
267     template<typename T>
268     T pi0 = T(3.1415926535897932385);   // expected-note {{variable template 'pi0' declared here}}
269 
270     template<> int pi0<int> = 10;
271     template int pi0<int>;
272     template float pi0<int>;    // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}}
273 
274     template<typename T1, typename T2>
275     CONST int pi2 = 1;
276 
277     template<typename T> CONST int pi2<T,int> = 2;
278     template CONST int pi2<int,int>;
279   }
280   namespace after_instantiation {
281     template<typename T>
282     T pi0 = T(3.1415926535897932385);
283 
284     template int pi0<int>;   // expected-note 2{{explicit instantiation first required here}}
285     template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}}
286     template<> float pi0<int>;    // expected-error {{explicit specialization of 'pi0' after instantiation}}
287 
288     template<typename T1, typename T2>
289     CONST int pi2 = 1;
290 
291     template CONST int pi2<int,int>;
292     template<typename T> CONST int pi2<T,int> = 2;
293   }
294 
295 #ifndef PRECXX11
296   namespace auto_var {
297     template<typename T, typename> auto var0 = T();
298     template<typename T> auto var0<T,int> = T();
299     template<> auto var0<int,int> = 7;
300 
301     template<typename T, typename> auto var = T();
302     template<typename T> T var<T,int> = T(5);
303     template<> int var<int,int> = 7;
304 
305     void foo() {
306       int i0 = var0<int,int>;
307       int b = var<int,int>;
308     }
309   }
310 #endif
311 
312   namespace extern_var {
313     // TODO:
314   }
315 
316   namespace diff_type {
317     // TODO:
318     template<typename T> T* var = new T();
319 #ifndef PRECXX11
320     template<typename T> auto var<T*> = T();  // expected-note {{previous definition is here}}
321     template<typename T> T var<T*> = T();     // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}}
322 #endif
323   }
324 }
325 
326 namespace narrowing {
327   template<typename T> T v = {1234};  // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}}
328 #ifndef PRECXX11
329   // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\
330   // expected-note@-2 {{override this message by inserting an explicit cast}}
331 #endif
332   int k = v<char>;        // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}}
333 }
334 
335 namespace use_in_structs {
336   // TODO:
337 }
338 
339 namespace attributes {
340   // TODO:
341 }
342 
343 #ifndef PRECXX11
344 namespace arrays {
345   template<typename T>
346   T* arr = new T[10]{T(10), T(23)};
347 
348   float f = 10.5;
349   template<> float* arr<float> = &f;
350 
351   void bar() {
352     int *iarr = arr<int>;
353     iarr[0] = 1;
354     iarr[2] = 3;
355     iarr[6] = -2;
356 
357     float ff = *arr<float>;
358     float nof = arr<float>[3];  // No bounds-check in C++
359   }
360 }
361 #endif
362 
363 namespace nested {
364 
365   namespace n0a {
366     template<typename T>
367     T pi0a = T(3.1415926535897932385);
368   }
369 
370   using namespace n0a;
371   int i0a = pi0a<int>;
372 
373   template float pi0a<float>;
374   float f0a = pi0a<float>;
375 
376   template<> double pi0a<double> = 5.2;
377   double d0a = pi0a<double>;
378 
379   namespace n0b {
380     template<typename T>
381     T pi0b = T(3.1415926535897932385);
382   }
383 
384   int i0b = n0b::pi0b<int>;
385 
386   template float n0b::pi0b<float>;
387   float f0b = n0b::pi0b<float>;
388 
389   template<> double n0b::pi0b<double> = 5.2;
390   double d0b = n0b::pi0b<double>;
391 
392   namespace n1 {
393     template<typename T>
394     T pi1a = T(3.1415926535897932385);
395 #ifndef PRECXX11
396 // expected-note@-2 {{explicit instantiation refers here}}
397 #endif
398 
399     template<typename T>
400     T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}
401 #ifndef PRECXX11
402 // expected-note@-2 {{explicit instantiation refers here}}
403 #endif
404   }
405 
406   namespace use_n1a {
407     using namespace n1;
408     int i1 = pi1a<int>;
409 
410     template float pi1a<float>;
411 #ifndef PRECXX11
412 // expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}}
413 #endif
414     float f1 = pi1a<float>;
415 
416     template<> double pi1a<double> = 5.2;  // expected-error {{no variable template matches specialization}}
417     double d1 = pi1a<double>;
418   }
419 
420   namespace use_n1b {
421     int i1 = n1::pi1b<int>;
422 
423     template float n1::pi1b<float>;
424 #ifndef PRECXX11
425 // expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}}
426 #endif
427     float f1 = n1::pi1b<float>;
428 
429     template<> double n1::pi1b<double> = 5.2;  // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \
430                                                // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}}
431     double d1 = n1::pi1b<double>;
432   }
433 }
434 
435