Home | History | Annotate | Download | only in temp.expl.spec
      1 // RUN: %clang_cc1 -fsyntax-only -verify %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) { // expected-note{{here}}
     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{{does not enclose namespace}}
     37 }
     38 
     39 template<> void N0::f0(double); // expected-warning{{C++11 extension}}
     40 template<> void N0::f0(double) { }
     41 
     42 struct X1 {
     43   template<typename T> void f(T);
     44 
     45   template<> void f(int); // expected-error{{in class scope}}
     46 };
     47 
     48 //     -- class template
     49 namespace N0 {
     50 
     51 template<typename T>
     52 struct X0 { // expected-note 2{{here}}
     53   static T member; // expected-note{{here}}
     54 
     55   void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
     56     t = 17;
     57   }
     58 
     59   struct Inner : public T { }; // expected-note 3{{here}}
     60 
     61   template<typename U>
     62   struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \
     63    // expected-error{{base specifier}}
     64 
     65   template<typename U>
     66   void ft1(T t, U u); // expected-note{{explicitly specialized}}
     67 };
     68 
     69 }
     70 
     71 template<typename T>
     72 template<typename U>
     73 void N0::X0<T>::ft1(T t, U u) {
     74   t = u;
     75 }
     76 
     77 template<typename T> T N0::X0<T>::member;
     78 
     79 template<> struct N0::X0<void> { }; // expected-warning{{C++11 extension}}
     80 N0::X0<void> test_X0;
     81 
     82 namespace N1 {
     83   template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}}
     84 }
     85 
     86 namespace N0 {
     87   template<> struct X0<volatile void>;
     88 }
     89 
     90 template<> struct N0::X0<volatile void> {
     91   void f1(void *);
     92 };
     93 
     94 //     -- member function of a class template
     95 template<> void N0::X0<void*>::f1(void *) { } // expected-warning{{member function specialization}}
     96 
     97 void test_spec(N0::X0<void*> xvp, void *vp) {
     98   xvp.f1(vp);
     99 }
    100 
    101 namespace N0 {
    102   template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
    103 
    104   template<> void X0<const volatile void*>::f1(const volatile void*);
    105 }
    106 
    107 void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
    108   x0.f1(cvp); // okay: we've explicitly specialized
    109 }
    110 
    111 //     -- static data member of a class template
    112 namespace N0 {
    113   // This actually tests p15; the following is a declaration, not a definition.
    114   template<>
    115   NonDefaultConstructible X0<NonDefaultConstructible>::member;
    116 
    117   template<> long X0<long>::member = 17;
    118 
    119   template<> float X0<float>::member;
    120 
    121   template<> double X0<double>::member;
    122 }
    123 
    124 NonDefaultConstructible &get_static_member() {
    125   return N0::X0<NonDefaultConstructible>::member;
    126 }
    127 
    128 template<> int N0::X0<int>::member;  // expected-warning{{C++11 extension}}
    129 
    130 template<> float N0::X0<float>::member = 3.14f;
    131 
    132 namespace N1 {
    133   template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
    134 }
    135 
    136 //    -- member class of a class template
    137 namespace N0 {
    138 
    139   template<>
    140   struct X0<void*>::Inner { };
    141 
    142   template<>
    143   struct X0<int>::Inner { };
    144 
    145   template<>
    146   struct X0<unsigned>::Inner;
    147 
    148   template<>
    149   struct X0<float>::Inner;
    150 
    151   template<>
    152   struct X0<double>::Inner; // expected-note{{forward declaration}}
    153 }
    154 
    155 template<>
    156 struct N0::X0<long>::Inner { }; // expected-warning{{C++11 extension}}
    157 
    158 template<>
    159 struct N0::X0<float>::Inner { };
    160 
    161 namespace N1 {
    162   template<>
    163   struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
    164 
    165   template<>
    166   struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
    167 };
    168 
    169 N0::X0<void*>::Inner inner0;
    170 N0::X0<int>::Inner inner1;
    171 N0::X0<long>::Inner inner2;
    172 N0::X0<float>::Inner inner3;
    173 N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
    174 
    175 //    -- member class template of a class template
    176 namespace N0 {
    177   template<>
    178   template<>
    179   struct X0<void*>::InnerTemplate<int> { };
    180 
    181   template<> template<>
    182   struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
    183 
    184   template<> template<>
    185   struct X0<int>::InnerTemplate<long>;
    186 
    187   template<> template<>
    188   struct X0<int>::InnerTemplate<double>;
    189 }
    190 
    191 template<> template<>
    192 struct N0::X0<int>::InnerTemplate<long> { }; // okay
    193 
    194 template<> template<>
    195 struct N0::X0<int>::InnerTemplate<float> { }; // expected-warning{{class template specialization}}
    196 
    197 namespace N1 {
    198   template<> template<>
    199   struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
    200 }
    201 
    202 N0::X0<void*>::InnerTemplate<int> inner_template0;
    203 N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
    204 N0::X0<int>::InnerTemplate<long> inner_template2;
    205 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
    206 
    207 //    -- member function template of a class template
    208 namespace N0 {
    209   template<>
    210   template<>
    211   void X0<void*>::ft1(void*, const void*) { }
    212 
    213   template<> template<>
    214   void X0<void*>::ft1(void *, int);
    215 
    216   template<> template<>
    217   void X0<void*>::ft1(void *, unsigned);
    218 
    219   template<> template<>
    220   void X0<void*>::ft1(void *, long);
    221 }
    222 
    223 template<> template<>
    224 void N0::X0<void*>::ft1(void *, unsigned) { } // okay
    225 
    226 template<> template<>
    227 void N0::X0<void*>::ft1(void *, float) { } // expected-warning{{function template specialization}}
    228 
    229 namespace N1 {
    230   template<> template<>
    231   void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
    232 }
    233 
    234 
    235 void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
    236                         int i, unsigned u) {
    237   xvp.ft1(vp, cvp);
    238   xvp.ft1(vp, i);
    239   xvp.ft1(vp, u);
    240 }
    241 
    242 namespace PR8979 {
    243   template<typename Z>
    244   struct X0 {
    245     template <class T, class U> class Inner;
    246     struct OtherInner;
    247     template<typename T, typename U> void f(Inner<T, U>&);
    248 
    249     typedef Inner<OtherInner, OtherInner> MyInner;
    250     template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}}
    251   };
    252 }
    253