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