465 lines · cpp
1// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -DPRECXX112// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s3// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1y -verify -fsyntax-only %s -DCPP1Y4 5#define CONST const6 7#ifdef PRECXX118#define static_assert _Static_assert9#endif10 11class 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 PRECXX1119 // expected-warning@-2 {{in-class initializer for static data member of type 'const float' is a GNU extension}}20#else21 // expected-error@-4 {{in-class initializer for static data member of type 'const float' requires 'constexpr' specifier}}22 // expected-note@-5 {{add 'constexpr'}}23#endif24 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 29namespace 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 77namespace 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 undefined102 // 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 definition135 };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 definition142 };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 PRECXX11162namespace 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#endif178 179namespace 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 class227 // templates.228 //229 // [temp.class.spec.mfunc]/2: If the primary member template is explicitly230 // specialized for a given specialization of the enclosing class template,231 // the partial specializations of the member template are ignored232 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're255 // not picking up partial specializations added after the primary template256 // 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 clear258 // 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 implicit266 // 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 'in_class_template::bad_reference::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 'in_class_template::bad_reference::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 'in_class_template::bad_reference::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 'in_class_template::bad_reference::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 324namespace in_nested_classes {325 // TODO:326}327 328namespace bitfield {329struct S {330 template <int I>331 static int f : I; // expected-error {{static member 'f' cannot be a bit-field}}332};333}334 335namespace 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}345namespace member_access_is_ok {346#ifdef CPP1Y347 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 ns1353#endif // CPP1Y354 355namespace 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 ns2363} // end ns member_access_is_ok364 365#ifdef CPP1Y366namespace PR24473 {367struct Value368{369 template<class T>370 static constexpr T value = 0;371};372 373template<typename TValue>374struct Something375{376 void foo() {377 static_assert(TValue::template value<int> == 0, ""); // error378 }379};380 381int main() {382 Something<Value>{}.foo();383 return 0;384}385 386} // end ns PR24473387#endif // CPP1Y388 389namespace 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 'dependent_static_var_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#ifdef CPP1Y417 namespace GH55872 {418 struct s {419 template<typename T>420 static CONST auto f = [] { return T::template g<s>; };421 // expected-note@-1 {{in instantiation of static data member 'dependent_static_var_template::GH55872::t::g' requested here}}422 // expected-note@-2 {{while substituting into a lambda expression here}}423 };424 425 struct t {426 template<typename T>427 static CONST auto g = [] { return T::template f<t>; };428 // expected-error@-1 {{the type of variable template specialization 'f<dependent_static_var_template::GH55872::t>' declared with deduced type 'const auto' depends on itself}}429 // expected-note@-2 {{while substituting into a lambda expression here}}430 };431 432 void test() { s::f<t>()(); } // expected-note {{in instantiation of static data member 'dependent_static_var_template::GH55872::s::f' requested here}}433 }434#endif435}436 437#ifndef PRECXX11438namespace template_vars_in_template {439template <int> struct TakesInt {};440 441template <class T2>442struct S {443 template <class T1>444 static constexpr int v = 42;445 446 template <class T>447 void mf() {448 constexpr int val = v<T>;449 }450 451 void mf2() {452 constexpr int val = v<char>;453 TakesInt<val> ti;454 (void)ti.x; // expected-error{{no member named 'x' in 'template_vars_in_template::TakesInt<42>'}}455 }456};457 458void useit() {459 S<int> x;460 x.mf<double>();461 x.mf2(); // expected-note{{in instantiation of member function 'template_vars_in_template::S<int>::mf2' requested here}}462}463}464#endif465