cxx1y-variable-templates_in_class.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
1// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -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#define CONST const
6
7#ifdef PRECXX11
8#define static_assert(expr, msg) typedef int static_assert[(expr) ? 1 : -1];
9#endif
10
11class A {
12  template<typename T> CONST T wrong;           // expected-error {{member 'wrong' declared as a template}}
13  template<typename T> CONST T wrong_init = 5;      // expected-error {{member 'wrong_init' 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 {{member 'right' declared as a template}}
17  template<typename T> CONST float right<float,T> = 5;  // expected-error {{member 'right' declared as a template}}
18  template<> static CONST int right<int,int> = 7;       // expected-error {{explicit specialization of 'right' in class scope}}
19  template<> static CONST float right<float,int>;       // expected-error {{explicit specialization of 'right' in class scope}}
20  template static CONST int right<int,int>;     // expected-error {{template specialization requires 'template<>'}} \
21                                                // expected-error {{explicit specialization of 'right' in class scope}}
22};
23
24namespace out_of_line {
25  class B0 {
26    template<typename T, typename T0> static CONST T right = T(100);
27    template<typename T> static CONST T right<T,int> = T(5);
28  };
29  template<> CONST int B0::right<int,int> = 7;
30  template CONST int B0::right<int,int>;
31  template<> CONST int B0::right<int,float>;
32  template CONST int B0::right<int,float>;
33
34  class B1 {
35    template<typename T, typename T0> static CONST T right;
36    template<typename T> static CONST T right<T,int>;
37  };
38  template<typename T, typename T0> CONST T B1::right = T(100);
39  template<typename T> CONST T B1::right<T,int> = T(5);
40
41  class B2 {
42    template<typename T, typename T0> static CONST T right = T(100);  // expected-note {{previous initialization is here}}
43    template<typename T> static CONST T right<T,int> = T(5);          // expected-note {{previous initialization is here}}
44  };
45  template<typename T, typename T0> CONST T B2::right = T(100);   // expected-error {{static data member 'right' already has an initializer}}
46  template<typename T> CONST T B2::right<T,int> = T(5);           // expected-error {{static data member 'right' already has an initializer}}
47
48  class B3 {
49    template<typename T, typename T0> static CONST T right = T(100);
50    template<typename T> static CONST T right<T,int> = T(5);
51  };
52  template<typename T, typename T0> CONST T B3::right;
53  template<typename T> CONST T B3::right<T,int>;
54
55  class B4 {
56    template<typename T, typename T0> static CONST T a;
57    template<typename T> static CONST T a<T,int> = T(100);
58    template<typename T, typename T0> static CONST T b = T(100);
59    template<typename T> static CONST T b<T,int>;
60  };
61  template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}}
62  template<typename T> CONST T B4::a<T,int>;
63  template CONST int B4::a<int,char>; // expected-note {{in instantiation of}}
64  template CONST int B4::a<int,int>;
65
66  template<typename T, typename T0> CONST T B4::b;
67  template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}}
68  template CONST int B4::b<int,char>;
69  template CONST int B4::b<int,int>; // expected-note {{in instantiation of}}
70}
71
72namespace non_const_init {
73  class A {
74    template<typename T> static T wrong_inst_undefined = T(10); // expected-note {{refers here}}
75    template<typename T> static T wrong_inst_defined = T(10); // expected-error {{non-const static data member must be initialized out of line}}
76    template<typename T> static T wrong_inst_out_of_line;
77  };
78
79  template const int A::wrong_inst_undefined<const int>; // expected-error {{undefined}}
80
81  template<typename T> T A::wrong_inst_defined;
82  template const int A::wrong_inst_defined<const int>;
83  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}}
84
85  template<typename T> T A::wrong_inst_out_of_line = T(10);
86  template int A::wrong_inst_out_of_line<int>;
87
88  class B {
89    template<typename T> static T wrong_inst; // expected-note {{refers here}}
90    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}}
91
92    template<typename T> static T wrong_inst_fixed;
93    template<typename T> static T wrong_inst_fixed<T*>;
94  };
95  template int B::wrong_inst<int>; // expected-error {{undefined}}
96  // FIXME: It'd be better to produce the 'explicit instantiation of undefined
97  // template' diagnostic here, not the 'must be initialized out of line'
98  // diagnostic.
99  template int B::wrong_inst<int*>; // expected-note {{in instantiation of static data member 'non_const_init::B::wrong_inst<int *>' requested here}}
100  template const int B::wrong_inst<const int*>; // expected-error {{undefined}}
101  template<typename T> T B::wrong_inst_fixed = T(100);
102  template int B::wrong_inst_fixed<int>;
103
104  class C {
105    template<typename T> static CONST T right_inst = T(10); // expected-note {{here}}
106    template<typename T> static CONST T right_inst<T*> = T(100); // expected-note {{here}}
107  };
108  template CONST int C::right_inst<int>; // expected-error {{undefined variable template}}
109  template CONST int C::right_inst<int*>; // expected-error {{undefined variable template}}
110
111  namespace pointers {
112
113    struct C0 {
114      template<typename U> static U Data;
115      template<typename U> static CONST U Data<U*> = U(); // expected-note {{here}}
116
117      template<typename U> static U Data2;
118      template<typename U> static CONST U Data2<U*> = U();
119    };
120    const int c0_test = C0::Data<int*>;
121    static_assert(c0_test == 0, "");
122    template const int C0::Data<int*>; // expected-error {{undefined}}
123
124    template<typename U> const U C0::Data2<U*>;
125    template const int C0::Data2<int*>;
126
127    struct C1a {
128      template<typename U> static U Data;
129      template<typename U> static U* Data<U*>;   // Okay, with out-of-line definition
130    };
131    template<typename T> T* C1a::Data<T*> = new T();
132    template int* C1a::Data<int*>;
133
134    struct C1b {
135      template<typename U> static U Data;
136      template<typename U> static CONST U* Data<U*>;   // Okay, with out-of-line definition
137    };
138    template<typename T> CONST T* C1b::Data<T*> = (T*)(0);
139    template CONST int* C1b::Data<int*>;
140
141    struct C2a {
142      template<typename U> static int Data;
143      template<typename U> static U* Data<U*> = new U();   // expected-error {{non-const static data member must be initialized out of line}}
144    };
145    template int* C2a::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int *>' requested here}}
146
147    struct C2b {
148      template<typename U> static int Data;
149      template<typename U> static U *const Data<U*> = (U*)(0); // expected-error {{static data member of type 'int *const'}}
150    };
151    template<typename U> U *const C2b::Data<U*>;
152    template int *const C2b::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int *>' requested here}}
153  }
154}
155
156#ifndef PRECXX11
157namespace constexpred {
158  class A {
159    template<typename T> constexpr T wrong;           // expected-error {{member 'wrong' declared as a template}} \
160                                                      // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
161    template<typename T> constexpr T wrong_init = 5;      // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
162    template<typename T, typename T0> static constexpr T right = T(100);
163    template<typename T> static constexpr T right<T,int> = 5;
164    template<typename T> constexpr int right<int,T>;  // expected-error {{member 'right' declared as a template}} \
165                                                      // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
166    template<typename T> constexpr float right<float,T> = 5;  // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
167    template<> static constexpr int right<int,int> = 7;       // expected-error {{explicit specialization of 'right' in class scope}}
168    template<> static constexpr float right<float,int>;       // expected-error {{explicit specialization of 'right' in class scope}}
169    template static constexpr int right<int,int>;     // expected-error {{template specialization requires 'template<>'}} \
170                                                  // expected-error {{explicit specialization of 'right' in class scope}}
171  };
172}
173#endif
174
175namespace in_class_template {
176
177  template<typename T>
178  class D0 {
179    template<typename U> static U Data; // expected-note {{here}}
180    template<typename U> static CONST U Data<U*> = U();
181  };
182  template CONST int D0<float>::Data<int*>;
183  template int D0<float>::Data<int>; // expected-error {{undefined}}
184  template<typename T> template<typename U> const U D0<T>::Data<U*>;
185
186  template<typename T>
187  class D1 {
188    template<typename U> static U Data;
189    template<typename U> static U* Data<U*>;
190  };
191  template<typename T>
192  template<typename U> U* D1<T>::Data<U*> = (U*)(0);
193  template int* D1<float>::Data<int*>; // expected-note {{previous}}
194  template int* D1<float>::Data<int*>; // expected-error {{duplicate explicit instantiation}}
195
196  template<typename T>
197  class D2 {
198    template<typename U> static U Data;
199    template<typename U> static U* Data<U*>;
200  };
201  template<>
202  template<typename U> U* D2<float>::Data<U*> = (U*)(0) + 1;
203  template int* D2<float>::Data<int*>; // expected-note {{previous}}
204  template int* D2<float>::Data<int*>; // expected-error {{duplicate explicit instantiation}}
205
206  template<typename T>
207  struct D3 {
208    template<typename U> static CONST U Data = U(100); // expected-note {{here}}
209  };
210  static_assert(D3<float>::Data<int> == 100, "");
211  template const char D3<float>::Data<char>; // expected-error {{undefined}}
212
213  namespace bug_files {
214    template<typename T>
215    class D0a {
216      template<typename U> static U Data;
217      template<typename U> static CONST U Data<U*> = U(10);  // expected-note {{previous definition is here}}
218    };
219    template<>
220    template<typename U> U D0a<float>::Data<U*> = U(100);  // expected-error {{redefinition of 'Data'}}
221
222    // FIXME: We should accept this, and the corresponding case for class
223    // templates.
224    //
225    // [temp.class.spec.mfunc]/2: If the primary member template is explicitly
226    // specialized for a given specialization of the enclosing class template,
227    // the partial specializations of the member template are ignored
228    template<typename T>
229    class D1 {
230      template<typename U> static U Data;
231      template<typename U> static CONST U Data<U*> = U(10);  // expected-note {{previous definition is here}}
232    };
233    template<>
234    template<typename U> U D1<float>::Data = U(10);
235    template<>
236    template<typename U> U D1<float>::Data<U*> = U(100);  // expected-error{{redefinition of 'Data'}}
237  }
238
239  namespace definition_after_outer_instantiation {
240    template<typename A> struct S {
241      template<typename B> static const int V1;
242      template<typename B> static const int V2;
243    };
244    template struct S<int>;
245    template<typename A> template<typename B> const int S<A>::V1 = 123;
246    template<typename A> template<typename B> const int S<A>::V2<B*> = 456;
247
248    static_assert(S<int>::V1<int> == 123, "");
249
250    // FIXME: The first and third case below possibly should be accepted. We're
251    // not picking up partial specializations added after the primary template
252    // is instantiated. This is kind of implied by [temp.class.spec.mfunc]/2,
253    // and matches our behavior for member class templates, but it's not clear
254    // that this is intentional. See PR17294 and core-24030.
255    static_assert(S<int>::V2<int*> == 456, ""); // FIXME expected-error {{}}
256    static_assert(S<int>::V2<int&> == 789, ""); // expected-error {{}}
257
258    template<typename A> template<typename B> const int S<A>::V2<B&> = 789;
259    static_assert(S<int>::V2<int&> == 789, ""); // FIXME expected-error {{}}
260
261    // All is OK if the partial specialization is declared before the implicit
262    // instantiation of the class template specialization.
263    static_assert(S<char>::V1<int> == 123, "");
264    static_assert(S<char>::V2<int*> == 456, "");
265    static_assert(S<char>::V2<int&> == 789, "");
266  }
267
268  namespace incomplete_array {
269    template<typename T> extern T var[];
270    template<typename T> T var[] = { 1, 2, 3 };
271    template<> char var<char>[] = "hello";
272    template<typename T> char var<T*>[] = "pointer";
273
274    static_assert(sizeof(var<int>) == 12, "");
275    static_assert(sizeof(var<char>) == 6, "");
276    static_assert(sizeof(var<void*>) == 8, "");
277
278    template<typename...> struct tuple;
279
280    template<typename T> struct A {
281      template<typename U> static T x[];
282      template<typename U> static T y[];
283
284      template<typename...U> static T y<tuple<U...> >[];
285    };
286
287    int *use_before_definition = A<int>::x<char>;
288    template<typename T> template<typename U> T A<T>::x[sizeof(U)];
289    static_assert(sizeof(A<int>::x<char>) == 4, "");
290
291    template<typename T> template<typename...U> T A<T>::y<tuple<U...> >[] = { U()... };
292    static_assert(sizeof(A<int>::y<tuple<char, char, char> >) == 12, "");
293  }
294
295  namespace bad_reference {
296    struct S {
297      template<typename T> static int A; // expected-note 4{{here}}
298    };
299
300    template<typename T> void f() {
301      typename T::template A<int> a; // expected-error {{template name refers to non-type template 'S::A'}}
302    }
303    template<typename T> void g() {
304      T::template A<int>::B = 0; // expected-error {{template name refers to non-type template 'S::A'}}
305    }
306    template<typename T> void h() {
307      class T::template A<int> c; // expected-error {{template name refers to non-type template 'S::A'}}
308    }
309
310    template<typename T>
311    struct X : T::template A<int> {}; // expected-error {{template name refers to non-type template 'S::A'}}
312
313    template void f<S>(); // expected-note {{in instantiation of}}
314    template void g<S>(); // expected-note {{in instantiation of}}
315    template void h<S>(); // expected-note {{in instantiation of}}
316    template struct X<S>; // expected-note {{in instantiation of}}
317  }
318}
319
320namespace in_nested_classes {
321  // TODO:
322}
323
324