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 11 class 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 24 namespace 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 72 namespace 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 157 namespace 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 175 namespace 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 320 namespace in_nested_classes { 321 // TODO: 322 } 323 324