Home | History | Annotate | Download | only in temp.expl.spec
      1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-c++1y-extensions
      2 
      3 // This test creates cases where implicit instantiations of various entities
      4 // would cause a diagnostic, but provides expliict specializations for those
      5 // entities that avoid the diagnostic. The specializations are alternately
      6 // declarations and definitions, and the intent of this test is to verify
      7 // that we allow specializations only in the appropriate namespaces (and
      8 // nowhere else).
      9 struct NonDefaultConstructible {
     10   NonDefaultConstructible(int);
     11 };
     12 
     13 // FIXME: The "must originally be declared in namespace" diagnostics throughout
     14 // this file are wrong.
     15 
     16 // C++ [temp.expl.spec]p1:
     17 //   An explicit specialization of any of the following:
     18 
     19 //     -- function template
     20 namespace N0 {
     21   template<typename T> void f0(T) {
     22     T t;
     23   }
     24 
     25   template<> void f0(NonDefaultConstructible) { }
     26 
     27   void test_f0(NonDefaultConstructible NDC) {
     28     f0(NDC);
     29   }
     30 
     31   template<> void f0(int);
     32   template<> void f0(long);
     33 }
     34 
     35 template<> void N0::f0(int) { } // okay
     36 
     37 namespace N1 {
     38   template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}
     39 }
     40 
     41 template<> void N0::f0(double) { }
     42 
     43 struct X1 {
     44   template<typename T> void f(T);
     45 
     46   template<> void f(int); // expected-error{{in class scope}}
     47 };
     48 
     49 //     -- class template
     50 namespace N0 {
     51 
     52 template<typename T>
     53 struct X0 { // expected-note {{here}}
     54   static T member;
     55 
     56   void f1(T t) {
     57     t = 17;
     58   }
     59 
     60   struct Inner : public T { }; // expected-note 2{{here}}
     61 
     62   template<typename U>
     63   struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \
     64    // expected-error{{base specifier}}
     65 
     66   template<typename U>
     67   void ft1(T t, U u);
     68 };
     69 
     70 }
     71 
     72 template<typename T>
     73 template<typename U>
     74 void N0::X0<T>::ft1(T t, U u) {
     75   t = u;
     76 }
     77 
     78 template<typename T> T N0::X0<T>::member;
     79 
     80 template<> struct N0::X0<void> { };
     81 N0::X0<void> test_X0;
     82 
     83 namespace N1 {
     84   template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}}
     85 }
     86 
     87 namespace N0 {
     88   template<> struct X0<volatile void>;
     89 }
     90 
     91 template<> struct N0::X0<volatile void> {
     92   void f1(void *);
     93 };
     94 
     95 //     -- variable template [C++1y]
     96 namespace N0 {
     97 template<typename T> int v0; // expected-note +{{here}}
     98 template<> extern int v0<char[1]>;
     99 template<> extern int v0<char[2]>;
    100 template<> extern int v0<char[5]>;
    101 template<> extern int v0<char[6]>;
    102 }
    103 using N0::v0;
    104 
    105 template<typename T> int v1; // expected-note +{{here}}
    106 template<> extern int v1<char[3]>;
    107 template<> extern int v1<char[4]>;
    108 template<> extern int v1<char[7]>;
    109 template<> extern int v1<char[8]>;
    110 
    111 template<> int N0::v0<int[1]>;
    112 template<> int v0<int[2]>; // FIXME: ill-formed
    113 template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}
    114 template<> int v1<int[4]>;
    115 
    116 template<> int N0::v0<char[1]>;
    117 template<> int v0<char[2]>; // FIXME: ill-formed
    118 template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}
    119 template<> int v1<char[4]>;
    120 
    121 namespace N1 {
    122 template<> int N0::v0<int[5]>; // expected-error {{must originally be declared in namespace 'N0'}} expected-error {{does not enclose namespace}}
    123 template<> int v0<int[6]>; // expected-error {{must originally be declared in namespace 'N0'}}
    124 template<> int ::v1<int[7]>; // expected-error {{must originally be declared in the global scope}} expected-error {{cannot name the global scope}}
    125 template<> int v1<int[8]>; // expected-error {{must originally be declared in the global scope}}
    126 
    127 template<> int N0::v0<char[5]>; // expected-error {{does not enclose namespace 'N0'}}
    128 template<> int v0<char[6]>; // FIXME: ill-formed
    129 template<> int ::v1<char[7]>; // expected-error {{cannot name the global scope}}
    130 template<> int v1<char[8]>; // FIXME: ill-formed
    131 }
    132 
    133 //     -- member function of a class template
    134 template<> void N0::X0<void*>::f1(void *) { }
    135 
    136 void test_spec(N0::X0<void*> xvp, void *vp) {
    137   xvp.f1(vp);
    138 }
    139 
    140 namespace N0 {
    141   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
    142 
    143   template<> void X0<const volatile void*>::f1(const volatile void*);
    144 }
    145 
    146 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
    147   x0.f1(cvp); // okay: we've explicitly specialized
    148 }
    149 
    150 //     -- static data member of a class template
    151 namespace N0 {
    152   // This actually tests p15; the following is a declaration, not a definition.
    153   template<>
    154   NonDefaultConstructible X0<NonDefaultConstructible>::member;
    155 
    156   template<> long X0<long>::member = 17;
    157 
    158   template<> float X0<float>::member;
    159 
    160   template<> double X0<double>::member;
    161 }
    162 
    163 NonDefaultConstructible &get_static_member() {
    164   return N0::X0<NonDefaultConstructible>::member;
    165 }
    166 
    167 template<> int N0::X0<int>::member;
    168 
    169 template<> float N0::X0<float>::member = 3.14f;
    170 
    171 namespace N1 {
    172   template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
    173 }
    174 
    175 //    -- member class of a class template
    176 namespace N0 {
    177 
    178   template<>
    179   struct X0<void*>::Inner { };
    180 
    181   template<>
    182   struct X0<int>::Inner { };
    183 
    184   template<>
    185   struct X0<unsigned>::Inner;
    186 
    187   template<>
    188   struct X0<float>::Inner;
    189 
    190   template<>
    191   struct X0<double>::Inner; // expected-note{{forward declaration}}
    192 }
    193 
    194 template<>
    195 struct N0::X0<long>::Inner { };
    196 
    197 template<>
    198 struct N0::X0<float>::Inner { };
    199 
    200 namespace N1 {
    201   template<>
    202   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
    203 
    204   template<>
    205   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
    206 };
    207 
    208 N0::X0<void*>::Inner inner0;
    209 N0::X0<int>::Inner inner1;
    210 N0::X0<long>::Inner inner2;
    211 N0::X0<float>::Inner inner3;
    212 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
    213 
    214 //    -- member class template of a class template
    215 namespace N0 {
    216   template<>
    217   template<>
    218   struct X0<void*>::InnerTemplate<int> { };
    219 
    220   template<> template<>
    221   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
    222 
    223   template<> template<>
    224   struct X0<int>::InnerTemplate<long>;
    225 
    226   template<> template<>
    227   struct X0<int>::InnerTemplate<double>;
    228 }
    229 
    230 template<> template<>
    231 struct N0::X0<int>::InnerTemplate<long> { }; // okay
    232 
    233 template<> template<>
    234 struct N0::X0<int>::InnerTemplate<float> { };
    235 
    236 namespace N1 {
    237   template<> template<>
    238   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
    239 }
    240 
    241 N0::X0<void*>::InnerTemplate<int> inner_template0;
    242 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
    243 N0::X0<int>::InnerTemplate<long> inner_template2;
    244 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
    245 
    246 //    -- member function template of a class template
    247 namespace N0 {
    248   template<>
    249   template<>
    250   void X0<void*>::ft1(void*, const void*) { }
    251 
    252   template<> template<>
    253   void X0<void*>::ft1(void *, int);
    254 
    255   template<> template<>
    256   void X0<void*>::ft1(void *, unsigned);
    257 
    258   template<> template<>
    259   void X0<void*>::ft1(void *, long);
    260 }
    261 
    262 template<> template<>
    263 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
    264 
    265 template<> template<>
    266 void N0::X0<void*>::ft1(void *, float) { }
    267 
    268 namespace N1 {
    269   template<> template<>
    270   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
    271 }
    272 
    273 
    274 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
    275                         int i, unsigned u) {
    276   xvp.ft1(vp, cvp);
    277   xvp.ft1(vp, i);
    278   xvp.ft1(vp, u);
    279 }
    280 
    281 namespace has_inline_namespaces {
    282   inline namespace inner {
    283     template<class T> void f(T&);
    284 
    285     template<class T>
    286     struct X0 {
    287       struct MemberClass;
    288 
    289       void mem_func();
    290 
    291       template<typename U>
    292       struct MemberClassTemplate;
    293 
    294       template<typename U>
    295       void mem_func_template(U&);
    296 
    297       static int value;
    298     };
    299   }
    300 
    301   struct X1;
    302   struct X2;
    303 
    304   // An explicit specialization whose declarator-id is not qualified
    305   // shall be declared in the nearest enclosing namespace of the
    306   // template, or, if the namespace is inline (7.3.1), any namespace
    307   // from its enclosing namespace set.
    308   template<> void f(X1&);
    309   template<> void f<X2>(X2&);
    310 
    311   template<> struct X0<X1> { };
    312 
    313   template<> struct X0<X2>::MemberClass { };
    314 
    315   template<> void X0<X2>::mem_func();
    316 
    317   template<> template<typename T> struct X0<X2>::MemberClassTemplate { };
    318 
    319   template<> template<typename T> void X0<X2>::mem_func_template(T&) { }
    320 
    321   template<> int X0<X2>::value = 12;
    322 }
    323 
    324 struct X3;
    325 struct X4;
    326 
    327 template<> void has_inline_namespaces::f(X3&);
    328 template<> void has_inline_namespaces::f<X4>(X4&);
    329 
    330 template<> struct has_inline_namespaces::X0<X3> { };
    331 
    332 template<> struct has_inline_namespaces::X0<X4>::MemberClass { };
    333 
    334 template<> void has_inline_namespaces::X0<X4>::mem_func();
    335 
    336 template<> template<typename T>
    337 struct has_inline_namespaces::X0<X4>::MemberClassTemplate { };
    338 
    339 template<> template<typename T>
    340 void has_inline_namespaces::X0<X4>::mem_func_template(T&) { }
    341 
    342 template<> int has_inline_namespaces::X0<X4>::value = 13;
    343 
    344 namespace PR12938 {
    345   template<typename> [[noreturn]] void func();
    346   template<> void func<int>();
    347 }
    348