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