From 4c8b24812ddcd1dedaca343a6d4e76f91f398981 Mon Sep 17 00:00:00 2001 From: Roman Divacky Date: Wed, 14 Oct 2009 18:03:49 +0000 Subject: Update clang to r84119. --- test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp | 99 ++++++++++ test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp | 7 + test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp | 8 + test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp | 6 + test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp | 42 +++++ test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp | 22 +++ test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp | 26 +++ test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp | 12 ++ test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp | 20 +++ test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp | 30 ++++ test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp | 239 +++++++++++++++++++++++++ test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp | 14 ++ test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp | 30 ++++ test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp | 14 ++ test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp | 59 ++++++ test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp | 61 +++++++ test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp | 56 ++++++ test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp | 14 ++ 18 files changed, 759 insertions(+) create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp create mode 100644 test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp (limited to 'test/CXX/temp/temp.spec/temp.expl.spec') diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp new file mode 100644 index 000000000000..239b8aeb04e4 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp @@ -0,0 +1,99 @@ +// RUN: clang-cc -fsyntax-only -verify %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 intent is to verify that +// implicit instantiations do not occur (because the explicit specialization +// is used instead). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +template void f0(T) { + T t; +} + +template<> void f0(NonDefaultConstructible) { } + +void test_f0(NonDefaultConstructible NDC) { + f0(NDC); +} + +// -- class template +template +struct X0 { + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; + + template + struct InnerTemplate : public T { }; + + template + void ft1(T t, U u); +}; + +template +template +void X0::ft1(T t, U u) { + t = u; +} + +template T X0::member; + +template<> struct X0 { }; +X0 test_X0; + + +// -- member function of a class template +template<> void X0::f1(void *) { } + +void test_spec(X0 xvp, void *vp) { + xvp.f1(vp); +} + +// -- static data member of a class template +template<> +NonDefaultConstructible X0::member = 17; + +NonDefaultConstructible &get_static_member() { + return X0::member; +} + +// -- member class of a class template +template<> +struct X0::Inner { }; + +X0::Inner inner0; + +// -- member class template of a class template +template<> +template<> +struct X0::InnerTemplate { }; + +X0::InnerTemplate inner_template0; + +// -- member function template of a class template +template<> +template<> +void X0::ft1(void*, const void*) { } + +void test_func_template(X0 xvp, void *vp, const void *cvp) { + xvp.ft1(vp, cvp); +} + +// example from the standard: +template class stream; +template<> class stream { /* ... */ }; +template class Array { /* ... */ }; +template void sort(Array& v) { /* ... */ } +template<> void sort(Array&) ; diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp new file mode 100644 index 000000000000..61f1710a6b9e --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template class X; +template<> class X; // expected-note{{forward}} +X* p; + +X x; // expected-error{{incomplete type}} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp new file mode 100644 index 000000000000..e794e67a5ef3 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template class Array { /* ... */ }; +template void sort(Array& v); + +// explicit specialization for sort(Array&) +// with deduced template-argument of type int +template<> void sort(Array&); diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp new file mode 100644 index 000000000000..63cf9f5e50d1 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only %s + +template void f(T); + +template<> void f(int) { } +void f(int) { } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp new file mode 100644 index 000000000000..a5d5b9e3c41e --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp @@ -0,0 +1,42 @@ +// RUN: clang-cc -emit-llvm -o - %s | FileCheck %s + +template void f(T) { /* ... */ } +template inline void g(T) { /* ... */ } + +// CHECK: define void @_Z1gIiEvT_ +template<> void g<>(int) { /* ... */ } + +template +struct X { + void f() { } + void g(); + void h(); +}; + +template +void X::g() { +} + +template +inline void X::h() { +} + +// CHECK: define void @_ZN1XIiE1fEv +template<> void X::f() { } + +// CHECK: define void @_ZN1XIiE1hEv +template<> void X::h() { } + +// CHECK: define linkonce_odr void @_Z1fIiEvT_ +template<> inline void f<>(int) { /* ... */ } + +// CHECK: define linkonce_odr void @_ZN1XIiE1gEv +template<> inline void X::g() { } + +void test(X xi) { + f(17); + g(17); + xi.f(); + xi.g(); + xi.h(); +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp new file mode 100644 index 000000000000..840f566362ed --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct NonDefaultConstructible { + NonDefaultConstructible(const NonDefaultConstructible&); +}; + +template +struct X { + static T member; +}; + +template +T X::member; // expected-error{{no matching constructor}} + +// Okay; this is a declaration, not a definition. +template<> +NonDefaultConstructible X::member; + +NonDefaultConstructible &test(bool b) { + return b? X::member // expected-note{{instantiation}} + : X::member; +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp new file mode 100644 index 000000000000..ce40afd40225 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only %s +template struct A { + void f(T); + template void g1(T, X1); + template void g2(T, X2); + void h(T) { } +}; + +// specialization +template<> void A::f(int); + +// out of class member template definition +template template void A::g1(T, X1) { } + +// member template specialization +template<> template void A::g1(int, X1); + +// member template specialization +template<> template<> + void A::g1(int, char); // X1 deduced as char + +template<> template<> + void A::g2(int, char); // X2 specified as char + // member specialization even if defined in class definition + +template<> void A::h(int) { } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp new file mode 100644 index 000000000000..883cb71d5686 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template +class A { + template class B { + void mf(); + }; +}; + +template<> template<> class A::B; +template<> template<> void A::B::mf(); + +template<> void A::B::mf(); // expected-error{{requires 'template<>'}} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp new file mode 100644 index 000000000000..a5877d281d74 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template class A { + template class B { + template void mf1(T3); + void mf2(); + }; +}; + +template<> template +class A::B { }; + +template<> template<> template + void A::B::mf1(T t) { } + +template<> template<> template +void A::B::mf1(T t) { } // expected-error{{does not match}} + +// FIXME: This diagnostic could probably be better. +template template<> + void A::B::mf2() { } // expected-error{{does not refer}} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp new file mode 100644 index 000000000000..1f38e5a2c17d --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template +struct X { + template struct Inner { }; + + template void f(T, U) { } +}; + +template<> template +struct X::Inner { + U member; +}; + +template<> template +void X::f(int x, U y) { + x = y; // expected-error{{incompatible type}} +} + +void test(X xi, X xl, float *fp) { + X::Inner xii; + xii.member = fp; + xi.f(17, 25); + xi.f(17, 3.14159); + xi.f(17, fp); // expected-note{{instantiation}} + X::Inner xli; + + xli.member = fp; // expected-error{{no member}} + xl.f(17, fp); // okay +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp new file mode 100644 index 000000000000..64856605a0a7 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -0,0 +1,239 @@ +// RUN: clang-cc -fsyntax-only -verify %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) { // expected-note{{here}} + 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{{not in a namespace enclosing}} +} + +template<> void N0::f0(double) { } // expected-error{{originally be declared}} + +struct X1 { + template void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template +struct X0 { // expected-note 2{{here}} + static T member; // expected-note{{here}} + + void f1(T t) { // expected-note{{explicitly specialized declaration is here}} + t = 17; + } + + struct Inner : public T { }; // expected-note 3{{here}} + + template + struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template + void ft1(T t, U u); // expected-note{{explicitly specialized}} +}; + +} + +template +template +void N0::X0::ft1(T t, U u) { + t = u; +} + +template T N0::X0::member; + +template<> struct N0::X0 { }; // expected-error{{originally}} +N0::X0 test_X0; + +namespace N1 { + template<> struct N0::X0 { }; // expected-error{{originally}} +} + +namespace N0 { + template<> struct X0; +} + +template<> struct N0::X0 { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0::f1(void *) { } // expected-error{{member function specialization}} + +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; // expected-error{{originally}} + +template<> float N0::X0::member = 3.14f; + +namespace N1 { + template<> double N0::X0::member = 3.14; // expected-error{{not in a namespace enclosing}} +} + +// -- 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 { }; // expected-error{{originally}} + +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 { }; // expected-error{{class template specialization}} + +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) { } // expected-error{{function template specialization}} + +namespace N1 { + template<> template<> + void N0::X0::ft1(void *, long) { } // expected-error{{enclosing}} +} + + +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); +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp new file mode 100644 index 000000000000..d270b8167a16 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template +void f(T); + +template +struct A { }; + +struct X { + template<> friend void f(int); // expected-error{{in class scope}} + template<> friend class A; // expected-error{{cannot be a friend}} + + friend void f(float); // okay + friend class A; // okay +}; diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp new file mode 100644 index 000000000000..9dae3eb5190b --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template +struct X { + void mf1(T); + template void mf2(T, U); // expected-note{{previous}} +}; + +template<> +void X::mf1(int i = 17) // expected-error{{default}} +{ +} + +template<> template<> +void X::mf2(int, int = 17) // expected-error{{default}} +{ } + +template<> template +void X::mf2(int, U = U()) // expected-error{{default}} +{ +} + +template<> +struct X { + void mf1(float); +}; + +void X::mf1(float = 3.14f) // okay +{ +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp new file mode 100644 index 000000000000..2bd1400faefb --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { + template class X; +} + +// FIXME: this diagnostic is terrible (PR3844). +template<> class X { /* ... */ }; // expected-error {{unqualified-id}} + +namespace N { + +template<> class X { /* ... */ }; // OK: X is a template + +} \ No newline at end of file diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp new file mode 100644 index 000000000000..8d91068f9b99 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp @@ -0,0 +1,59 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct IntHolder { // expected-note{{here}} + IntHolder(int); +}; + +template +struct X { // expected-note{{here}} + void f() { + T t; // expected-error{{no matching}} + } + + void g() { } + + struct Inner { + T value; // expected-note {{member is declared here}} + }; + + static T value; +}; + +template +T X::value; // expected-error{{no matching constructor}} + +IntHolder &test_X_IntHolderInt(X xih) { + xih.g(); // okay + xih.f(); // expected-note{{instantiation}} + + // FIXME: diagnostic here has incorrect reason (PR5154) + X::Inner inner; // expected-error{{implicit default}} + + return X::value; // expected-note{{instantiation}} +} + +// Explicitly specialize the members of X to not cause +// problems with instantiation. +template<> +void X::f() { } + +template<> +struct X::Inner { + Inner() : value(17) { } + IntHolder value; +}; + +template<> +IntHolder X::value = 17; + +IntHolder &test_X_IntHolderInt(X xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X::Inner inner; // okay, uses specialization + + return X::value; // okay, uses specialization +} + +template<> +X::X() { } // expected-error{{instantiated member}} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp new file mode 100644 index 000000000000..58682c786f95 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp @@ -0,0 +1,61 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct IntHolder { + IntHolder(int); +}; + +template +struct X { + void f() { + T t; + } + + void g() { } + + struct Inner { + T value; + }; + + static T value; +}; + +template +T X::value; + +// Explicitly specialize the members of X to not cause +// problems with instantiation, but only provide declarations (not definitions). +template<> +void X::f(); + +template<> +struct X::Inner; // expected-note{{forward declaration}} + +template<> +IntHolder X::value; + +IntHolder &test_X_IntHolderInt(X xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X::Inner inner; // expected-error {{incomplete}} + + return X::value; // okay, uses specialization +} + + +template struct A { + void f(T) { /* ... */ } +}; + +template<> struct A { + void f(int); +}; + +void h() { + A a; + a.f(16); // A::f must be defined somewhere +} + +// explicit specialization syntax not used for a member of +// explicitly specialized class template specialization +void A::f(int) { /* ... */ } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp new file mode 100644 index 000000000000..e92d3f0a8883 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template +struct X0 { + void f(); + + template + void g(U); + + struct Nested { + }; + + static T member; +}; + +int &use_X0_int(X0 x0i, // expected-note{{implicit instantiation first required here}} + int i) { + x0i.f(); // expected-note{{implicit instantiation first required here}} + x0i.g(i); // expected-note{{implicit instantiation first required here}} + X0::Nested nested; // expected-note{{implicit instantiation first required here}} + return X0::member; // expected-note{{implicit instantiation first required here}} +} + +template<> +void X0::f() { // expected-error{{after instantiation}} +} + +template<> template<> +void X0::g(int) { // expected-error{{after instantiation}} +} + +template<> +struct X0::Nested { }; // expected-error{{after instantiation}} + +template<> +int X0::member = 17; // expected-error{{after instantiation}} + +template<> +struct X0 { }; // expected-error{{after instantiation}} + +// Example from the standard +template class Array { /* ... */ }; + +template void sort(Array& v) { /* ... */ } + +struct String {}; + +void f(Array& v) { + + sort(v); // expected-note{{required}} + // use primary template + // sort(Array&), T is String +} + +template<> void sort(Array& v); // // expected-error{{after instantiation}} +template<> void sort<>(Array& v); // OK: sort not yet used diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp new file mode 100644 index 000000000000..49481d2e6d7a --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { + template class X { /* ... */ }; + template class Y { /* ... */ }; + template<> class X { /* ... */ }; + template<> class Y; + + const unsigned NumElements = 17; +} + +template<> class N::Y { + int array[NumElements]; +}; -- cgit v1.3