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