summaryrefslogtreecommitdiff
path: root/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp')
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp252
1 files changed, 252 insertions, 0 deletions
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 0000000..c972bf7
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
@@ -0,0 +1,252 @@
+// RUN: %clang_cc1 -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{{does not enclose namespace}}
+}
+
+template<> void N0::f0(double); // expected-warning{{C++11 extension}}
+template<> void N0::f0(double) { }
+
+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-warning{{C++11 extension}}
+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-warning{{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-warning{{C++11 extension}}
+
+template<> float N0::X0<float>::member = 3.14f;
+
+namespace N1 {
+ template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}}
+}
+
+// -- 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-warning{{C++11 extension}}
+
+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-warning{{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-warning{{function template specialization}}
+
+namespace N1 {
+ template<> template<>
+ void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}}
+}
+
+
+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);
+}
+
+namespace PR8979 {
+ template<typename Z>
+ struct X0 {
+ template <class T, class U> class Inner;
+ struct OtherInner;
+ template<typename T, typename U> void f(Inner<T, U>&);
+
+ typedef Inner<OtherInner, OtherInner> MyInner;
+ template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}}
+ };
+}