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