diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp | 4 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp | 114 | ||||
-rw-r--r-- | clang/test/SemaTemplate/class-template-spec.cpp | 4 | ||||
-rw-r--r-- | clang/test/SemaTemplate/temp_class_spec_neg.cpp | 4 |
4 files changed, 121 insertions, 5 deletions
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp index f3d0709ef82..239b8aeb04e 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp @@ -1,8 +1,10 @@ -// RUN: clang-cc -fsyntax-only %s +// 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); }; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp new file mode 100644 index 00000000000..3bc0a07c96e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -0,0 +1,114 @@ +// 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}} + +// FIXME: update the remainder of this test to check for scopes properly. +// -- 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/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp index 34c616cc2f4..e4d917f7756 100644 --- a/clang/test/SemaTemplate/class-template-spec.cpp +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -85,12 +85,12 @@ namespace N { template<> struct N::B<int> { }; // okay -template<> struct N::B<float> { }; // expected-error{{class template specialization of 'B' not in namespace 'N'}} +template<> struct N::B<float> { }; // expected-error{{originally}} namespace M { template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}} - template<> struct ::A<long double>; // expected-error{{class template specialization of 'A' must occur in the global scope}} + template<> struct ::A<long double>; // expected-error{{originally}} } template<> struct N::B<char> { diff --git a/clang/test/SemaTemplate/temp_class_spec_neg.cpp b/clang/test/SemaTemplate/temp_class_spec_neg.cpp index b50bd8f634a..a029f474fc5 100644 --- a/clang/test/SemaTemplate/temp_class_spec_neg.cpp +++ b/clang/test/SemaTemplate/temp_class_spec_neg.cpp @@ -9,7 +9,7 @@ namespace N { } template<typename T> -struct N::M::A<T*> { }; // expected-error{{not in namespace}} +struct N::M::A<T*> { }; // expected-error{{originally}} // C++ [temp.class.spec]p9 // bullet 1 @@ -25,7 +25,7 @@ template <class T, T* t> struct C<T*, t>; // okay template< int X, int (*array_ptr)[X] > class A2 {}; // expected-note{{here}} int array[5]; -template< int X > class A2<X,&array> { }; // expected-error{{specializes}} +template< int X > class A2<X, &array> { }; // expected-error{{specializes}} template<typename T, int N, template<typename X> class TT> struct Test0; |