544 lines · cpp
1// RUN: %clang_cc1 -std=c++98 -verify -fsyntax-only -Wno-unused-value -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX112// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-unused-value -Wno-c++1y-extensions %s3// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wno-unused-value %s4// RUN: %clang_cc1 -std=c++2c -verify -fsyntax-only -Wno-unused-value %s5 6 7#ifdef PRECXX118 #define CONST const9#else10 #define CONST constexpr11#endif12 13template<typename T>14T pi = T(3.1415926535897932385); // expected-note 2{{declared here}}15 16template<typename T>17CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}18 19template<typename T> extern CONST T vc;20#ifndef PRECXX1121// expected-error@-2 {{constexpr variable declaration must be a definition}}22#endif23 24namespace use_in_top_level_funcs {25 26 void good() {27 int ipi = pi<int>;28 int icpi = cpi<int>;29 double dpi = pi<double>;30 double dcpi = cpi<double>;31 }32 33 void no_deduce() {34 // template arguments are not deduced for uses of variable templates.35 int ipi = pi; // expected-error {{use of variable template 'pi' requires template arguments}}36 int icpi = cpi; // expected-error {{use of variable template 'cpi' requires template arguments}}37 }38 39 template<typename T>40 T circular_area(T r) {41 return pi<T> * r * r;42 }43 44 template<typename T>45 CONST T const_circular_area(T r) {46 return cpi<T> * r * r;47 }48 49 double use_circular_area(double r) {50 CONST float t = const_circular_area(2.0) - 12;51#ifndef PRECXX1152 static_assert(const_circular_area(2) == 12, "");53 CONST int test = (t > 0) && (t < 1);54 static_assert(test, "");55#endif56 return circular_area(r);57 }58}59 60namespace shadow {61 void foo() {62 int ipi0 = pi<int>;63 int pi; // expected-note {{found}}64 int a = pi;65 int ipi = pi<int>; // expected-error {{'pi' does not name a template but is followed by template arguments; did you mean '::pi'?}}66 }67}68 69namespace odr_tmpl {70 namespace pv_cvt {71 int v; // expected-note {{previous definition is here}}72 template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}}73 }74 namespace pvt_cv {75 template<typename T> T v; // expected-note {{previous definition is here}}76 int v; // expected-error {{redefinition of 'v' as different kind of symbol}}77 }78 namespace pvt_cvt {79 template<typename T> T v0; // expected-note {{previous definition is here}}80 template<typename T> T v0; // expected-error {{redefinition of 'v0'}}81 82 template<typename T> T v; // expected-note {{previous definition is here}}83 template<typename T> int v; // expected-error {{redefinition of 'v'}}84 85 template<typename T> extern int v1; // expected-note {{previous template declaration is here}}86 template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}}87 }88 namespace pvt_use {89 template<typename T> T v;90 v = 10; // expected-error {{a type specifier is required for all declarations}}91 }92 93 namespace pvt_diff_params {94 template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}}95 template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}}96 template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}}97 }98 99 namespace pvt_extern {100 template<typename T> T v = T();101 template<typename T> extern T v; // redeclaration is allowed \102 // expected-note {{previous declaration is here}}103 template<typename T> extern int v; // expected-error {{redeclaration of 'v' with a different type: 'int' vs 'T'}}104 105#ifndef PRECXX11106 template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with deduced type 'auto' requires an initializer}}107#endif108 109 template<typename T> T var = T(); // expected-note {{previous definition is here}}110 extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}}111 }112 113#ifndef PRECXX11114 namespace pvt_auto {115 template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with deduced type 'auto' requires an initializer}}116 template<typename T> auto v1 = T(); // expected-note {{previous definition is here}}117 template<typename T> int v1; // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}}118 template<typename T> auto v2 = T(); // expected-note {{previous definition is here}}119 template<typename T> T v2; // expected-error {{redefinition of 'v2'}}120 template<typename T> auto v3 = T(); // expected-note {{previous definition is here}}121 template<typename T> extern T v3; // expected-error {{redeclaration of 'v3' with a different type: 'T' vs 'auto'}}122 template<typename T> auto v4 = T();123 template<typename T> extern auto v4; // expected-error {{declaration of variable 'v4' with deduced type 'auto' requires an initializer}}124 }125#endif126 127}128 129namespace explicit_instantiation {130 template<typename T>131 T pi0a = T(3.1415926535897932385); // expected-note {{variable template 'pi0a' declared here}}132 template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}}133 134 template<typename T>135 T pi0b = T(3.1415926535897932385); // expected-note {{variable template 'pi0b' declared here}}136 template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}}137 138 template<typename T>139 T pi0c = T(3.1415926535897932385); // expected-note {{variable template 'pi0c' declared here}}140 template int pi0c<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}}141 142 template<typename T>143 T pi0 = T(3.1415926535897932385);144 template int pi0<int>; // expected-note {{previous explicit instantiation is here}}145 template int pi0<int>; // expected-error {{duplicate explicit instantiation of 'pi0<int>'}}146 147 template<typename T>148 CONST T pi1a = T(3.1415926535897932385); // expected-note {{variable template 'pi1a' declared here}}149 template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}}150 151 template<typename T>152 CONST T pi1b = T(3.1415926535897932385); // expected-note {{variable template 'pi1b' declared here}}153 template int pi1b<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}}154 155 template<typename T>156 CONST T pi1 = T(3.1415926535897932385);157 template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}}158 template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}}159 160#ifndef PRECXX11161 namespace auto_var {162 template<typename T> auto var0 = T();163 template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}}164 165 template<typename T> auto var = T();166 template int var<int>;167 }168#endif169 170 template<typename=int> int missing_args; // expected-note {{here}}171 template int missing_args; // expected-error {{must specify a template argument list}}172 173 namespace extern_var {174 // TODO:175 }176}177 178namespace explicit_specialization {179 180 namespace good {181 template<typename T1, typename T2>182 CONST int pi2 = 1;183 184 template<typename T>185 CONST int pi2<T,int> = 2;186 187 template<typename T>188 CONST int pi2<int,T> = 3;189 190 template<> CONST int pi2<int,int> = 4;191 192#ifndef PRECXX11193 void foo() {194 static_assert(pi2<int,int> == 4, "");195 static_assert(pi2<float,int> == 2, "");196 static_assert(pi2<int,float> == 3, "");197 static_assert(pi2<int,float> == pi2<int,double>, "");198 static_assert(pi2<float,float> == 1, "");199 static_assert(pi2<float,float> == pi2<float,double>, "");200 }201#endif202 }203 204 namespace ambiguous {205 206 template<typename T1, typename T2>207 CONST int pi2 = 1;208 209 template<typename T>210 CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}}211 212 template<typename T>213 CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}}214 215 void foo() {216 int a = pi2<int,int>; // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}}217 }218 }219 220 namespace type_changes {221 222 template<typename T>223 T pi0 = T(3.1415926535897932385);224 225 template<> float pi0<int> = 10;226 template<> int pi0<const int> = 10;227 228 template<typename T>229 T pi1 = T(3.1415926535897932385);230 template<> CONST int pi1<int> = 10;231 232 template<typename T>233 T pi2 = T(3.1415926535897932385);234 template<> int pi2<const int> = 10;235 236 template<typename T>237 CONST T pi4 = T(3.1415926535897932385);238 template<> int pi4<int> = 10;239 }240 241 namespace redefinition {242 template<typename T>243 T pi0 = T(3.1415926535897932385);244 245 template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}}246#ifndef PRECXX11247// expected-note@-2 {{previous definition is here}}248#endif249 template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}}250 template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}}251 template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}}252#ifndef PRECXX11253 template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}}254#endif255 256 257 template<typename T>258 CONST T pi1 = T(3.1415926535897932385);259 260 template<> CONST int pi1<int> = 10; // expected-note {{previous definition is here}}261 template<> CONST int pi1<int> = 10; // expected-error {{redefinition of 'pi1<int>'}}262 }263 264 namespace before_instantiation {265 template<typename T>266 T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}}267 268 template<> int pi0<int> = 10; // expected-note 2{{previous template specialization is here}}269 template int pi0<int>; // expected-warning {{has no effect}}270 template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} expected-warning {{has no effect}}271 272 template<typename T1, typename T2>273 CONST int pi2 = 1;274 275 template<typename T> CONST int pi2<T,int> = 2;276 template CONST int pi2<int,int>;277 }278 namespace after_instantiation {279 template<typename T>280 T pi0 = T(3.1415926535897932385);281 282 template int pi0<int>; // expected-note 2{{explicit instantiation first required here}}283 template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}}284 template<> float pi0<int>; // expected-error {{explicit specialization of 'pi0' after instantiation}}285 286 template<typename T1, typename T2>287 CONST int pi2 = 1;288 289 template CONST int pi2<int,int>;290 template<typename T> CONST int pi2<T,int> = 2;291 }292 293#ifndef PRECXX11294 namespace auto_var {295 template<typename T, typename> auto var0 = T();296 template<typename T> auto var0<T,int> = T();297 template<> auto var0<int,int> = 7;298 299 template<typename T, typename> auto var = T();300 template<typename T> T var<T,int> = T(5);301 template<> int var<int,int> = 7;302 303 void foo() {304 int i0 = var0<int,int>;305 int b = var<int,int>;306 }307 }308#endif309 310 namespace extern_var {311 // TODO:312 }313 314 namespace diff_type {315 // TODO:316 template<typename T> T* var = new T();317#ifndef PRECXX11318 template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}}319 template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}}320#endif321 }322}323 324namespace narrowing {325 template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}}326#ifndef PRECXX11327 // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\328 // expected-note@-2 {{insert an explicit cast to silence this issue}}329#endif330 int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}}331}332 333namespace use_in_structs {334 // TODO:335}336 337namespace attributes {338 // TODO:339}340 341#ifndef PRECXX11342namespace arrays {343 template<typename T>344 T* arr = new T[10]{T(10), T(23)};345 346 float f = 10.5;347 template<> float* arr<float> = &f;348 349 void bar() {350 int *iarr = arr<int>;351 iarr[0] = 1;352 iarr[2] = 3;353 iarr[6] = -2;354 355 float ff = *arr<float>;356 float nof = arr<float>[3]; // No bounds-check in C++357 }358}359#endif360 361namespace nested {362 363 namespace n0a {364 template<typename T>365 T pi0a = T(3.1415926535897932385);366 }367 368 using namespace n0a;369 int i0a = pi0a<int>;370 371 template float pi0a<float>;372 float f0a = pi0a<float>;373 374 template<> double pi0a<double> = 5.2;375 double d0a = pi0a<double>;376 377 namespace n0b {378 template<typename T>379 T pi0b = T(3.1415926535897932385);380 }381 382 int i0b = n0b::pi0b<int>;383 384 template float n0b::pi0b<float>;385 float f0b = n0b::pi0b<float>;386 387 template<> double n0b::pi0b<double> = 5.2;388 double d0b = n0b::pi0b<double>;389 390 namespace n1 {391 template<typename T>392 T pi1a = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}393#ifndef PRECXX11394// expected-note@-2 {{explicit instantiation refers here}}395#endif396 397 template<typename T>398 T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}399#ifndef PRECXX11400// expected-note@-2 {{explicit instantiation refers here}}401#endif402 }403 404 namespace use_n1a {405 using namespace n1;406 int i1 = pi1a<int>;407 408 template float pi1a<float>;409#ifndef PRECXX11410// expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}}411#endif412 float f1 = pi1a<float>;413 414 template<> double pi1a<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}415 double d1 = pi1a<double>;416 }417 418 namespace use_n1b {419 int i1 = n1::pi1b<int>;420 421 template float n1::pi1b<float>;422#ifndef PRECXX11423// expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}}424#endif425 float f1 = n1::pi1b<float>;426 427 template<> double n1::pi1b<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}428 double d1 = n1::pi1b<double>;429 }430}431 432namespace nested_name {433 template<typename T> int a; // expected-note {{variable template 'a' declared here}}434 a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}}435 436 class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}}437 enum a<int> {}; // expected-error {{expected identifier or '{'}}438}439 440namespace PR18530 {441 template<typename T> int a;442 int a<int>; // expected-error {{requires 'template<>'}}443}444 445namespace PR19152 {446#ifndef PRECXX11447 template<typename T> const auto x = 1;448 static_assert(x<int> == 1, "");449#endif450}451 452namespace PR19169 {453 template <typename T> int* f();454 template <typename T> void f();455 template<> int f<double>; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}}456 457 template <typename T> void g();458 template<> int g<double>; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}}459}460 461#ifndef PRECXX11462template <typename... Args> struct Variadic_t { };463template <typename... Args> Variadic_t<Args...> Variadic;464auto variadic1 = Variadic<>;465auto variadic2 = Variadic<int, int>;466#endif467 468namespace VexingParse {469 template <typename> int var; // expected-note {{declared here}}470 int x(var); // expected-error {{use of variable template 'var' requires template arguments}}471}472 473#ifndef PRECXX11474 475namespace GH79750 {476 477enum class Values { A };478 479template<typename E>480constexpr Values values[] = {E::A};481 482constexpr auto r = values<Values>[0] == Values::A;483 484}485 486namespace GH113956 {487 488template <class T, T... VALUES>489struct C {490 static constexpr T VALUEARRAY[] = {VALUES...};491};492 493static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[3] == 3, "");494static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[0] == 0, "");495 496}497 498namespace appear_in_its_own_init {499template <class T>500auto GH51347 = GH51347<T>; // expected-error {{variable template 'GH51347' declared with deduced type 'auto' cannot appear in its own initializer}}501 502template <class T, class... Ts>503auto a = [] {504 using U = T;505 a<U, Ts...>; // expected-error {{variable template 'a' declared with deduced type 'auto' cannot appear in its own initializer}}506};507 508template <int...> int b;509template <int I>510auto b<I, I * 2, 5> = b<I, I * 2, 5l>; // expected-error {{variable template partial specialization 'b<I, I * 2, 5>' declared with deduced type 'auto' cannot appear in its own initializer}}511template <> auto b<0, 0, 0> = b<0, 0, 0>; // expected-error {{variable template explicit specialization 'b<0, 0, 0>' declared with deduced type 'auto' cannot appear in its own initializer}}512}513 514#endif515 516#if __cplusplus > 201702L517namespace GH140622 {518template <typename> struct S {};519 520struct Outer {521 template <typename T>522 static constexpr S<T> g;523};524 525template <typename T>526struct OuterTpl {527 static constexpr S<T> f;528 template <typename U>529 static constexpr S<U> g;530};531 532template <typename T>533constexpr S<T> g;534 535void test() {536 constexpr auto x = 42;537 x, g<int>,538 Outer::g<int>,539 OuterTpl<int>::f,540 OuterTpl<int>::g<int>;541}542}543#endif544