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