cxx1y-variable-templates_in_class.cpp revision 58ee425b11e178c652fa6ff4c1c924fe9b98801e
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 definition is here}}
43    template<typename T> static CONST T right<T,int> = T(5);          // expected-note {{previous definition is here}}
44  };
45  template<typename T, typename T0> CONST T B2::right = T(100);   // expected-error {{redefinition of 'right'}}
46  template<typename T> CONST T B2::right<T,int> = T(5);           // expected-error {{redefinition of 'right'}}
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 right;
57    template<typename T> static CONST T right<T,int>;
58    template<typename T, typename T0> static CONST T right_def = T(100);
59    template<typename T> static CONST T right_def<T,int>;   // expected-note {{explicit instantiation refers here}}
60  };
61  template<typename T, typename T0> CONST T B4::right;
62  template<typename T> CONST T B4::right<T,int>; // expected-note {{explicit instantiation refers here}}
63  template CONST int B4::right<int,int>;  // expected-error {{explicit instantiation of undefined static data member template 'right' of class}}
64  template CONST int B4::right_def<int,int>;  // expected-error {{explicit instantiation of undefined static data member template 'right_def' of class}}
65}
66
67namespace non_const_init {
68  class A {
69    template<typename T> static T wrong_inst = T(10); // expected-error {{non-const static data member must be initialized out of line}}
70    template<typename T> static T wrong_inst_fixed;
71  };
72  template int A::wrong_inst<int>;  // expected-note {{in instantiation of static data member 'non_const_init::A::wrong_inst<int>' requested here}}
73  template<typename T> T A::wrong_inst_fixed = T(10);
74  template int A::wrong_inst_fixed<int>;
75
76  class B {
77    template<typename T> static T wrong_inst;
78    template<typename T> static T wrong_inst<T*> = T(100);  // expected-error {{non-const static data member must be initialized out of line}}
79
80    template<typename T> static T wrong_inst_fixed;
81    template<typename T> static T wrong_inst_fixed<T*>;
82  };
83  template int B::wrong_inst<int*>;  // expected-note {{in instantiation of static data member 'non_const_init::B::wrong_inst<int *>' requested here}}
84  template<typename T> T B::wrong_inst_fixed = T(100);
85  template int B::wrong_inst_fixed<int>;
86
87  class C {
88    template<typename T> static CONST T right_inst = T(10);
89    template<typename T> static CONST T right_inst<T*> = T(100);
90  };
91  template CONST int C::right_inst<int>;
92  template CONST int C::right_inst<int*>;
93
94  namespace pointers {
95
96    struct C0 {
97      template<typename U> static U Data;
98      template<typename U> static CONST U Data<U*> = U();   // Okay
99    };
100    template CONST int C0::Data<int*>;
101
102    struct C1a {
103      template<typename U> static U Data;
104      template<typename U> static U* Data<U>;   // Okay, with out-of-line definition
105    };
106    template<typename T> T* C1a::Data<T> = new T();
107    template int* C1a::Data<int>;
108
109    struct C1b {
110      template<typename U> static U Data;
111      template<typename U> static CONST U* Data<U>;   // Okay, with out-of-line definition
112    };
113    template<typename T> CONST T* C1b::Data<T> = (T*)(0);
114    template CONST int* C1b::Data<int>;
115
116    struct C2a {
117      template<typename U> static U Data;
118      template<typename U> static U* Data<U> = new U();   // expected-error {{non-const static data member must be initialized out of line}}
119    };
120    template int* C2a::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int>' requested here}}
121
122    struct C2b {  // FIXME: ?!? Should this be an error? pointer-types are automatically non-const?
123      template<typename U> static U Data;
124      template<typename U> static CONST U* Data<U> = (U*)(0); // expected-error {{non-const static data member must be initialized out of line}}
125    };
126    template CONST int* C2b::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int>' requested here}}
127  }
128}
129
130#ifndef PRECXX11
131namespace constexpred {
132  class A {
133    template<typename T> constexpr T wrong;           // expected-error {{member 'wrong' declared as a template}} \
134                                                      // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
135    template<typename T> constexpr T wrong_init = 5;      // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
136    template<typename T, typename T0> static constexpr T right = T(100);
137    template<typename T> static constexpr T right<T,int> = 5;
138    template<typename T> constexpr int right<int,T>;  // expected-error {{member 'right' declared as a template}} \
139                                                      // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
140    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?}}
141    template<> static constexpr int right<int,int> = 7;       // expected-error {{explicit specialization of 'right' in class scope}}
142    template<> static constexpr float right<float,int>;       // expected-error {{explicit specialization of 'right' in class scope}}
143    template static constexpr int right<int,int>;     // expected-error {{template specialization requires 'template<>'}} \
144                                                  // expected-error {{explicit specialization of 'right' in class scope}}
145  };
146}
147#endif
148
149struct matrix_constants {
150  // TODO: (?)
151};
152
153namespace in_class_template {
154
155  template<typename T>
156  class D0 {
157    template<typename U> static U Data;
158    template<typename U> static CONST U Data<U*> = U();
159  };
160  template CONST int D0<float>::Data<int*>;
161
162  template<typename T>
163  class D1 {
164    template<typename U> static U Data;
165    template<typename U> static U* Data<U*>;
166  };
167  template<typename T>
168  template<typename U> U* D1<T>::Data<U*> = (U*)(0);
169  template int* D1<float>::Data<int*>;
170
171  template<typename T>
172  class D2 {
173    template<typename U> static U Data;
174    template<typename U> static U* Data<U*>;
175  };
176  template<>
177  template<typename U> U* D2<float>::Data<U*> = (U*)(0) + 1;
178  template int* D1<float>::Data<int*>;
179
180  template<typename T>
181  struct D3 {
182    template<typename U> static CONST U Data = U(100);
183  };
184  template CONST int D3<float>::Data<int>;
185  static_assert(D3<float>::Data<int> == 100, "");
186
187  namespace bug_files {
188    // FIXME: A bug has been filed addressing an issue similar to these.
189    // No error diagnosis should be produced, because an
190    // explicit specialization of a member templates of class
191    // template specialization should not inherit the partial
192    // specializations from the class template specialization.
193
194    template<typename T>
195    class D0 {
196      template<typename U> static U Data;
197      template<typename U> static CONST U Data<U*> = U(10);  // expected-note {{previous definition is here}}
198    };
199    template<>
200    template<typename U> U D0<float>::Data<U*> = U(100);  // expected-error{{redefinition of 'Data'}}
201
202    template<typename T>
203    class D1 {
204      template<typename U> static U Data;
205      template<typename U> static U* Data<U*>;  // expected-note {{previous definition is here}}
206    };
207    template<typename T>
208    template<typename U> U* D1<T>::Data<U*> = (U*)(0);
209    template<>
210    template<typename U> U* D1<float>::Data<U*> = (U*)(0) + 1;  // expected-error{{redefinition of 'Data'}}
211  }
212
213  namespace other_bugs {
214    // FIXME: This fails to properly initialize the variable 'k'.
215
216    template<typename A> struct S {
217      template<typename B> static int V;
218      template<typename B> static int V0;
219    };
220    template struct S<int>;
221    template<typename A> template<typename B> int S<A>::V0 = 123;
222    template<typename A> template<typename B> int S<A>::V<B> = 123;
223    int k = S<int>::V<void>;
224  }
225
226  namespace incomplete_array {
227    template<typename T> extern T var[];
228    template<typename T> T var[] = { 1, 2, 3 };
229    template<> char var<char>[] = "hello";
230    template<typename T> char var<T*>[] = "pointer";
231
232    static_assert(sizeof(var<int>) == 12, "");
233    static_assert(sizeof(var<char>) == 6, "");
234    static_assert(sizeof(var<void*>) == 8, "");
235
236    template<typename...> struct tuple;
237
238    template<typename T> struct A {
239      template<typename U> static T x[];
240      template<typename U> static T y[];
241
242      template<typename...U> static T y<tuple<U...> >[];
243    };
244
245    // FIXME: These cases should be accepted.
246    int *use_before_definition = A<int>::x<char>;
247    template<typename T> template<typename U> T A<T>::x<U>[sizeof(U)];
248    static_assert(sizeof(A<int>::x<char>) == 1, ""); // expected-error {{incomplete}}
249
250    template<typename T> template<typename...U> T A<T>::y<tuple<U...> >[] = { U()... };
251    static_assert(sizeof(A<int>::y<tuple<char, char, char> >) == 12, ""); // expected-error {{incomplete}}
252  }
253}
254
255namespace in_nested_classes {
256  // TODO:
257}
258
259