348 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-c++1y-extensions2 3// This test creates cases where implicit instantiations of various entities4// would cause a diagnostic, but provides expliict specializations for those5// entities that avoid the diagnostic. The specializations are alternately6// declarations and definitions, and the intent of this test is to verify7// that we allow specializations only in the appropriate namespaces (and8// nowhere else).9struct NonDefaultConstructible {10 NonDefaultConstructible(int);11};12 13// C++ [temp.expl.spec]p1:14// An explicit specialization of any of the following:15 16// -- function template17namespace N0 {18 template<typename T> void f0(T) {19 T t;20 }21 22 template<> void f0(NonDefaultConstructible) { }23 24 void test_f0(NonDefaultConstructible NDC) {25 f0(NDC);26 }27 28 template<> void f0(int);29 template<> void f0(long);30}31 32template<> void N0::f0(int) { } // okay33 34namespace N1 {35 template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}}36}37 38template<> void N0::f0(double) { }39 40struct X1 {41 template<typename T> void f(T);42 43 template<> void f(int); // OK (DR727)44};45 46// -- class template47namespace N0 {48 49template<typename T>50struct X0 { // expected-note {{here}}51 static T member;52 53 void f1(T t) {54 t = 17;55 }56 57 struct Inner : public T { }; // expected-note 2{{here}}58 59 template<typename U>60 struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \61 // expected-error{{base specifier}}62 63 template<typename U>64 void ft1(T t, U u);65};66 67}68 69template<typename T>70template<typename U>71void N0::X0<T>::ft1(T t, U u) {72 t = u;73}74 75template<typename T> T N0::X0<T>::member;76 77template<> struct N0::X0<void> { };78N0::X0<void> test_X0;79 80namespace N1 {81 template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}}82}83 84namespace N0 {85 template<> struct X0<volatile void>;86}87 88template<> struct N0::X0<volatile void> {89 void f1(void *);90};91 92// -- variable template [C++1y]93namespace N0 {94template<typename T> int v0; // expected-note 4{{explicitly specialized declaration is here}}95template<> int v0<char[1]>; // expected-note {{previous definition is here}}96template<> int v0<char[2]>;97template<> int v0<char[5]>; // expected-note {{previous definition is here}}98template<> int v0<char[6]>;99}100using N0::v0;101 102template<typename T> int v1; // expected-note 4{{explicitly specialized declaration is here}}103template<> int v1<char[3]>; // expected-note {{previous definition is here}}104template<> int v1<char[4]>; // expected-note {{previous definition is here}}105template<> int v1<char[7]>; // expected-note {{previous definition is here}}106template<> int v1<char[8]>;107 108template<> int N0::v0<int[1]>;109template<> int v0<int[2]>;110template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}111template<> int v1<int[4]>;112 113template<> int N0::v0<char[1]>; // expected-error {{redefinition of 'v0<char[1]>'}}114template<> int v0<char[2]>;115template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}116 // expected-error@-1 {{redefinition of 'v1<char[3]>'}}117template<> int v1<char[4]>; // expected-error {{redefinition of 'v1<char[4]>'}}118 119namespace N1 {120template<> int N0::v0<int[5]>; // expected-error {{not in a namespace enclosing 'N0'}}121template<> int v0<int[6]>; // expected-error {{not in a namespace enclosing 'N0'}}122template<> int ::v1<int[7]>; // expected-error {{must occur at global scope}}123template<> int v1<int[8]>; // expected-error {{must occur at global scope}}124 125template<> int N0::v0<char[5]>; // expected-error {{not in a namespace enclosing 'N0'}}126 // expected-error@-1 {{redefinition of 'v0<char[5]>'}}127template<> int v0<char[6]>; // expected-error {{not in a namespace enclosing 'N0'}}128template<> int ::v1<char[7]>; // expected-error {{must occur at global scope}}129 // expected-error@-1 {{redefinition of 'v1<char[7]>'}}130template<> int v1<char[8]>; // expected-error {{must occur at global scope}}131}132 133// -- member function of a class template134template<> void N0::X0<void*>::f1(void *) { }135 136void test_spec(N0::X0<void*> xvp, void *vp) {137 xvp.f1(vp);138}139 140namespace N0 {141 template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}142 143 template<> void X0<const volatile void*>::f1(const volatile void*);144}145 146void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {147 x0.f1(cvp); // okay: we've explicitly specialized148}149 150// -- static data member of a class template151namespace N0 {152 // This actually tests p15; the following is a declaration, not a definition.153 template<>154 NonDefaultConstructible X0<NonDefaultConstructible>::member;155 156 template<> long X0<long>::member = 17;157 158 template<> float X0<float>::member;159 160 template<> double X0<double>::member;161}162 163NonDefaultConstructible &get_static_member() {164 return N0::X0<NonDefaultConstructible>::member;165}166 167template<> int N0::X0<int>::member;168 169template<> float N0::X0<float>::member = 3.14f;170 171namespace N1 {172 template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}173}174 175// -- member class of a class template176namespace N0 {177 178 template<>179 struct X0<void*>::Inner { };180 181 template<>182 struct X0<int>::Inner { };183 184 template<>185 struct X0<unsigned>::Inner;186 187 template<>188 struct X0<float>::Inner;189 190 template<>191 struct X0<double>::Inner; // expected-note{{forward declaration}}192}193 194template<>195struct N0::X0<long>::Inner { };196 197template<>198struct N0::X0<float>::Inner { };199 200namespace N1 {201 template<>202 struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}203 204 template<>205 struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}206};207 208N0::X0<void*>::Inner inner0;209N0::X0<int>::Inner inner1;210N0::X0<long>::Inner inner2;211N0::X0<float>::Inner inner3;212N0::X0<double>::Inner inner4; // expected-error{{incomplete}}213 214// -- member class template of a class template215namespace N0 {216 template<>217 template<>218 struct X0<void*>::InnerTemplate<int> { };219 220 template<> template<>221 struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}222 223 template<> template<>224 struct X0<int>::InnerTemplate<long>;225 226 template<> template<>227 struct X0<int>::InnerTemplate<double>;228}229 230template<> template<>231struct N0::X0<int>::InnerTemplate<long> { }; // okay232 233template<> template<>234struct N0::X0<int>::InnerTemplate<float> { };235 236namespace N1 {237 template<> template<>238 struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}239}240 241N0::X0<void*>::InnerTemplate<int> inner_template0;242N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}243N0::X0<int>::InnerTemplate<long> inner_template2;244N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}245 246// -- member function template of a class template247namespace N0 {248 template<>249 template<>250 void X0<void*>::ft1(void*, const void*) { }251 252 template<> template<>253 void X0<void*>::ft1(void *, int);254 255 template<> template<>256 void X0<void*>::ft1(void *, unsigned);257 258 template<> template<>259 void X0<void*>::ft1(void *, long);260}261 262template<> template<>263void N0::X0<void*>::ft1(void *, unsigned) { } // okay264 265template<> template<>266void N0::X0<void*>::ft1(void *, float) { }267 268namespace N1 {269 template<> template<>270 void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}271}272 273 274void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,275 int i, unsigned u) {276 xvp.ft1(vp, cvp);277 xvp.ft1(vp, i);278 xvp.ft1(vp, u);279}280 281namespace has_inline_namespaces {282 inline namespace inner {283 template<class T> void f(T&);284 285 template<class T>286 struct X0 {287 struct MemberClass;288 289 void mem_func();290 291 template<typename U>292 struct MemberClassTemplate;293 294 template<typename U>295 void mem_func_template(U&);296 297 static int value;298 };299 }300 301 struct X1;302 struct X2;303 304 // An explicit specialization whose declarator-id is not qualified305 // shall be declared in the nearest enclosing namespace of the306 // template, or, if the namespace is inline (7.3.1), any namespace307 // from its enclosing namespace set.308 template<> void f(X1&);309 template<> void f<X2>(X2&);310 311 template<> struct X0<X1> { };312 313 template<> struct X0<X2>::MemberClass { };314 315 template<> void X0<X2>::mem_func();316 317 template<> template<typename T> struct X0<X2>::MemberClassTemplate { };318 319 template<> template<typename T> void X0<X2>::mem_func_template(T&) { }320 321 template<> int X0<X2>::value = 12;322}323 324struct X3;325struct X4;326 327template<> void has_inline_namespaces::f(X3&);328template<> void has_inline_namespaces::f<X4>(X4&);329 330template<> struct has_inline_namespaces::X0<X3> { };331 332template<> struct has_inline_namespaces::X0<X4>::MemberClass { };333 334template<> void has_inline_namespaces::X0<X4>::mem_func();335 336template<> template<typename T>337struct has_inline_namespaces::X0<X4>::MemberClassTemplate { };338 339template<> template<typename T>340void has_inline_namespaces::X0<X4>::mem_func_template(T&) { }341 342template<> int has_inline_namespaces::X0<X4>::value = 13;343 344namespace PR12938 {345 template<typename> [[noreturn]] void func();346 template<> void func<int>();347}348