1 // RUN: %clang_cc1 -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 {{template is 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 {{cannot refer to variable template 'pi' without a template argument list}} 34 int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}} 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; 62 int a = pi; 63 int ipi = pi<int>; // expected-error {{expected '(' for function-style cast or type construction}} \ 64 // expected-error {{expected expression}} 65 } 66 } 67 68 namespace odr_tmpl { 69 namespace pv_cvt { 70 int v; // expected-note {{previous definition is here}} 71 template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}} 72 } 73 namespace pvt_cv { 74 template<typename T> T v; // expected-note {{previous definition is here}} 75 int v; // expected-error {{redefinition of 'v' as different kind of symbol}} 76 } 77 namespace pvt_cvt { 78 template<typename T> T v0; // expected-note {{previous definition is here}} 79 template<typename T> T v0; // expected-error {{redefinition of 'v0'}} 80 81 template<typename T> T v; // expected-note {{previous definition is here}} 82 template<typename T> int v; // expected-error {{redefinition of 'v'}} 83 84 template<typename T> int v1; // expected-note {{previous template declaration is here}} 85 template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}} 86 } 87 namespace pvt_use { 88 template<typename T> T v; 89 v = 10; // expected-error {{C++ requires a type specifier for all declarations}} 90 } 91 92 namespace pvt_diff_params { 93 // FIXME: (?) Redefinitions should simply be not allowed, whether the 94 // template parameters match or not. However, this current behaviour also 95 // matches that of class templates... 96 template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}} 97 template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} 98 template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}} 99 } 100 101 namespace pvt_extern { 102 template<typename T> T v = T(); 103 template<typename T> extern T v; // redeclaration is allowed \ 104 // expected-note {{previous definition is here}} 105 template<typename T> extern int v; // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}} 106 107 #ifndef PRECXX11 108 template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}} 109 #endif 110 111 template<typename T> T var = T(); // expected-note {{previous definition is here}} 112 extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}} 113 } 114 115 #ifndef PRECXX11 116 namespace pvt_auto { 117 template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}} 118 template<typename T> auto v1 = T(); // expected-note {{previous definition is here}} 119 template<typename T> int v1; // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}} 120 template<typename T> auto v2 = T(); // expected-note {{previous definition is here}} 121 template<typename T> T v2; // expected-error {{redefinition of 'v2'}} 122 template<typename T> auto v3 = T(); // expected-note {{previous definition is here}} 123 template<typename T> extern T v3; // expected-error {{redefinition of 'v3' with a different type: 'T' vs 'auto'}} 124 template<typename T> auto v4 = T(); 125 template<typename T> extern auto v4; // expected-error {{declaration of variable 'v4' with type 'auto' requires an initializer}} 126 } 127 #endif 128 129 } 130 131 namespace explicit_instantiation { 132 template<typename T> 133 T pi0a = T(3.1415926535897932385); // expected-note {{variable template 'pi0a' declared here}} 134 template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}} 135 136 template<typename T> 137 T pi0b = T(3.1415926535897932385); // expected-note {{variable template 'pi0b' declared here}} 138 template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}} 139 140 template<typename T> 141 T pi0c = T(3.1415926535897932385); // expected-note {{variable template 'pi0c' declared here}} 142 template int pi0c<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}} 143 144 template<typename T> 145 T pi0 = T(3.1415926535897932385); 146 template int pi0<int>; // expected-note {{previous explicit instantiation is here}} 147 template int pi0<int>; // expected-error {{duplicate explicit instantiation of 'pi0<int>'}} 148 149 template<typename T> 150 CONST T pi1a = T(3.1415926535897932385); // expected-note {{variable template 'pi1a' declared here}} 151 template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}} 152 153 template<typename T> 154 CONST T pi1b = T(3.1415926535897932385); // expected-note {{variable template 'pi1b' declared here}} 155 template int pi1b<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}} 156 157 template<typename T> 158 CONST T pi1 = T(3.1415926535897932385); 159 template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}} 160 template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}} 161 162 #ifndef PRECXX11 163 namespace auto_var { 164 template<typename T> auto var0 = T(); 165 template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}} 166 167 template<typename T> auto var = T(); 168 template int var<int>; 169 } 170 #endif 171 172 template<typename=int> int missing_args; // expected-note {{here}} 173 template int missing_args; // expected-error {{must specify a template argument list}} 174 175 namespace extern_var { 176 // TODO: 177 } 178 } 179 180 namespace explicit_specialization { 181 182 namespace good { 183 template<typename T1, typename T2> 184 CONST int pi2 = 1; 185 186 template<typename T> 187 CONST int pi2<T,int> = 2; 188 189 template<typename T> 190 CONST int pi2<int,T> = 3; 191 192 template<> CONST int pi2<int,int> = 4; 193 194 #ifndef PRECXX11 195 void foo() { 196 static_assert(pi2<int,int> == 4, ""); 197 static_assert(pi2<float,int> == 2, ""); 198 static_assert(pi2<int,float> == 3, ""); 199 static_assert(pi2<int,float> == pi2<int,double>, ""); 200 static_assert(pi2<float,float> == 1, ""); 201 static_assert(pi2<float,float> == pi2<float,double>, ""); 202 } 203 #endif 204 } 205 206 namespace ambiguous { 207 208 template<typename T1, typename T2> 209 CONST int pi2 = 1; 210 211 template<typename T> 212 CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}} 213 214 template<typename T> 215 CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}} 216 217 void foo() { 218 int a = pi2<int,int>; // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}} 219 } 220 } 221 222 namespace type_changes { 223 224 template<typename T> 225 T pi0 = T(3.1415926535897932385); 226 227 template<> float pi0<int> = 10; 228 template<> int pi0<const int> = 10; 229 230 template<typename T> 231 T pi1 = T(3.1415926535897932385); 232 template<> CONST int pi1<int> = 10; 233 234 template<typename T> 235 T pi2 = T(3.1415926535897932385); 236 template<> int pi2<const int> = 10; 237 238 template<typename T> 239 CONST T pi4 = T(3.1415926535897932385); 240 template<> int pi4<int> = 10; 241 } 242 243 namespace redefinition { 244 template<typename T> 245 T pi0 = T(3.1415926535897932385); 246 247 template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}} 248 #ifndef PRECXX11 249 // expected-note@-2 {{previous definition is here}} 250 #endif 251 template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} 252 template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}} 253 template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}} 254 #ifndef PRECXX11 255 template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} 256 #endif 257 258 259 template<typename T> 260 CONST T pi1 = T(3.1415926535897932385); 261 262 template<> CONST int pi1<int> = 10; // expected-note {{previous definition is here}} 263 template<> CONST int pi1<int> = 10; // expected-error {{redefinition of 'pi1<int>'}} 264 } 265 266 namespace before_instantiation { 267 template<typename T> 268 T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}} 269 270 template<> int pi0<int> = 10; 271 template int pi0<int>; 272 template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} 273 274 template<typename T1, typename T2> 275 CONST int pi2 = 1; 276 277 template<typename T> CONST int pi2<T,int> = 2; 278 template CONST int pi2<int,int>; 279 } 280 namespace after_instantiation { 281 template<typename T> 282 T pi0 = T(3.1415926535897932385); 283 284 template int pi0<int>; // expected-note 2{{explicit instantiation first required here}} 285 template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}} 286 template<> float pi0<int>; // expected-error {{explicit specialization of 'pi0' after instantiation}} 287 288 template<typename T1, typename T2> 289 CONST int pi2 = 1; 290 291 template CONST int pi2<int,int>; 292 template<typename T> CONST int pi2<T,int> = 2; 293 } 294 295 #ifndef PRECXX11 296 namespace auto_var { 297 template<typename T, typename> auto var0 = T(); 298 template<typename T> auto var0<T,int> = T(); 299 template<> auto var0<int,int> = 7; 300 301 template<typename T, typename> auto var = T(); 302 template<typename T> T var<T,int> = T(5); 303 template<> int var<int,int> = 7; 304 305 void foo() { 306 int i0 = var0<int,int>; 307 int b = var<int,int>; 308 } 309 } 310 #endif 311 312 namespace extern_var { 313 // TODO: 314 } 315 316 namespace diff_type { 317 // TODO: 318 template<typename T> T* var = new T(); 319 #ifndef PRECXX11 320 template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}} 321 template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}} 322 #endif 323 } 324 } 325 326 namespace narrowing { 327 template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}} 328 #ifndef PRECXX11 329 // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\ 330 // expected-note@-2 {{override this message by inserting an explicit cast}} 331 #endif 332 int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}} 333 } 334 335 namespace use_in_structs { 336 // TODO: 337 } 338 339 namespace attributes { 340 // TODO: 341 } 342 343 #ifndef PRECXX11 344 namespace arrays { 345 template<typename T> 346 T* arr = new T[10]{T(10), T(23)}; 347 348 float f = 10.5; 349 template<> float* arr<float> = &f; 350 351 void bar() { 352 int *iarr = arr<int>; 353 iarr[0] = 1; 354 iarr[2] = 3; 355 iarr[6] = -2; 356 357 float ff = *arr<float>; 358 float nof = arr<float>[3]; // No bounds-check in C++ 359 } 360 } 361 #endif 362 363 namespace nested { 364 365 namespace n0a { 366 template<typename T> 367 T pi0a = T(3.1415926535897932385); 368 } 369 370 using namespace n0a; 371 int i0a = pi0a<int>; 372 373 template float pi0a<float>; 374 float f0a = pi0a<float>; 375 376 template<> double pi0a<double> = 5.2; 377 double d0a = pi0a<double>; 378 379 namespace n0b { 380 template<typename T> 381 T pi0b = T(3.1415926535897932385); 382 } 383 384 int i0b = n0b::pi0b<int>; 385 386 template float n0b::pi0b<float>; 387 float f0b = n0b::pi0b<float>; 388 389 template<> double n0b::pi0b<double> = 5.2; 390 double d0b = n0b::pi0b<double>; 391 392 namespace n1 { 393 template<typename T> 394 T pi1a = T(3.1415926535897932385); 395 #ifndef PRECXX11 396 // expected-note@-2 {{explicit instantiation refers here}} 397 #endif 398 399 template<typename T> 400 T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} 401 #ifndef PRECXX11 402 // expected-note@-2 {{explicit instantiation refers here}} 403 #endif 404 } 405 406 namespace use_n1a { 407 using namespace n1; 408 int i1 = pi1a<int>; 409 410 template float pi1a<float>; 411 #ifndef PRECXX11 412 // expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}} 413 #endif 414 float f1 = pi1a<float>; 415 416 template<> double pi1a<double> = 5.2; // expected-error {{no variable template matches specialization}} 417 double d1 = pi1a<double>; 418 } 419 420 namespace use_n1b { 421 int i1 = n1::pi1b<int>; 422 423 template float n1::pi1b<float>; 424 #ifndef PRECXX11 425 // expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}} 426 #endif 427 float f1 = n1::pi1b<float>; 428 429 template<> double n1::pi1b<double> = 5.2; // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \ 430 // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}} 431 double d1 = n1::pi1b<double>; 432 } 433 } 434 435