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