| 1 | // RUN: %clang_cc1 -std=c++98 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -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 | #ifdef PRECXX11 |
| 6 | #define CONST const |
| 7 | #else |
| 8 | #define CONST constexpr |
| 9 | #endif |
| 10 | |
| 11 | template<typename T> |
| 12 | T pi = T(3.1415926535897932385); // expected-note 2{{declared here}} |
| 13 | |
| 14 | template<typename T> |
| 15 | CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}} |
| 16 | |
| 17 | template<typename T> extern CONST T vc; |
| 18 | #ifndef PRECXX11 |
| 19 | // expected-error@-2 {{constexpr variable declaration must be a definition}} |
| 20 | #endif |
| 21 | |
| 22 | namespace use_in_top_level_funcs { |
| 23 | |
| 24 | void good() { |
| 25 | int ipi = pi<int>; |
| 26 | int icpi = cpi<int>; |
| 27 | double dpi = pi<double>; |
| 28 | double dcpi = cpi<double>; |
| 29 | } |
| 30 | |
| 31 | void no_deduce() { |
| 32 | // template arguments are not deduced for uses of variable templates. |
| 33 | int ipi = pi; // expected-error {{use of variable template 'pi' requires template arguments}} |
| 34 | int icpi = cpi; // expected-error {{use of variable template 'cpi' requires template arguments}} |
| 35 | } |
| 36 | |
| 37 | template<typename T> |
| 38 | T circular_area(T r) { |
| 39 | return pi<T> * r * r; |
| 40 | } |
| 41 | |
| 42 | template<typename T> |
| 43 | CONST T const_circular_area(T r) { |
| 44 | return cpi<T> * r * r; |
| 45 | } |
| 46 | |
| 47 | double use_circular_area(double r) { |
| 48 | CONST float t = const_circular_area(2.0) - 12; |
| 49 | #ifndef PRECXX11 |
| 50 | static_assert(const_circular_area(2) == 12, ""); |
| 51 | CONST int test = (t > 0) && (t < 1); |
| 52 | static_assert(test, ""); |
| 53 | #endif |
| 54 | return circular_area(r); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | namespace shadow { |
| 59 | void foo() { |
| 60 | int ipi0 = pi<int>; |
| 61 | int pi; // expected-note {{found}} |
| 62 | int a = pi; |
| 63 | int ipi = pi<int>; // expected-error {{'pi' does not name a template but is followed by template arguments; did you mean '::pi'?}} |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | namespace odr_tmpl { |
| 68 | namespace pv_cvt { |
| 69 | int v; // expected-note {{previous definition is here}} |
| 70 | template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}} |
| 71 | } |
| 72 | namespace pvt_cv { |
| 73 | template<typename T> T v; // expected-note {{previous definition is here}} |
| 74 | int v; // expected-error {{redefinition of 'v' as different kind of symbol}} |
| 75 | } |
| 76 | namespace pvt_cvt { |
| 77 | template<typename T> T v0; // expected-note {{previous definition is here}} |
| 78 | template<typename T> T v0; // expected-error {{redefinition of 'v0'}} |
| 79 | |
| 80 | template<typename T> T v; // expected-note {{previous definition is here}} |
| 81 | template<typename T> int v; // expected-error {{redefinition of 'v'}} |
| 82 | |
| 83 | template<typename T> extern int v1; // expected-note {{previous template declaration is here}} |
| 84 | template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}} |
| 85 | } |
| 86 | namespace pvt_use { |
| 87 | template<typename T> T v; |
| 88 | v = 10; // expected-error {{C++ requires a type specifier for all declarations}} |
| 89 | } |
| 90 | |
| 91 | namespace pvt_diff_params { |
| 92 | template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}} |
| 93 | template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} |
| 94 | template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}} |
| 95 | } |
| 96 | |
| 97 | namespace pvt_extern { |
| 98 | template<typename T> T v = T(); |
| 99 | template<typename T> extern T v; // redeclaration is allowed \ |
| 100 | // expected-note {{previous declaration is here}} |
| 101 | template<typename T> extern int v; // expected-error {{redeclaration of 'v' with a different type: 'int' vs 'T'}} |
| 102 | |
| 103 | #ifndef PRECXX11 |
| 104 | template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with deduced type 'auto' requires an initializer}} |
| 105 | #endif |
| 106 | |
| 107 | template<typename T> T var = T(); // expected-note {{previous definition is here}} |
| 108 | extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}} |
| 109 | } |
| 110 | |
| 111 | #ifndef PRECXX11 |
| 112 | namespace pvt_auto { |
| 113 | template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with deduced type 'auto' requires an initializer}} |
| 114 | template<typename T> auto v1 = T(); // expected-note {{previous definition is here}} |
| 115 | template<typename T> int v1; // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}} |
| 116 | template<typename T> auto v2 = T(); // expected-note {{previous definition is here}} |
| 117 | template<typename T> T v2; // expected-error {{redefinition of 'v2'}} |
| 118 | template<typename T> auto v3 = T(); // expected-note {{previous definition is here}} |
| 119 | template<typename T> extern T v3; // expected-error {{redeclaration of 'v3' with a different type: 'T' vs 'auto'}} |
| 120 | template<typename T> auto v4 = T(); |
| 121 | template<typename T> extern auto v4; // expected-error {{declaration of variable 'v4' with deduced type 'auto' requires an initializer}} |
| 122 | } |
| 123 | #endif |
| 124 | |
| 125 | } |
| 126 | |
| 127 | namespace explicit_instantiation { |
| 128 | template<typename T> |
| 129 | T pi0a = T(3.1415926535897932385); // expected-note {{variable template 'pi0a' declared here}} |
| 130 | template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}} |
| 131 | |
| 132 | template<typename T> |
| 133 | T pi0b = T(3.1415926535897932385); // expected-note {{variable template 'pi0b' declared here}} |
| 134 | template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}} |
| 135 | |
| 136 | template<typename T> |
| 137 | T pi0c = T(3.1415926535897932385); // expected-note {{variable template 'pi0c' declared here}} |
| 138 | template int pi0c<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}} |
| 139 | |
| 140 | template<typename T> |
| 141 | T pi0 = T(3.1415926535897932385); |
| 142 | template int pi0<int>; // expected-note {{previous explicit instantiation is here}} |
| 143 | template int pi0<int>; // expected-error {{duplicate explicit instantiation of 'pi0<int>'}} |
| 144 | |
| 145 | template<typename T> |
| 146 | CONST T pi1a = T(3.1415926535897932385); // expected-note {{variable template 'pi1a' declared here}} |
| 147 | template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}} |
| 148 | |
| 149 | template<typename T> |
| 150 | CONST T pi1b = T(3.1415926535897932385); // expected-note {{variable template 'pi1b' declared here}} |
| 151 | template int pi1b<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}} |
| 152 | |
| 153 | template<typename T> |
| 154 | CONST T pi1 = T(3.1415926535897932385); |
| 155 | template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}} |
| 156 | template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}} |
| 157 | |
| 158 | #ifndef PRECXX11 |
| 159 | namespace auto_var { |
| 160 | template<typename T> auto var0 = T(); |
| 161 | template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}} |
| 162 | |
| 163 | template<typename T> auto var = T(); |
| 164 | template int var<int>; |
| 165 | } |
| 166 | #endif |
| 167 | |
| 168 | template<typename=int> int missing_args; // expected-note {{here}} |
| 169 | template int missing_args; // expected-error {{must specify a template argument list}} |
| 170 | |
| 171 | namespace extern_var { |
| 172 | // TODO: |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | namespace explicit_specialization { |
| 177 | |
| 178 | namespace good { |
| 179 | template<typename T1, typename T2> |
| 180 | CONST int pi2 = 1; |
| 181 | |
| 182 | template<typename T> |
| 183 | CONST int pi2<T,int> = 2; |
| 184 | |
| 185 | template<typename T> |
| 186 | CONST int pi2<int,T> = 3; |
| 187 | |
| 188 | template<> CONST int pi2<int,int> = 4; |
| 189 | |
| 190 | #ifndef PRECXX11 |
| 191 | void foo() { |
| 192 | static_assert(pi2<int,int> == 4, ""); |
| 193 | static_assert(pi2<float,int> == 2, ""); |
| 194 | static_assert(pi2<int,float> == 3, ""); |
| 195 | static_assert(pi2<int,float> == pi2<int,double>, ""); |
| 196 | static_assert(pi2<float,float> == 1, ""); |
| 197 | static_assert(pi2<float,float> == pi2<float,double>, ""); |
| 198 | } |
| 199 | #endif |
| 200 | } |
| 201 | |
| 202 | namespace ambiguous { |
| 203 | |
| 204 | template<typename T1, typename T2> |
| 205 | CONST int pi2 = 1; |
| 206 | |
| 207 | template<typename T> |
| 208 | CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}} |
| 209 | |
| 210 | template<typename T> |
| 211 | CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}} |
| 212 | |
| 213 | void foo() { |
| 214 | int a = pi2<int,int>; // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}} |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | namespace type_changes { |
| 219 | |
| 220 | template<typename T> |
| 221 | T pi0 = T(3.1415926535897932385); |
| 222 | |
| 223 | template<> float pi0<int> = 10; |
| 224 | template<> int pi0<const int> = 10; |
| 225 | |
| 226 | template<typename T> |
| 227 | T pi1 = T(3.1415926535897932385); |
| 228 | template<> CONST int pi1<int> = 10; |
| 229 | |
| 230 | template<typename T> |
| 231 | T pi2 = T(3.1415926535897932385); |
| 232 | template<> int pi2<const int> = 10; |
| 233 | |
| 234 | template<typename T> |
| 235 | CONST T pi4 = T(3.1415926535897932385); |
| 236 | template<> int pi4<int> = 10; |
| 237 | } |
| 238 | |
| 239 | namespace redefinition { |
| 240 | template<typename T> |
| 241 | T pi0 = T(3.1415926535897932385); |
| 242 | |
| 243 | template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}} |
| 244 | #ifndef PRECXX11 |
| 245 | // expected-note@-2 {{previous definition is here}} |
| 246 | #endif |
| 247 | template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} |
| 248 | template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}} |
| 249 | template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}} |
| 250 | #ifndef PRECXX11 |
| 251 | template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} |
| 252 | #endif |
| 253 | |
| 254 | |
| 255 | template<typename T> |
| 256 | CONST T pi1 = T(3.1415926535897932385); |
| 257 | |
| 258 | template<> CONST int pi1<int> = 10; // expected-note {{previous definition is here}} |
| 259 | template<> CONST int pi1<int> = 10; // expected-error {{redefinition of 'pi1<int>'}} |
| 260 | } |
| 261 | |
| 262 | namespace before_instantiation { |
| 263 | template<typename T> |
| 264 | T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}} |
| 265 | |
| 266 | template<> int pi0<int> = 10; // expected-note 2{{previous template specialization is here}} |
| 267 | template int pi0<int>; // expected-warning {{has no effect}} |
| 268 | template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} expected-warning {{has no effect}} |
| 269 | |
| 270 | template<typename T1, typename T2> |
| 271 | CONST int pi2 = 1; |
| 272 | |
| 273 | template<typename T> CONST int pi2<T,int> = 2; |
| 274 | template CONST int pi2<int,int>; |
| 275 | } |
| 276 | namespace after_instantiation { |
| 277 | template<typename T> |
| 278 | T pi0 = T(3.1415926535897932385); |
| 279 | |
| 280 | template int pi0<int>; // expected-note 2{{explicit instantiation first required here}} |
| 281 | template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}} |
| 282 | template<> float pi0<int>; // expected-error {{explicit specialization of 'pi0' after instantiation}} |
| 283 | |
| 284 | template<typename T1, typename T2> |
| 285 | CONST int pi2 = 1; |
| 286 | |
| 287 | template CONST int pi2<int,int>; |
| 288 | template<typename T> CONST int pi2<T,int> = 2; |
| 289 | } |
| 290 | |
| 291 | #ifndef PRECXX11 |
| 292 | namespace auto_var { |
| 293 | template<typename T, typename> auto var0 = T(); |
| 294 | template<typename T> auto var0<T,int> = T(); |
| 295 | template<> auto var0<int,int> = 7; |
| 296 | |
| 297 | template<typename T, typename> auto var = T(); |
| 298 | template<typename T> T var<T,int> = T(5); |
| 299 | template<> int var<int,int> = 7; |
| 300 | |
| 301 | void foo() { |
| 302 | int i0 = var0<int,int>; |
| 303 | int b = var<int,int>; |
| 304 | } |
| 305 | } |
| 306 | #endif |
| 307 | |
| 308 | namespace extern_var { |
| 309 | // TODO: |
| 310 | } |
| 311 | |
| 312 | namespace diff_type { |
| 313 | // TODO: |
| 314 | template<typename T> T* var = new T(); |
| 315 | #ifndef PRECXX11 |
| 316 | template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}} |
| 317 | template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}} |
| 318 | #endif |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | namespace narrowing { |
| 323 | template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}} |
| 324 | #ifndef PRECXX11 |
| 325 | // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\ |
| 326 | // expected-note@-2 {{insert an explicit cast to silence this issue}} |
| 327 | #endif |
| 328 | int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}} |
| 329 | } |
| 330 | |
| 331 | namespace use_in_structs { |
| 332 | // TODO: |
| 333 | } |
| 334 | |
| 335 | namespace attributes { |
| 336 | // TODO: |
| 337 | } |
| 338 | |
| 339 | #ifndef PRECXX11 |
| 340 | namespace arrays { |
| 341 | template<typename T> |
| 342 | T* arr = new T[10]{T(10), T(23)}; |
| 343 | |
| 344 | float f = 10.5; |
| 345 | template<> float* arr<float> = &f; |
| 346 | |
| 347 | void bar() { |
| 348 | int *iarr = arr<int>; |
| 349 | iarr[0] = 1; |
| 350 | iarr[2] = 3; |
| 351 | iarr[6] = -2; |
| 352 | |
| 353 | float ff = *arr<float>; |
| 354 | float nof = arr<float>[3]; // No bounds-check in C++ |
| 355 | } |
| 356 | } |
| 357 | #endif |
| 358 | |
| 359 | namespace nested { |
| 360 | |
| 361 | namespace n0a { |
| 362 | template<typename T> |
| 363 | T pi0a = T(3.1415926535897932385); |
| 364 | } |
| 365 | |
| 366 | using namespace n0a; |
| 367 | int i0a = pi0a<int>; |
| 368 | |
| 369 | template float pi0a<float>; |
| 370 | float f0a = pi0a<float>; |
| 371 | |
| 372 | template<> double pi0a<double> = 5.2; |
| 373 | double d0a = pi0a<double>; |
| 374 | |
| 375 | namespace n0b { |
| 376 | template<typename T> |
| 377 | T pi0b = T(3.1415926535897932385); |
| 378 | } |
| 379 | |
| 380 | int i0b = n0b::pi0b<int>; |
| 381 | |
| 382 | template float n0b::pi0b<float>; |
| 383 | float f0b = n0b::pi0b<float>; |
| 384 | |
| 385 | template<> double n0b::pi0b<double> = 5.2; |
| 386 | double d0b = n0b::pi0b<double>; |
| 387 | |
| 388 | namespace n1 { |
| 389 | template<typename T> |
| 390 | T pi1a = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} |
| 391 | #ifndef PRECXX11 |
| 392 | // expected-note@-2 {{explicit instantiation refers here}} |
| 393 | #endif |
| 394 | |
| 395 | template<typename T> |
| 396 | T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} |
| 397 | #ifndef PRECXX11 |
| 398 | // expected-note@-2 {{explicit instantiation refers here}} |
| 399 | #endif |
| 400 | } |
| 401 | |
| 402 | namespace use_n1a { |
| 403 | using namespace n1; |
| 404 | int i1 = pi1a<int>; |
| 405 | |
| 406 | template float pi1a<float>; |
| 407 | #ifndef PRECXX11 |
| 408 | // expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}} |
| 409 | #endif |
| 410 | float f1 = pi1a<float>; |
| 411 | |
| 412 | template<> double pi1a<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}} |
| 413 | double d1 = pi1a<double>; |
| 414 | } |
| 415 | |
| 416 | namespace use_n1b { |
| 417 | int i1 = n1::pi1b<int>; |
| 418 | |
| 419 | template float n1::pi1b<float>; |
| 420 | #ifndef PRECXX11 |
| 421 | // expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}} |
| 422 | #endif |
| 423 | float f1 = n1::pi1b<float>; |
| 424 | |
| 425 | template<> double n1::pi1b<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}} |
| 426 | double d1 = n1::pi1b<double>; |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | namespace nested_name { |
| 431 | template<typename T> int a; // expected-note {{variable template 'a' declared here}} |
| 432 | a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}} |
| 433 | |
| 434 | class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}} |
| 435 | enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}} |
| 436 | } |
| 437 | |
| 438 | namespace PR18530 { |
| 439 | template<typename T> int a; |
| 440 | int a<int>; // expected-error {{requires 'template<>'}} |
| 441 | } |
| 442 | |
| 443 | namespace PR19152 { |
| 444 | #ifndef PRECXX11 |
| 445 | template<typename T> const auto x = 1; |
| 446 | static_assert(x<int> == 1, ""); |
| 447 | #endif |
| 448 | } |
| 449 | |
| 450 | namespace PR19169 { |
| 451 | template <typename T> int* f(); |
| 452 | template <typename T> void f(); |
| 453 | template<> int f<double>; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}} |
| 454 | |
| 455 | template <typename T> void g(); |
| 456 | template<> int g<double>; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} |
| 457 | } |
| 458 | |
| 459 | #ifndef PRECXX11 |
| 460 | template <typename... Args> struct Variadic_t { }; |
| 461 | template <typename... Args> Variadic_t<Args...> Variadic; |
| 462 | auto variadic1 = Variadic<>; |
| 463 | auto variadic2 = Variadic<int, int>; |
| 464 | #endif |
| 465 | |
| 466 | namespace VexingParse { |
| 467 | template <typename> int var; // expected-note {{declared here}} |
| 468 | int x(var); // expected-error {{use of variable template 'var' requires template arguments}} |
| 469 | } |
| 470 | |