xref: /llvm-project/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (revision ef7d46c7e6b33b6294f23b6df290b335a761fbd5)
1 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -DPRECXX11
2 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s
3 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1y -verify -fsyntax-only %s -DCPP1Y
4 
5 #define CONST const
6 
7 #ifdef PRECXX11
8 #define static_assert _Static_assert
9 #endif
10 
11 class A {
12   template<typename T> CONST T wrong;           // expected-error {{non-static data member 'wrong' cannot be declared as a template}}
13   template<typename T> CONST T wrong_init = 5;      // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}}
14   template<typename T, typename T0> static CONST T right = T(100);
15   template<typename T> static CONST T right<T,int> = 5;
16   template<typename T> CONST int right<int,T>;  // expected-error {{non-static data member 'right' cannot be declared as a template}}
17   template<typename T> CONST float right<float,T> = 5;  // expected-error {{non-static data member 'right' cannot be declared as a template}}
18 #ifdef PRECXX11
19                                                         // expected-warning@-2 {{in-class initializer for static data member of type 'const float' is a GNU extension}}
20 #else
21                                                         // expected-error@-4 {{in-class initializer for static data member of type 'const float' requires 'constexpr' specifier}}
22                                                         // expected-note@-5 {{add 'constexpr'}}
23 #endif
24   template<> CONST int right<int,int> = 7;
25   template<> CONST float right<float,int>;
26   template static CONST int right<int,int>;     // expected-error {{expected '<' after 'template'}}
27 };
28 
29 namespace out_of_line {
30   class B0 {
31     template<typename T, typename T0> static CONST T right = T(100);
32     template<typename T> static CONST T right<T,int> = T(5);
33   };
34   template<> CONST int B0::right<int,int> = 7; // expected-note {{previous}}
35   template CONST int B0::right<int,int>; // expected-warning {{has no effect}}
36   template<> CONST int B0::right<int,float>; // expected-note {{previous}}
37   template CONST int B0::right<int,float>; // expected-warning {{has no effect}}
38 
39   class B1 {
40     template<typename T, typename T0> static CONST T right;
41     template<typename T> static CONST T right<T,int>;
42   };
43   template<typename T, typename T0> CONST T B1::right = T(100);
44   template<typename T> CONST T B1::right<T,int> = T(5);
45 
46   class B2 {
47     template<typename T, typename T0> static CONST T right = T(100);  // expected-note {{previous initialization is here}}
48     template<typename T> static CONST T right<T,int> = T(5);          // expected-note {{previous initialization is here}}
49   };
50   template<typename T, typename T0> CONST T B2::right = T(100);   // expected-error {{static data member 'right' already has an initializer}}
51   template<typename T> CONST T B2::right<T,int> = T(5);           // expected-error {{static data member 'right' already has an initializer}}
52 
53   class B3 {
54     template<typename T, typename T0> static CONST T right = T(100);
55     template<typename T> static CONST T right<T,int> = T(5);
56   };
57   template<typename T, typename T0> CONST T B3::right;
58   template<typename T> CONST T B3::right<T,int>;
59 
60   class B4 {
61     template<typename T, typename T0> static CONST T a;
62     template<typename T> static CONST T a<T,int> = T(100);
63     template<typename T, typename T0> static CONST T b = T(100);
64     template<typename T> static CONST T b<T,int>;
65   };
66   template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}}
67   template<typename T> CONST T B4::a<T,int>;
68   template CONST int B4::a<int,char>; // expected-note {{in instantiation of}}
69   template CONST int B4::a<int,int>;
70 
71   template<typename T, typename T0> CONST T B4::b;
72   template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}}
73   template CONST int B4::b<int,char>;
74   template CONST int B4::b<int,int>; // expected-note {{in instantiation of}}
75 }
76 
77 namespace non_const_init {
78   class A {
79     template<typename T> static T wrong_inst_undefined = T(10); // expected-note {{refers here}}
80     template<typename T> static T wrong_inst_defined = T(10); // expected-error {{non-const static data member must be initialized out of line}}
81     template<typename T> static T wrong_inst_out_of_line;
82   };
83 
84   template const int A::wrong_inst_undefined<const int>; // expected-error {{undefined}}
85 
86   template<typename T> T A::wrong_inst_defined;
87   template const int A::wrong_inst_defined<const int>;
88   template int A::wrong_inst_defined<int>; // expected-note {{in instantiation of static data member 'non_const_init::A::wrong_inst_defined<int>' requested here}}
89 
90   template<typename T> T A::wrong_inst_out_of_line = T(10);
91   template int A::wrong_inst_out_of_line<int>;
92 
93   class B {
94     template<typename T> static T wrong_inst; // expected-note {{refers here}}
95     template<typename T> static T wrong_inst<T*> = T(100); // expected-error {{non-const static data member must be initialized out of line}} expected-note {{refers here}}
96 
97     template<typename T> static T wrong_inst_fixed;
98     template<typename T> static T wrong_inst_fixed<T*>;
99   };
100   template int B::wrong_inst<int>; // expected-error {{undefined}}
101   // FIXME: It'd be better to produce the 'explicit instantiation of undefined
102   // template' diagnostic here, not the 'must be initialized out of line'
103   // diagnostic.
104   template int B::wrong_inst<int*>; // expected-note {{in instantiation of static data member 'non_const_init::B::wrong_inst<int *>' requested here}}
105   template const int B::wrong_inst<const int*>; // expected-error {{undefined}}
106   template<typename T> T B::wrong_inst_fixed = T(100);
107   template int B::wrong_inst_fixed<int>;
108 
109   class C {
110     template<typename T> static CONST T right_inst = T(10); // expected-note {{here}}
111     template<typename T> static CONST T right_inst<T*> = T(100); // expected-note {{here}}
112   };
113   template CONST int C::right_inst<int>; // expected-error {{undefined variable template}}
114   template CONST int C::right_inst<int*>; // expected-error {{undefined variable template}}
115 
116   namespace pointers {
117 
118     struct C0 {
119       template<typename U> static U Data;
120       template<typename U> static CONST U Data<U*> = U(); // expected-note {{here}}
121 
122       template<typename U> static U Data2;
123       template<typename U> static CONST U Data2<U*> = U();
124     };
125     const int c0_test = C0::Data<int*>;
126     static_assert(c0_test == 0, "");
127     template const int C0::Data<int*>; // expected-error {{undefined}}
128 
129     template<typename U> const U C0::Data2<U*>;
130     template const int C0::Data2<int*>;
131 
132     struct C1a {
133       template<typename U> static U Data;
134       template<typename U> static U* Data<U*>;   // Okay, with out-of-line definition
135     };
136     template<typename T> T* C1a::Data<T*> = new T();
137     template int* C1a::Data<int*>;
138 
139     struct C1b {
140       template<typename U> static U Data;
141       template<typename U> static CONST U* Data<U*>;   // Okay, with out-of-line definition
142     };
143     template<typename T> CONST T* C1b::Data<T*> = (T*)(0);
144     template CONST int* C1b::Data<int*>;
145 
146     struct C2a {
147       template<typename U> static int Data;
148       template<typename U> static U* Data<U*> = new U();   // expected-error {{non-const static data member must be initialized out of line}}
149     };
150     template int* C2a::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int *>' requested here}}
151 
152     struct C2b {
153       template<typename U> static int Data;
154       template<typename U> static U *const Data<U*> = (U*)(0); // expected-error {{static data member of type 'int *const'}}
155     };
156     template<typename U> U *const C2b::Data<U*>;
157     template int *const C2b::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int *>' requested here}}
158   }
159 }
160 
161 #ifndef PRECXX11
162 namespace constexpred {
163   class A {
164     template<typename T> constexpr T wrong;           // expected-error {{non-static data member 'wrong' cannot be declared as a template}}
165                                                       // expected-error@-1 {{declaration of constexpr static data member 'wrong' requires an initializer}}
166     template<typename T> constexpr T wrong_init = 5;  // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}}
167     template<typename T, typename T0> static constexpr T right = T(100);
168     template<typename T> static constexpr T right<T,int> = 5;
169     template<typename T> constexpr int right<int,T>;         // expected-error {{non-static data member 'right' cannot be declared as a template}}
170                                                              // expected-error@-1 {{declaration of constexpr static data member 'right<int, T>' requires an initializer}}
171     template<typename T> constexpr float right<float,T> = 5; // expected-error {{non-static data member 'right' cannot be declared as a template}}
172     template<> constexpr int right<int,int> = 7;
173     template<> constexpr float right<float, int>; // expected-error {{declaration of constexpr static data member 'right<float, int>' requires an initializer}}
174     template static constexpr int right<int,int>;     // expected-error {{expected '<' after 'template'}}
175   };
176 }
177 #endif
178 
179 namespace in_class_template {
180 
181   template<typename T>
182   class D0 {
183     template<typename U> static U Data; // expected-note {{here}}
184     template<typename U> static CONST U Data<U*> = U();
185   };
186   template CONST int D0<float>::Data<int*>;
187   template int D0<float>::Data<int>; // expected-error {{undefined}}
188   template<typename T> template<typename U> const U D0<T>::Data<U*>;
189 
190   template<typename T>
191   class D1 {
192     template<typename U> static U Data;
193     template<typename U> static U* Data<U*>;
194   };
195   template<typename T>
196   template<typename U> U* D1<T>::Data<U*> = (U*)(0);
197   template int* D1<float>::Data<int*>; // expected-note {{previous}}
198   template int* D1<float>::Data<int*>; // expected-error {{duplicate explicit instantiation}}
199 
200   template<typename T>
201   class D2 {
202     template<typename U> static U Data;
203     template<typename U> static U* Data<U*>;
204   };
205   template<>
206   template<typename U> U* D2<float>::Data<U*> = (U*)(0) + 1;
207   template int* D2<float>::Data<int*>; // expected-note {{previous}}
208   template int* D2<float>::Data<int*>; // expected-error {{duplicate explicit instantiation}}
209 
210   template<typename T>
211   struct D3 {
212     template<typename U> static CONST U Data = U(100); // expected-note {{here}}
213   };
214   static_assert(D3<float>::Data<int> == 100, "");
215   template const char D3<float>::Data<char>; // expected-error {{undefined}}
216 
217   namespace bug_files {
218     template<typename T>
219     class D0a {
220       template<typename U> static U Data;
221       template<typename U> static CONST U Data<U*> = U(10);  // expected-note {{previous declaration is here}}
222     };
223     template<>
224     template<typename U> U D0a<float>::Data<U*> = U(100);  // expected-error {{redefinition of 'Data'}}
225 
226     // FIXME: We should accept this, and the corresponding case for class
227     // templates.
228     //
229     // [temp.class.spec.mfunc]/2: If the primary member template is explicitly
230     // specialized for a given specialization of the enclosing class template,
231     // the partial specializations of the member template are ignored
232     template<typename T>
233     class D1 {
234       template<typename U> static U Data;
235       template<typename U> static CONST U Data<U*> = U(10);  // expected-note {{previous declaration is here}}
236     };
237     template<>
238     template<typename U> U D1<float>::Data = U(10);
239     template<>
240     template<typename U> U D1<float>::Data<U*> = U(100);  // expected-error{{redefinition of 'Data'}}
241   }
242 
243   namespace definition_after_outer_instantiation {
244     template<typename A> struct S {
245       template<typename B> static const int V1;
246       template<typename B> static const int V2; // expected-note 3{{here}}
247     };
248     template struct S<int>;
249     template<typename A> template<typename B> const int S<A>::V1 = 123;
250     template<typename A> template<typename B> const int S<A>::V2<B*> = 456;
251 
252     static_assert(S<int>::V1<int> == 123, "");
253 
254     // FIXME: The first and third case below possibly should be accepted. We're
255     // not picking up partial specializations added after the primary template
256     // is instantiated. This is kind of implied by [temp.class.spec.mfunc]/2,
257     // and matches our behavior for member class templates, but it's not clear
258     // that this is intentional. See PR17294 and core-24030.
259     static_assert(S<int>::V2<int*> == 456, ""); // FIXME expected-error {{}} expected-note {{initializer of 'V2<int *>' is unknown}}
260     static_assert(S<int>::V2<int&> == 789, ""); // expected-error {{}} expected-note {{initializer of 'V2<int &>' is unknown}}
261 
262     template<typename A> template<typename B> const int S<A>::V2<B&> = 789;
263     static_assert(S<int>::V2<int&> == 789, ""); // FIXME expected-error {{}} expected-note {{initializer of 'V2<int &>' is unknown}}
264 
265     // All is OK if the partial specialization is declared before the implicit
266     // instantiation of the class template specialization.
267     static_assert(S<char>::V1<int> == 123, "");
268     static_assert(S<char>::V2<int*> == 456, "");
269     static_assert(S<char>::V2<int&> == 789, "");
270   }
271 
272   namespace incomplete_array {
273     template<typename T> extern T var[];
274     template<typename T> T var[] = { 1, 2, 3 };
275     template<> char var<char>[] = "hello";
276     template<typename T> char var<T*>[] = "pointer";
277 
278     static_assert(sizeof(var<int>) == 12, "");
279     static_assert(sizeof(var<char>) == 6, "");
280     static_assert(sizeof(var<void*>) == 8, "");
281 
282     template<typename...> struct tuple;
283 
284     template<typename T> struct A {
285       template<typename U> static T x[];
286       template<typename U> static T y[];
287 
288       template<typename...U> static T y<tuple<U...> >[];
289     };
290 
291     int *use_before_definition = A<int>::x<char>;
292     template<typename T> template<typename U> T A<T>::x[sizeof(U)];
293     static_assert(sizeof(A<int>::x<char>) == 4, "");
294 
295     template<typename T> template<typename...U> T A<T>::y<tuple<U...> >[] = { U()... };
296     static_assert(sizeof(A<int>::y<tuple<char, char, char> >) == 12, "");
297   }
298 
299   namespace bad_reference {
300     struct S {
301       template<typename T> static int A; // expected-note 4{{here}}
302     };
303 
304     template<typename T> void f() {
305       typename T::template A<int> a; // expected-error {{template name refers to non-type template 'S::template A'}}
306     }
307     template<typename T> void g() {
308       T::template A<int>::B = 0; // expected-error {{template name refers to non-type template 'S::template A'}}
309     }
310     template<typename T> void h() {
311       class T::template A<int> c; // expected-error {{template name refers to non-type template 'S::template A'}}
312     }
313 
314     template<typename T>
315     struct X : T::template A<int> {}; // expected-error {{template name refers to non-type template 'S::template A'}}
316 
317     template void f<S>(); // expected-note {{in instantiation of}}
318     template void g<S>(); // expected-note {{in instantiation of}}
319     template void h<S>(); // expected-note {{in instantiation of}}
320     template struct X<S>; // expected-note {{in instantiation of}}
321   }
322 }
323 
324 namespace in_nested_classes {
325   // TODO:
326 }
327 
328 namespace bitfield {
329 struct S {
330   template <int I>
331   static int f : I; // expected-error {{static member 'f' cannot be a bit-field}}
332 };
333 }
334 
335 namespace b20896909 {
336   // This used to crash.
337   template<typename T> struct helper {};
338   template<typename T> class A {
339     template <typename> static helper<typename T::error> x;  // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
340   };
341   void test() {
342     A<int> ai;  // expected-note {{in instantiation of}}
343   }
344 }
345 namespace member_access_is_ok {
346 #ifdef CPP1Y
347   namespace ns1 {
348     struct A {
349       template<class T, T N> constexpr static T Var = N;
350     };
351     static_assert(A{}.Var<int,5> == 5,"");
352   } // end ns1
353 #endif // CPP1Y
354 
355 namespace ns2 {
356   template<class T> struct A {
357     template<class U, T N, U M> static T&& Var;
358   };
359   template<class T> template<class U, T N, U M> T&& A<T>::Var = T(N + M);
360   int *AV = &A<int>().Var<char, 5, 'A'>;
361 
362 } //end ns2
363 } // end ns member_access_is_ok
364 
365 #ifdef CPP1Y
366 namespace PR24473 {
367 struct Value
368 {
369     template<class T>
370     static constexpr T value = 0;
371 };
372 
373 template<typename TValue>
374 struct Something
375 {
376     void foo() {
377         static_assert(TValue::template value<int> == 0, ""); // error
378     }
379 };
380 
381 int main() {
382     Something<Value>{}.foo();
383     return 0;
384 }
385 
386 } // end ns PR24473
387 #endif // CPP1Y
388 
389 namespace dependent_static_var_template {
390   struct A {
391     template<int = 0> static int n; // expected-note 2{{here}}
392   };
393   int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
394 
395   template<typename T>
396   int &f() { return T::template n; } // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
397   int &s = f<A>(); // expected-note {{instantiation of}}
398 
399   namespace B {
400     template<int = 0> static int n; // expected-note {{here}}
401   }
402   int &t = B::template n; // expected-error {{use of variable template 'B::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
403 
404   struct C {
405     template <class T> static T G;
406   };
407   template<class T> T C::G = T(6);
408 
409   template <class T> T F() {
410     C c;
411     return c.G<T>;
412   }
413 
414   int cf() { return F<int>(); }
415 }
416 
417 #ifndef PRECXX11
418 namespace template_vars_in_template {
419 template <int> struct TakesInt {};
420 
421 template <class T2>
422 struct S {
423   template <class T1>
424   static constexpr int v = 42;
425 
426   template <class T>
427   void mf() {
428     constexpr int val = v<T>;
429   }
430 
431   void mf2() {
432     constexpr int val = v<char>;
433     TakesInt<val> ti;
434     (void)ti.x; // expected-error{{no member named 'x' in 'template_vars_in_template::TakesInt<42>'}}
435   }
436 };
437 
438 void useit() {
439   S<int> x;
440   x.mf<double>();
441   x.mf2(); // expected-note{{in instantiation of member function 'template_vars_in_template::S<int>::mf2' requested here}}
442 }
443 }
444 #endif
445