diff options
Diffstat (limited to 'test/CXX/temp/temp.spec/temp.expl.spec')
18 files changed, 759 insertions, 0 deletions
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<typename T> void f0(T) { + T t; +} + +template<> void f0(NonDefaultConstructible) { } + +void test_f0(NonDefaultConstructible NDC) { + f0(NDC); +} + +// -- class template +template<typename T> +struct X0 { + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; + + template<typename U> + struct InnerTemplate : public T { }; + + template<typename U> + void ft1(T t, U u); +}; + +template<typename T> +template<typename U> +void X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T X0<T>::member; + +template<> struct X0<void> { }; +X0<void> test_X0; + + +// -- member function of a class template +template<> void X0<void*>::f1(void *) { } + +void test_spec(X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +// -- static data member of a class template +template<> +NonDefaultConstructible X0<NonDefaultConstructible>::member = 17; + +NonDefaultConstructible &get_static_member() { + return X0<NonDefaultConstructible>::member; +} + +// -- member class of a class template +template<> +struct X0<void*>::Inner { }; + +X0<void*>::Inner inner0; + +// -- member class template of a class template +template<> +template<> +struct X0<void*>::InnerTemplate<int> { }; + +X0<void*>::InnerTemplate<int> inner_template0; + +// -- member function template of a class template +template<> +template<> +void X0<void*>::ft1(void*, const void*) { } + +void test_func_template(X0<void *> xvp, void *vp, const void *cvp) { + xvp.ft1(vp, cvp); +} + +// example from the standard: +template<class T> class stream; +template<> class stream<char> { /* ... */ }; +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v) { /* ... */ } +template<> void sort<char*>(Array<char*>&) ; 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 T> class X; +template<> class X<int>; // expected-note{{forward}} +X<int>* p; + +X<int> 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 T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v); + +// explicit specialization for sort(Array<int>&) +// with deduced template-argument of type int +template<> void sort(Array<int>&); 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<typename T> 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<class T> void f(T) { /* ... */ } +template<class T> inline void g(T) { /* ... */ } + +// CHECK: define void @_Z1gIiEvT_ +template<> void g<>(int) { /* ... */ } + +template<class T> +struct X { + void f() { } + void g(); + void h(); +}; + +template<class T> +void X<T>::g() { +} + +template<class T> +inline void X<T>::h() { +} + +// CHECK: define void @_ZN1XIiE1fEv +template<> void X<int>::f() { } + +// CHECK: define void @_ZN1XIiE1hEv +template<> void X<int>::h() { } + +// CHECK: define linkonce_odr void @_Z1fIiEvT_ +template<> inline void f<>(int) { /* ... */ } + +// CHECK: define linkonce_odr void @_ZN1XIiE1gEv +template<> inline void X<int>::g() { } + +void test(X<int> 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<typename T, typename U> +struct X { + static T member; +}; + +template<typename T, typename U> +T X<T, U>::member; // expected-error{{no matching constructor}} + +// Okay; this is a declaration, not a definition. +template<> +NonDefaultConstructible X<NonDefaultConstructible, long>::member; + +NonDefaultConstructible &test(bool b) { + return b? X<NonDefaultConstructible, int>::member // expected-note{{instantiation}} + : X<NonDefaultConstructible, long>::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<class T> struct A { + void f(T); + template<class X1> void g1(T, X1); + template<class X2> void g2(T, X2); + void h(T) { } +}; + +// specialization +template<> void A<int>::f(int); + +// out of class member template definition +template<class T> template<class X1> void A<T>::g1(T, X1) { } + +// member template specialization +template<> template<class X1> void A<int>::g1(int, X1); + +// member template specialization +template<> template<> + void A<int>::g1(int, char); // X1 deduced as char + +template<> template<> + void A<int>::g2<char>(int, char); // X2 specified as char + // member specialization even if defined in class definition + +template<> void A<int>::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 T1> +class A { + template<class T2> class B { + void mf(); + }; +}; + +template<> template<> class A<int>::B<double>; +template<> template<> void A<char>::B<char>::mf(); + +template<> void A<char>::B<int>::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 T1> class A { + template<class T2> class B { + template<class T3> void mf1(T3); + void mf2(); + }; +}; + +template<> template<class X> +class A<long>::B { }; + +template<> template<> template<class T> + void A<int>::B<double>::mf1(T t) { } + +template<> template<> template<class T> +void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}} + +// FIXME: This diagnostic could probably be better. +template<class Y> template<> + void A<Y>::B<double>::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<typename T> +struct X { + template<typename U> struct Inner { }; + + template<typename U> void f(T, U) { } +}; + +template<> template<typename U> +struct X<int>::Inner { + U member; +}; + +template<> template<typename U> +void X<int>::f(int x, U y) { + x = y; // expected-error{{incompatible type}} +} + +void test(X<int> xi, X<long> xl, float *fp) { + X<int>::Inner<float*> xii; + xii.member = fp; + xi.f(17, 25); + xi.f(17, 3.14159); + xi.f(17, fp); // expected-note{{instantiation}} + X<long>::Inner<float*> 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<typename T> 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<typename T> void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template<typename T> +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<typename U> + struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template<typename U> + void ft1(T t, U u); // expected-note{{explicitly specialized}} +}; + +} + +template<typename T> +template<typename U> +void N0::X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T N0::X0<T>::member; + +template<> struct N0::X0<void> { }; // expected-error{{originally}} +N0::X0<void> test_X0; + +namespace N1 { + template<> struct N0::X0<const void> { }; // expected-error{{originally}} +} + +namespace N0 { + template<> struct X0<volatile void>; +} + +template<> struct N0::X0<volatile void> { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}} + +void test_spec(N0::X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +namespace N0 { + template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}} + + template<> void X0<const volatile void*>::f1(const volatile void*); +} + +void test_x0_cvvoid(N0::X0<const volatile void*> 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<NonDefaultConstructible>::member; + + template<> long X0<long>::member = 17; + + template<> float X0<float>::member; + + template<> double X0<double>::member; +} + +NonDefaultConstructible &get_static_member() { + return N0::X0<NonDefaultConstructible>::member; +} + +template<> int N0::X0<int>::member; // expected-error{{originally}} + +template<> float N0::X0<float>::member = 3.14f; + +namespace N1 { + template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}} +} + +// -- member class of a class template +namespace N0 { + + template<> + struct X0<void*>::Inner { }; + + template<> + struct X0<int>::Inner { }; + + template<> + struct X0<unsigned>::Inner; + + template<> + struct X0<float>::Inner; + + template<> + struct X0<double>::Inner; // expected-note{{forward declaration}} +} + +template<> +struct N0::X0<long>::Inner { }; // expected-error{{originally}} + +template<> +struct N0::X0<float>::Inner { }; + +namespace N1 { + template<> + struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}} + + template<> + struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}} +}; + +N0::X0<void*>::Inner inner0; +N0::X0<int>::Inner inner1; +N0::X0<long>::Inner inner2; +N0::X0<float>::Inner inner3; +N0::X0<double>::Inner inner4; // expected-error{{incomplete}} + +// -- member class template of a class template +namespace N0 { + template<> + template<> + struct X0<void*>::InnerTemplate<int> { }; + + template<> template<> + struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}} + + template<> template<> + struct X0<int>::InnerTemplate<long>; + + template<> template<> + struct X0<int>::InnerTemplate<double>; +} + +template<> template<> +struct N0::X0<int>::InnerTemplate<long> { }; // okay + +template<> template<> +struct N0::X0<int>::InnerTemplate<float> { }; // expected-error{{class template specialization}} + +namespace N1 { + template<> template<> + struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}} +} + +N0::X0<void*>::InnerTemplate<int> inner_template0; +N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}} +N0::X0<int>::InnerTemplate<long> inner_template2; +N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}} + +// -- member function template of a class template +namespace N0 { + template<> + template<> + void X0<void*>::ft1(void*, const void*) { } + + template<> template<> + void X0<void*>::ft1(void *, int); + + template<> template<> + void X0<void*>::ft1(void *, unsigned); + + template<> template<> + void X0<void*>::ft1(void *, long); +} + +template<> template<> +void N0::X0<void*>::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0<void*>::ft1(void *, float) { } // expected-error{{function template specialization}} + +namespace N1 { + template<> template<> + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}} +} + + +void test_func_template(N0::X0<void *> 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<typename T> +void f(T); + +template<typename T> +struct A { }; + +struct X { + template<> friend void f<int>(int); // expected-error{{in class scope}} + template<> friend class A<int>; // expected-error{{cannot be a friend}} + + friend void f<float>(float); // okay + friend class A<float>; // 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<typename T> +struct X { + void mf1(T); + template<typename U> void mf2(T, U); // expected-note{{previous}} +}; + +template<> +void X<int>::mf1(int i = 17) // expected-error{{default}} +{ +} + +template<> template<> +void X<int>::mf2(int, int = 17) // expected-error{{default}} +{ } + +template<> template<typename U> +void X<int>::mf2(int, U = U()) // expected-error{{default}} +{ +} + +template<> +struct X<float> { + void mf1(float); +}; + +void X<float>::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 T> class X; +} + +// FIXME: this diagnostic is terrible (PR3844). +template<> class X<int> { /* ... */ }; // expected-error {{unqualified-id}} + +namespace N { + +template<> class X<char*> { /* ... */ }; // 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<typename T, typename U> +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<typename T, typename U> +T X<T, U>::value; // expected-error{{no matching constructor}} + +IntHolder &test_X_IntHolderInt(X<IntHolder, int> xih) { + xih.g(); // okay + xih.f(); // expected-note{{instantiation}} + + // FIXME: diagnostic here has incorrect reason (PR5154) + X<IntHolder, int>::Inner inner; // expected-error{{implicit default}} + + return X<IntHolder, int>::value; // expected-note{{instantiation}} +} + +// Explicitly specialize the members of X<IntHolder, long> to not cause +// problems with instantiation. +template<> +void X<IntHolder, long>::f() { } + +template<> +struct X<IntHolder, long>::Inner { + Inner() : value(17) { } + IntHolder value; +}; + +template<> +IntHolder X<IntHolder, long>::value = 17; + +IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X<IntHolder, long>::Inner inner; // okay, uses specialization + + return X<IntHolder, long>::value; // okay, uses specialization +} + +template<> +X<IntHolder, long>::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<typename T, typename U> +struct X { + void f() { + T t; + } + + void g() { } + + struct Inner { + T value; + }; + + static T value; +}; + +template<typename T, typename U> +T X<T, U>::value; + +// Explicitly specialize the members of X<IntHolder, long> to not cause +// problems with instantiation, but only provide declarations (not definitions). +template<> +void X<IntHolder, long>::f(); + +template<> +struct X<IntHolder, long>::Inner; // expected-note{{forward declaration}} + +template<> +IntHolder X<IntHolder, long>::value; + +IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X<IntHolder, long>::Inner inner; // expected-error {{incomplete}} + + return X<IntHolder, long>::value; // okay, uses specialization +} + + +template<class T> struct A { + void f(T) { /* ... */ } +}; + +template<> struct A<int> { + void f(int); +}; + +void h() { + A<int> a; + a.f(16); // A<int>::f must be defined somewhere +} + +// explicit specialization syntax not used for a member of +// explicitly specialized class template specialization +void A<int>::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<typename T> +struct X0 { + void f(); + + template<typename U> + void g(U); + + struct Nested { + }; + + static T member; +}; + +int &use_X0_int(X0<int> 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<int>::Nested nested; // expected-note{{implicit instantiation first required here}} + return X0<int>::member; // expected-note{{implicit instantiation first required here}} +} + +template<> +void X0<int>::f() { // expected-error{{after instantiation}} +} + +template<> template<> +void X0<int>::g(int) { // expected-error{{after instantiation}} +} + +template<> +struct X0<int>::Nested { }; // expected-error{{after instantiation}} + +template<> +int X0<int>::member = 17; // expected-error{{after instantiation}} + +template<> +struct X0<int> { }; // expected-error{{after instantiation}} + +// Example from the standard +template<class T> class Array { /* ... */ }; + +template<class T> void sort(Array<T>& v) { /* ... */ } + +struct String {}; + +void f(Array<String>& v) { + + sort(v); // expected-note{{required}} + // use primary template + // sort(Array<T>&), T is String +} + +template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}} +template<> void sort<>(Array<char*>& v); // OK: sort<char*> 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 T> class X { /* ... */ }; + template<class T> class Y { /* ... */ }; + template<> class X<int> { /* ... */ }; + template<> class Y<double>; + + const unsigned NumElements = 17; +} + +template<> class N::Y<double> { + int array[NumElements]; +}; |