Home | History | Annotate | Download | only in temp.expl.spec
      1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
      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 
     14 // C++ [temp.expl.spec]p1:
     15 //   An explicit specialization of any of the following:
     16 
     17 //     -- function template
     18 namespace N0 {
     19   template<typename T> void f0(T) {
     20     T t;
     21   }
     22 
     23   template<> void f0(NonDefaultConstructible) { }
     24 
     25   void test_f0(NonDefaultConstructible NDC) {
     26     f0(NDC);
     27   }
     28 
     29   template<> void f0(int);
     30   template<> void f0(long);
     31 }
     32 
     33 template<> void N0::f0(int) { } // okay
     34 
     35 namespace N1 {
     36   template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}}
     37 }
     38 
     39 template<> void N0::f0(double) { }
     40 
     41 struct X1 {
     42   template<typename T> void f(T);
     43 
     44   template<> void f(int); // expected-error{{in class scope}}
     45 };
     46 
     47 //     -- class template
     48 namespace N0 {
     49 
     50 template<typename T>
     51 struct X0 { // expected-note {{here}}
     52   static T member;
     53 
     54   void f1(T t) {
     55     t = 17;
     56   }
     57 
     58   struct Inner : public T { }; // expected-note 2{{here}}
     59 
     60   template<typename U>
     61   struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \
     62    // expected-error{{base specifier}}
     63 
     64   template<typename U>
     65   void ft1(T t, U u);
     66 };
     67 
     68 }
     69 
     70 template<typename T>
     71 template<typename U>
     72 void N0::X0<T>::ft1(T t, U u) {
     73   t = u;
     74 }
     75 
     76 template<typename T> T N0::X0<T>::member;
     77 
     78 template<> struct N0::X0<void> { };
     79 N0::X0<void> test_X0;
     80 
     81 namespace N1 {
     82   template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' must originally be declared in namespace 'N0'}}
     83 }
     84 
     85 namespace N0 {
     86   template<> struct X0<volatile void>;
     87 }
     88 
     89 template<> struct N0::X0<volatile void> {
     90   void f1(void *);
     91 };
     92 
     93 //     -- member function of a class template
     94 template<> void N0::X0<void*>::f1(void *) { }
     95 
     96 void test_spec(N0::X0<void*> xvp, void *vp) {
     97   xvp.f1(vp);
     98 }
     99 
    100 namespace N0 {
    101   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
    102 
    103   template<> void X0<const volatile void*>::f1(const volatile void*);
    104 }
    105 
    106 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
    107   x0.f1(cvp); // okay: we've explicitly specialized
    108 }
    109 
    110 //     -- static data member of a class template
    111 namespace N0 {
    112   // This actually tests p15; the following is a declaration, not a definition.
    113   template<>
    114   NonDefaultConstructible X0<NonDefaultConstructible>::member;
    115 
    116   template<> long X0<long>::member = 17;
    117 
    118   template<> float X0<float>::member;
    119 
    120   template<> double X0<double>::member;
    121 }
    122 
    123 NonDefaultConstructible &get_static_member() {
    124   return N0::X0<NonDefaultConstructible>::member;
    125 }
    126 
    127 template<> int N0::X0<int>::member;
    128 
    129 template<> float N0::X0<float>::member = 3.14f;
    130 
    131 namespace N1 {
    132   template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}}
    133 }
    134 
    135 //    -- member class of a class template
    136 namespace N0 {
    137 
    138   template<>
    139   struct X0<void*>::Inner { };
    140 
    141   template<>
    142   struct X0<int>::Inner { };
    143 
    144   template<>
    145   struct X0<unsigned>::Inner;
    146 
    147   template<>
    148   struct X0<float>::Inner;
    149 
    150   template<>
    151   struct X0<double>::Inner; // expected-note{{forward declaration}}
    152 }
    153 
    154 template<>
    155 struct N0::X0<long>::Inner { };
    156 
    157 template<>
    158 struct N0::X0<float>::Inner { };
    159 
    160 namespace N1 {
    161   template<>
    162   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
    163 
    164   template<>
    165   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
    166 };
    167 
    168 N0::X0<void*>::Inner inner0;
    169 N0::X0<int>::Inner inner1;
    170 N0::X0<long>::Inner inner2;
    171 N0::X0<float>::Inner inner3;
    172 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
    173 
    174 //    -- member class template of a class template
    175 namespace N0 {
    176   template<>
    177   template<>
    178   struct X0<void*>::InnerTemplate<int> { };
    179 
    180   template<> template<>
    181   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
    182 
    183   template<> template<>
    184   struct X0<int>::InnerTemplate<long>;
    185 
    186   template<> template<>
    187   struct X0<int>::InnerTemplate<double>;
    188 }
    189 
    190 template<> template<>
    191 struct N0::X0<int>::InnerTemplate<long> { }; // okay
    192 
    193 template<> template<>
    194 struct N0::X0<int>::InnerTemplate<float> { };
    195 
    196 namespace N1 {
    197   template<> template<>
    198   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
    199 }
    200 
    201 N0::X0<void*>::InnerTemplate<int> inner_template0;
    202 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
    203 N0::X0<int>::InnerTemplate<long> inner_template2;
    204 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
    205 
    206 //    -- member function template of a class template
    207 namespace N0 {
    208   template<>
    209   template<>
    210   void X0<void*>::ft1(void*, const void*) { }
    211 
    212   template<> template<>
    213   void X0<void*>::ft1(void *, int);
    214 
    215   template<> template<>
    216   void X0<void*>::ft1(void *, unsigned);
    217 
    218   template<> template<>
    219   void X0<void*>::ft1(void *, long);
    220 }
    221 
    222 template<> template<>
    223 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
    224 
    225 template<> template<>
    226 void N0::X0<void*>::ft1(void *, float) { }
    227 
    228 namespace N1 {
    229   template<> template<>
    230   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}}
    231 }
    232 
    233 
    234 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
    235                         int i, unsigned u) {
    236   xvp.ft1(vp, cvp);
    237   xvp.ft1(vp, i);
    238   xvp.ft1(vp, u);
    239 }
    240 
    241 namespace has_inline_namespaces {
    242   inline namespace inner {
    243     template<class T> void f(T&);
    244 
    245     template<class T>
    246     struct X0 {
    247       struct MemberClass;
    248 
    249       void mem_func();
    250 
    251       template<typename U>
    252       struct MemberClassTemplate;
    253 
    254       template<typename U>
    255       void mem_func_template(U&);
    256 
    257       static int value;
    258     };
    259   }
    260 
    261   struct X1;
    262   struct X2;
    263 
    264   // An explicit specialization whose declarator-id is not qualified
    265   // shall be declared in the nearest enclosing namespace of the
    266   // template, or, if the namespace is inline (7.3.1), any namespace
    267   // from its enclosing namespace set.
    268   template<> void f(X1&);
    269   template<> void f<X2>(X2&);
    270 
    271   template<> struct X0<X1> { };
    272 
    273   template<> struct X0<X2>::MemberClass { };
    274 
    275   template<> void X0<X2>::mem_func();
    276 
    277   template<> template<typename T> struct X0<X2>::MemberClassTemplate { };
    278 
    279   template<> template<typename T> void X0<X2>::mem_func_template(T&) { }
    280 
    281   template<> int X0<X2>::value = 12;
    282 }
    283 
    284 struct X3;
    285 struct X4;
    286 
    287 template<> void has_inline_namespaces::f(X3&);
    288 template<> void has_inline_namespaces::f<X4>(X4&);
    289 
    290 template<> struct has_inline_namespaces::X0<X3> { };
    291 
    292 template<> struct has_inline_namespaces::X0<X4>::MemberClass { };
    293 
    294 template<> void has_inline_namespaces::X0<X4>::mem_func();
    295 
    296 template<> template<typename T>
    297 struct has_inline_namespaces::X0<X4>::MemberClassTemplate { };
    298 
    299 template<> template<typename T>
    300 void has_inline_namespaces::X0<X4>::mem_func_template(T&) { }
    301 
    302 template<> int has_inline_namespaces::X0<X4>::value = 13;
    303