// RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // This test creates cases where implicit instantiations of various entities // would cause a diagnostic, but provides expliict specializations for those // entities that avoid the diagnostic. The specializations are alternately // declarations and definitions, and the intent of this test is to verify // that we allow specializations only in the appropriate namespaces (and // nowhere else). struct NonDefaultConstructible { NonDefaultConstructible(int); }; // C++ [temp.expl.spec]p1: // An explicit specialization of any of the following: // -- function template namespace N0 { template void f0(T) { #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif T t; } template<> void f0(NonDefaultConstructible) { } void test_f0(NonDefaultConstructible NDC) { f0(NDC); } template<> void f0(int); template<> void f0(long); } template<> void N0::f0(int) { } // okay namespace N1 { template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} } template<> void N0::f0(double); #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of function template specialization of 'f0' outside namespace 'N0' is a C++11 extension}} #endif template<> void N0::f0(double) { } struct X1 { template void f(T); template<> void f(int); // expected-error{{in class scope}} }; // -- class template namespace N0 { template struct X0 { // expected-note {{explicitly specialized declaration is here}} #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif static T member; #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif void f1(T t) { #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif t = 17; } struct Inner : public T { }; // expected-note 2{{explicitly specialized declaration is here}} #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif template struct InnerTemplate : public T { }; // expected-note {{explicitly specialized declaration is here}} #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif // expected-error@-4 {{base specifier must name a class}} template void ft1(T t, U u); #if __cplusplus <= 199711L // expected-note@-2 {{explicitly specialized declaration is here}} #endif }; } template template void N0::X0::ft1(T t, U u) { t = u; } template T N0::X0::member; template<> struct N0::X0 { }; #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of class template specialization of 'X0' outside namespace 'N0' is a C++11 extension}} #endif N0::X0 test_X0; namespace N1 { template<> struct N0::X0 { }; // expected-error{{not in a namespace enclosing 'N0'}} } namespace N0 { template<> struct X0; } template<> struct N0::X0 { void f1(void *); }; // -- member function of a class template template<> void N0::X0::f1(void *) { } #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of member function specialization of 'f1' outside namespace 'N0' is a C++11 extension}} #endif void test_spec(N0::X0 xvp, void *vp) { xvp.f1(vp); } namespace N0 { template<> void X0::f1(void *) { } // expected-error{{no function template matches}} template<> void X0::f1(const volatile void*); } void test_x0_cvvoid(N0::X0 x0, const volatile void *cvp) { x0.f1(cvp); // okay: we've explicitly specialized } // -- static data member of a class template namespace N0 { // This actually tests p15; the following is a declaration, not a definition. template<> NonDefaultConstructible X0::member; template<> long X0::member = 17; template<> float X0::member; template<> double X0::member; } NonDefaultConstructible &get_static_member() { return N0::X0::member; } template<> int N0::X0::member; #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of static data member specialization of 'member' outside namespace 'N0' is a C++11 extension}} #endif template<> float N0::X0::member = 3.14f; namespace N1 { template<> double N0::X0::member = 3.14; // expected-error{{does not enclose namespace}} } // -- member class of a class template namespace N0 { template<> struct X0::Inner { }; template<> struct X0::Inner { }; template<> struct X0::Inner; template<> struct X0::Inner; template<> struct X0::Inner; // expected-note{{forward declaration}} } template<> struct N0::X0::Inner { }; #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of member class specialization of 'Inner' outside namespace 'N0' is a C++11 extension}} #endif template<> struct N0::X0::Inner { }; namespace N1 { template<> struct N0::X0::Inner { }; // expected-error{{member class specialization}} template<> struct N0::X0::Inner { }; // expected-error{{member class specialization}} }; N0::X0::Inner inner0; N0::X0::Inner inner1; N0::X0::Inner inner2; N0::X0::Inner inner3; N0::X0::Inner inner4; // expected-error{{incomplete}} // -- member class template of a class template namespace N0 { template<> template<> struct X0::InnerTemplate { }; template<> template<> struct X0::InnerTemplate; // expected-note{{forward declaration}} template<> template<> struct X0::InnerTemplate; template<> template<> struct X0::InnerTemplate; } template<> template<> struct N0::X0::InnerTemplate { }; // okay template<> template<> struct N0::X0::InnerTemplate { }; #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of class template specialization of 'InnerTemplate' outside namespace 'N0' is a C++11 extension}} #endif namespace N1 { template<> template<> struct N0::X0::InnerTemplate { }; // expected-error{{enclosing}} } N0::X0::InnerTemplate inner_template0; N0::X0::InnerTemplate inner_template1; // expected-error{{incomplete}} N0::X0::InnerTemplate inner_template2; N0::X0::InnerTemplate inner_template3; // expected-note{{instantiation}} // -- member function template of a class template namespace N0 { template<> template<> void X0::ft1(void*, const void*) { } template<> template<> void X0::ft1(void *, int); template<> template<> void X0::ft1(void *, unsigned); template<> template<> void X0::ft1(void *, long); } template<> template<> void N0::X0::ft1(void *, unsigned) { } // okay template<> template<> void N0::X0::ft1(void *, float) { } #if __cplusplus <= 199711L // expected-warning@-2 {{first declaration of function template specialization of 'ft1' outside namespace 'N0' is a C++11 extension}} #endif namespace N1 { template<> template<> void N0::X0::ft1(void *, long) { } // expected-error{{does not enclose namespace}} } void test_func_template(N0::X0 xvp, void *vp, const void *cvp, int i, unsigned u) { xvp.ft1(vp, cvp); xvp.ft1(vp, i); xvp.ft1(vp, u); } namespace PR8979 { template struct X0 { template class Inner; struct OtherInner; template void f(Inner&); typedef Inner MyInner; template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}} }; }