diff options
author | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
---|---|---|
committer | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
commit | be1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch) | |
tree | 1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/test/CXX/temp/temp.decls/temp.class | |
parent | c4626a62754862d20b41e8a46a3574264ea80e6d (diff) | |
parent | f1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff) |
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/test/CXX/temp/temp.decls/temp.class')
8 files changed, 395 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp new file mode 100644 index 0000000..b65e1d0 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, typename U> +struct X0 { + struct Inner; +}; + +template<typename T, typename U> +struct X0<T, U>::Inner { + T x; + U y; + + void f() { x = y; } // expected-error{{incompatible}} +}; + + +void test(int i, float f) { + X0<int, float>::Inner inner; + inner.x = 5; + inner.y = 3.4; + inner.f(); + + X0<int*, float *>::Inner inner2; + inner2.x = &i; + inner2.y = &f; + inner2.f(); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp new file mode 100644 index 0000000..f8cc009 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<typename T> struct A { + enum E : T; // expected-note {{here}} + E v; + E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}} + E g() { return E::e1; } + E h(); +}; + +A<int> a; +A<int>::E a0 = A<int>().v; +int n = A<int>::E::e1; // expected-error {{implicit instantiation of undefined member}} + +template<typename T> enum A<T>::E : T { e1, e2 }; + +// FIXME: Now that A<T>::E is defined, we are supposed to inject its enumerators +// into the already-instantiated class A<T>. This seems like a really bad idea, +// though, so we don't implement that, but what we do implement is inconsistent. +// +// Either do as the standard says, or only include enumerators lexically defined +// within the class in its scope. +A<int>::E a1 = A<int>::e1; // expected-error {{no member named 'e1' in 'A<int>'}} + +A<char>::E a2 = A<char>::e2; + +template<typename T> typename A<T>::E A<T>::h() { return e2; } +A<short>::E a3 = A<short>().h(); + + +template<typename T> struct B { + enum class E; + E v; + E f() { return E::e1; } + E g(); +}; + +B<int> b; +B<int>::E b0 = B<int>().v; + +template<typename T> enum class B<T>::E { e1, e2 }; +B<int>::E b1 = B<int>::E::e1; + +B<char>::E b2 = B<char>::E::e2; + +template<typename T> typename B<T>::E B<T>::g() { return e2; } +B<short>::E b3 = B<short>().g(); + + +// Enumeration members of class templates can be explicitly specialized. For +// unscoped enumerations, specializations must be defined before the primary +// template is, since otherwise the primary template will be implicitly +// instantiated when we parse the nested name specifier. +template<> enum A<long long>::E : long long { e3, e4 }; // expected-error {{explicit specialization of 'E' after instantiation}} expected-note {{first required here}} + +template<> enum class B<long long>::E { e3, e4 }; +B<long long>::E b4 = B<long long>::E::e4; + +B<long>::E b5; +template<> enum class B<long>::E { e5 }; +void fb5() { b5 = decltype(b5)::e5; } +B<long>::E b6 = B<long>::E::e5; + + +template<typename T> struct C { + enum class E : T; +}; + +template<> enum class C<long long>::E : long long { e3, e4 }; +C<long long>::E c0 = C<long long>::E::e3; + +C<long>::E c1; +template<> enum class C<long>::E : long { e5 }; +void fc1() { c1 = decltype(c1)::e5; } +C<long>::E c2 = C<long>::E::e5; + +template<> enum class C<int>::E : int { e6 }; +template<typename T> enum class C<T>::E : T { e0 }; +C<int>::E c3 = C<int>::E::e6; +C<int>::E c4 = C<int>::E::e0; // expected-error {{no member named 'e0' in 'C<int>::E'}} + + +// Enumeration members can't be partially-specialized. +template<typename T> enum class B<T*>::E { e5, e6 }; // expected-error {{nested name specifier for a declaration cannot depend on a template parameter}} + + +// Explicit specializations can be forward-declared. +template<typename T> +struct D { + enum class E { e1 }; +}; +template<> enum class D<int>::E; +D<int>::E d1 = D<int>::E::e1; // expected-error {{incomplete type 'D<int>::E'}} +template<> enum class D<int>::E { e2 }; +D<int>::E d2 = D<int>::E::e2; +D<char>::E d3 = D<char>::E::e1; // expected-note {{first required here}} +D<char>::E d4 = D<char>::E::e2; // expected-error {{no member named 'e2'}} +template<> enum class D<char>::E { e3 }; // expected-error {{explicit specialization of 'E' after instantiation}} + +template<> enum class D<short>::E; +struct F { + // Per C++11 [class.friend]p3, these friend declarations have no effect. + // Only classes and functions can be friends. + template<typename T> friend enum D<T>::E; + template<> friend enum D<short>::E; + + template<> friend enum D<double>::E { e3 }; // expected-error {{cannot define a type in a friend declaration}} + +private: + static const int n = 1; // expected-note {{private here}} +}; +template<> enum class D<short>::E { + e = F::n // expected-error {{private member}} +}; + +class Access { + friend class X; + + template<typename T> + class Priv { + friend class X; + + enum class E : T; + }; + + class S { + typedef int N; // expected-note {{here}} + static const int k = 3; // expected-note {{here}} + + friend class Priv<char>; + }; + + static const int k = 5; +}; + +template<> enum class Access::Priv<Access::S::N>::E + : Access::S::N { // expected-error {{private member}} + a = Access::k, // ok + b = Access::S::k // expected-error {{private member}} +}; + +template<typename T> enum class Access::Priv<T>::E : T { + c = Access::k, + d = Access::S::k +}; + +class X { + Access::Priv<int>::E a = Access::Priv<int>::E::a; + Access::Priv<char>::E c = Access::Priv<char>::E::d; + // FIXME: We should see an access error for this enumerator. + Access::Priv<short>::E b = Access::Priv<short>::E::d; +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp new file mode 100644 index 0000000..4c05c62 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct X1 { }; + +template<typename T> +struct X0 { + typedef int size_type; + typedef T value_type; + + size_type f0() const; + value_type *f1(); + X1<value_type*> f2(); +}; + +template<typename T> +typename X0<T>::size_type X0<T>::f0() const { + return 0; +} + +template<typename U> +typename X0<U>::value_type *X0<U>::f1() { + return 0; +}; + +template<typename U> +X1<typename X0<U>::value_type*> X0<U>::f2() { + return 0; +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp new file mode 100644 index 0000000..1764563 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U> // expected-note{{previous template}} +class X0 { +public: + typedef int size_type; + + X0(int); + ~X0(); + + void f0(const T&, const U&); + + T& operator[](int i) const; + + void f1(size_type) const; + void f2(size_type) const; + void f3(size_type) const; + void f4() ; + + operator T*() const; + + T value; +}; + +template<typename T, typename U> +void X0<T, U>::f0(const T&, const U&) { // expected-note{{previous definition}} +} + +template<class X, class Y> +X& X0<X, Y>::operator[](int i) const { + (void)i; + return value; +} + +template<class X, class Y> +void X0<X, Y>::f1(int) const { } + +template<class X, class Y> +void X0<X, Y>::f2(size_type) const { } + +template<class X, class Y, class Z> // expected-error{{too many template parameters}} +void X0<X, Y>::f3(size_type) const { +} + +template<class X, class Y> +void X0<Y, X>::f4() { } // expected-error{{does not refer}} + +// FIXME: error message should probably say, "redefinition of 'X0<T, U>::f0'" +// rather than just "redefinition of 'f0'" +template<typename T, typename U> +void X0<T, U>::f0(const T&, const U&) { // expected-error{{redefinition}} +} + +// Test out-of-line constructors, destructors +template<typename T, typename U> +X0<T, U>::X0(int x) : value(x) { } + +template<typename T, typename U> +X0<T, U>::~X0() { } + +// Test out-of-line conversion functions. +template<typename T, typename U> +X0<T, U>::operator T*() const { + return &value; +} + +namespace N { template <class X> class A {void a();}; } +namespace N { template <class X> void A<X>::a() {} } + +// PR5566 +template<typename T> +struct X1 { + template<typename U> + struct B { void f(); }; +}; + +template<typename T> +template<typename U> +void X1<T>::template B<U>::f() { } + +// PR5527 +template <template <class> class T> +class X2 { + template <class F> + class Bar { + void Func(); + }; +}; + +template <template <class> class T> +template <class F> +void X2<T>::Bar<F>::Func() {} + +// PR5528 +template <template <class> class T> +class X3 { + void F(); +}; + +template <template <class> class T> +void X3<T>::F() {} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp new file mode 100644 index 0000000..f09faa9 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// Test instantiation of member functions of class templates defined out-of-line +template<typename T, typename U> +struct X0 { + void f(T *t, const U &u); + void f(T *); +}; + +template<typename T, typename U> +void X0<T, U>::f(T *t, const U &u) { + *t = u; // expected-error{{not assignable}} +} + +void test_f(X0<float, int> xfi, X0<void, int> xvi, float *fp, void *vp, int i) { + xfi.f(fp, i); + xvi.f(vp, i); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp new file mode 100644 index 0000000..70c9c70 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern "C" void * malloc(int); + +template <typename T> struct A { + void *malloc(int); +}; + +template <typename T> +inline void *A<T>::malloc(int) +{ + return 0; +} + +void f() { + malloc(10); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp new file mode 100644 index 0000000..9fc4a58 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test instantiation of static data members declared out-of-line. + +template<typename T> +struct X { + static T value; +}; + +template<typename T> + T X<T>::value = 17; // expected-error{{no viable conversion}} + +struct InitOkay { + InitOkay(int) { } +}; + +struct CannotInit { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + +int &returnInt() { return X<int>::value; } +float &returnFloat() { return X<float>::value; } + +InitOkay &returnInitOkay() { return X<InitOkay>::value; } + +unsigned long sizeOkay() { return sizeof(X<CannotInit>::value); } + +CannotInit &returnError() { + return X<CannotInit>::value; // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp new file mode 100644 index 0000000..2eae112 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + static T value; +}; + +template<typename T> +T X0<T>::value = 0; // expected-error{{no viable conversion}} + +struct X1 { + X1(int); +}; + +struct X2 { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + +int& get_int() { return X0<int>::value; } +X1& get_X1() { return X0<X1>::value; } + +double*& get_double_ptr() { return X0<int*>::value; } // expected-error{{non-const lvalue reference to type 'double *' cannot bind to a value of unrelated type 'int *'}} + +X2& get_X2() { + return X0<X2>::value; // expected-note{{instantiation}} +} + +template<typename T> T x; // expected-error{{variable 'x' declared as a template}} |