diff options
Diffstat (limited to 'test/SemaTemplate')
56 files changed, 1687 insertions, 62 deletions
diff --git a/test/SemaTemplate/ackermann.cpp b/test/SemaTemplate/ackermann.cpp index 48fbbbb3cf1d..c936889f25f9 100644 --- a/test/SemaTemplate/ackermann.cpp +++ b/test/SemaTemplate/ackermann.cpp @@ -1,9 +1,9 @@ -// RUN: clang-cc -fsyntax-only -ftemplate-depth=1000 -verify %s +// RUN: clang-cc -fsyntax-only -verify %s // template<unsigned M, unsigned N> // struct Ackermann { // enum { -// value = M ? (N ? Ackermann<M-1, Ackermann<M-1, N-1> >::value +// value = M ? (N ? Ackermann<M-1, Ackermann<M, N-1> >::value // : Ackermann<M-1, 1>::value) // : N + 1 // }; @@ -34,4 +34,5 @@ template<> struct Ackermann<0, 0> { }; }; -int g0[Ackermann<3, 8>::value == 2045 ? 1 : -1]; +int g0[Ackermann<3, 4>::value == 125 ? 1 : -1]; + diff --git a/test/SemaTemplate/ambiguous-ovl-print.cpp b/test/SemaTemplate/ambiguous-ovl-print.cpp new file mode 100644 index 000000000000..ccdeb9bebc57 --- /dev/null +++ b/test/SemaTemplate/ambiguous-ovl-print.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f(void*, int); // expected-note{{candidate function}} +template<typename T> + void f(T*, long); // expected-note{{candidate function template}} + +void test_f(int *ip, int i) { + f(ip, i); // expected-error{{ambiguous}} +} diff --git a/test/SemaTemplate/canonical-expr-type-0x.cpp b/test/SemaTemplate/canonical-expr-type-0x.cpp new file mode 100644 index 000000000000..21552105b0ff --- /dev/null +++ b/test/SemaTemplate/canonical-expr-type-0x.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +void f(); + +// FIXME: would like to refer to the first function parameter in these test, +// but that won't work (yet). + +// Test typeof(expr) canonicalization +template<typename T, T N> +void f0(T x, decltype(f(N)) y) { } // expected-note{{previous}} + +template<typename T, T N> +void f0(T x, decltype((f)(N)) y) { } + +template<typename U, U M> +void f0(U u, decltype(f(M))) { } // expected-error{{redefinition}} diff --git a/test/SemaTemplate/canonical-expr-type.cpp b/test/SemaTemplate/canonical-expr-type.cpp new file mode 100644 index 000000000000..0580c677e627 --- /dev/null +++ b/test/SemaTemplate/canonical-expr-type.cpp @@ -0,0 +1,53 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f(); + +// Test typeof(expr) canonicalization +template<typename T> +void f0(T x, __typeof__(f(x)) y) { } // expected-note{{previous}} + +template<typename T> +void f0(T x, __typeof__((f)(x)) y) { } + +template<typename U> +void f0(U u, __typeof__(f(u))) { } // expected-error{{redefinition}} + +// Test insane typeof(expr) overload set canonicalization +void f(int); +void f(double); + +template<typename T, T N> +void f0a(T x, __typeof__(f(N)) y) { } // expected-note{{previous}} + +void f(int); + +template<typename T, T N> +void f0a(T x, __typeof__(f(N)) y) { } // expected-error{{redefinition}} \ + // expected-note{{previous}} + +void f(float); + +template<typename T, T N> +void f0a(T x, __typeof__(f(N)) y) { } // expected-error{{redefinition}} + +// Test dependently-sized array canonicalization +template<typename T, int N, int M> +void f1(T (&array)[N + M]) { } // expected-note{{previous}} + +template<typename T, int N, int M> +void f1(T (&array)[M + N]) { } + +template<typename T, int M, int N> +void f1(T (&array)[M + N]) { } // expected-error{{redefinition}} + +// Test dependently-sized extended vector type canonicalization +template<typename T, int N, int M> +struct X2 { + typedef T __attribute__((ext_vector_type(N))) type1; + typedef T __attribute__((ext_vector_type(M))) type2; + typedef T __attribute__((ext_vector_type(N))) type3; + + void f0(type1); // expected-note{{previous}} + void f0(type2); + void f0(type3); // expected-error{{redeclared}} +}; diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp index 71d8ea14be6b..e44115c748c3 100644 --- a/test/SemaTemplate/class-template-spec.cpp +++ b/test/SemaTemplate/class-template-spec.cpp @@ -1,5 +1,6 @@ // RUN: clang-cc -fsyntax-only -verify %s -template<typename T, typename U = int> struct A; // expected-note 2{{template is declared here}} +template<typename T, typename U = int> struct A; // expected-note {{template is declared here}} \ + // expected-note{{explicitly specialized}} template<> struct A<double, double>; // expected-note{{forward declaration}} @@ -19,7 +20,8 @@ int test_incomplete_specs(A<double, double> *a1, A<double> *a2) { (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}} - (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} + (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} \ + // expected-note{{first required here}} } typedef float FLOAT; @@ -49,13 +51,33 @@ struct A<char> { A<char>::A() { } +// Make sure we can see specializations defined before the primary template. +namespace N{ + template<typename T> struct A0; +} + +namespace N { + template<> + struct A0<void> { + typedef void* pointer; + }; +} + +namespace N { + template<typename T> + struct A0 { + void foo(A0<void>::pointer p = 0); + }; +} + // Diagnose specialization errors -struct A<double> { }; // expected-error{{template specialization requires 'template<>'}} +struct A<double> { }; // expected-error{{template specialization requires 'template<>'}} \ + // expected-error{{after instantiation}} template<> struct ::A<double>; namespace N { - template<typename T> struct B; // expected-note 2{{template is declared here}} + template<typename T> struct B; // expected-note 2{{explicitly specialized}} template<> struct ::N::B<char>; // okay template<> struct ::N::B<short>; // okay @@ -66,12 +88,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/test/SemaTemplate/constructor-template.cpp b/test/SemaTemplate/constructor-template.cpp new file mode 100644 index 000000000000..acd845bc2fd5 --- /dev/null +++ b/test/SemaTemplate/constructor-template.cpp @@ -0,0 +1,53 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct X0 { // expected-note{{candidate}} + X0(int); // expected-note{{candidate}} + template<typename T> X0(T); + template<typename T, typename U> X0(T*, U*); + + // PR4761 + template<typename T> X0() : f0(T::foo) {} + int f0; +}; + +void accept_X0(X0); + +void test_X0(int i, float f) { + X0 x0a(i); + X0 x0b(f); + X0 x0c = i; + X0 x0d = f; + accept_X0(i); + accept_X0(&i); + accept_X0(f); + accept_X0(&f); + X0 x0e(&i, &f); + X0 x0f(&f, &i); + + X0 x0g(f, &i); // expected-error{{no matching constructor}} +} + +template<typename T> +struct X1 { + X1(const X1&); + template<typename U> X1(const X1<U>&); +}; + +template<typename T> +struct Outer { + typedef X1<T> A; + + A alloc; + + explicit Outer(const A& a) : alloc(a) { } +}; + +void test_X1(X1<int> xi) { + Outer<int> oi(xi); + Outer<float> of(xi); +} + +// PR4655 +template<class C> struct A {}; +template <> struct A<int>{A(const A<int>&);}; +struct B { A<int> x; B(B& a) : x(a.x) {} }; diff --git a/test/SemaTemplate/copy-ctor-assign.cpp b/test/SemaTemplate/copy-ctor-assign.cpp new file mode 100644 index 000000000000..90fb0133a721 --- /dev/null +++ b/test/SemaTemplate/copy-ctor-assign.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Make sure that copy constructors and assignment operators are properly +// generated when there is a matching + +// PR5072 +template<typename T> +struct X { + template<typename U> + X(const X<U>& other) + : value(other.value + 1) { } // expected-error{{binary expression}} + + template<typename U> + X& operator=(const X<U>& other) { + value = other.value + 1; // expected-error{{binary expression}} + return *this; + } + + T value; +}; + +struct Y {}; + +X<int Y::*> test0(X<int Y::*> x) { return x; } +X<int> test1(X<long> x) { return x; } + + +X<int> test2(X<int Y::*> x) { + return x; // expected-note{{instantiation}} +} + +void test3(X<int> &x, X<int> xi, X<long> xl, X<int Y::*> xmptr) { + x = xi; + x = xl; + x = xmptr; // expected-note{{instantiation}} +}
\ No newline at end of file diff --git a/test/SemaTemplate/current-instantiation.cpp b/test/SemaTemplate/current-instantiation.cpp index 603c14016fbc..a1d9fcb5372b 100644 --- a/test/SemaTemplate/current-instantiation.cpp +++ b/test/SemaTemplate/current-instantiation.cpp @@ -69,3 +69,76 @@ struct X0 { void g8(typename ::X0<typename X0<T_type, U>::X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}} }; }; + + +template<typename T, typename U> +struct X0<T*, U*> { + typedef T T_type; + typedef U U_type; + typedef T* Tptr; + typedef U* Uptr; + + void f0(T&); // expected-note{{previous}} + void f0(typename X0::U_type&); + void f0(typename X0::T_type&); // expected-error{{redecl}} + + void f1(T&); // expected-note{{previous}} + void f1(typename X0::U_type&); + void f1(typename X0<T*, U*>::T_type&); // expected-error{{redecl}} + + void f2(T&); // expected-note{{previous}} + void f2(typename X0::U_type&); + void f2(typename X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}} + + void f3(T&); // expected-note{{previous}} + void f3(typename X0::U_type&); + void f3(typename ::X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}} + + void f4(T&); // expected-note{{previous}} + void f4(typename X0::U_type&); + void f4(typename ::X0<Tptr, Uptr>::T_type&); // expected-error{{redecl}} + + void f5(X0*); // expected-note{{previous}} + void f5(::X0<T, U>*); + void f5(::X0<T*, U*>*); // expected-error{{redecl}} + + struct X2 { + typedef T my_T_type; + + void g0(T&); // expected-note{{previous}} + void g0(typename X0::U_type&); + void g0(typename X0::T_type&); // expected-error{{redecl}} + + void g1(T&); // expected-note{{previous}} + void g1(typename X0::U_type&); + void g1(typename X0<T*, U*>::T_type&); // expected-error{{redecl}} + + void g2(T&); // expected-note{{previous}} + void g2(typename X0::U_type&); + void g2(typename X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}} + + void g3(T&); // expected-note{{previous}} + void g3(typename X0::U_type&); + void g3(typename ::X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}} + + void g4(T&); // expected-note{{previous}} + void g4(typename X0::U_type&); + void g4(typename X2::my_T_type&); // expected-error{{redecl}} + + void g5(T&); // expected-note{{previous}} + void g5(typename X0::U_type&); + void g5(typename X0::X2::my_T_type&); // expected-error{{redecl}} + + void g6(T&); // expected-note{{previous}} + void g6(typename X0::U_type&); + void g6(typename X0<T*, U*>::X2::my_T_type&); // expected-error{{redecl}} + + void g7(T&); // expected-note{{previous}} + void g7(typename X0::U_type&); + void g7(typename ::X0<typename X2::my_T_type*, U_type*>::X2::my_T_type&); // expected-error{{redecl}} + + void g8(T&); // expected-note{{previous}} + void g8(typename X0<U, T_type>::T_type&); + void g8(typename ::X0<typename X0<T_type*, U*>::X2::my_T_type*, U_type*>::X2::my_T_type&); // expected-error{{redecl}} + }; +}; diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp index f9bb44ecb9c0..33677aab73ac 100644 --- a/test/SemaTemplate/default-arguments.cpp +++ b/test/SemaTemplate/default-arguments.cpp @@ -22,3 +22,23 @@ template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member na template struct p<bool>; // expected-note {{in instantiation of default argument for 'p<bool>' required here}} template struct p<int>; + +// PR5187 +template<typename T, typename U> +struct A; + +template<typename T, typename U = T> +struct A; + +template<typename T, typename U> +struct A { + void f(A<T>); +}; + +template<typename T> +struct B { }; + +template<> +struct B<void> { + typedef B<void*> type; +}; diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp new file mode 100644 index 000000000000..575283ed8b51 --- /dev/null +++ b/test/SemaTemplate/default-expr-arguments.cpp @@ -0,0 +1,86 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +class C { C(int a0 = 0); }; + +template<> +C<char>::C(int a0); + +struct S { }; + +template<typename T> void f1(T a, T b = 10) { } // expected-error{{cannot initialize 'b' with an rvalue of type 'int'}} + +template<typename T> void f2(T a, T b = T()) { } + +template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid operands to binary expression ('struct S' and 'struct S')}} + +void g() { + f1(10); + f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1<struct S>' required here}} + + f2(10); + f2(S()); + + f3(10); + f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<struct S>' required here}} +} + +template<typename T> struct F { + F(T t = 10); // expected-error{{cannot initialize 't' with an rvalue of type 'int'}} + void f(T t = 10); // expected-error{{cannot initialize 't' with an rvalue of type 'int'}} +}; + +struct FD : F<int> { }; + +void g2() { + F<int> f; + FD fd; +} + +void g3(F<int> f, F<struct S> s) { + f.f(); + s.f(); // expected-note{{in instantiation of default function argument expression for 'f<struct S>' required here}} + + F<int> f2; + F<S> s2; // expected-note{{in instantiation of default function argument expression for 'F<struct S>' required here}} +} + +template<typename T> struct G { + G(T) {} +}; + +void s(G<int> flags = 10) { } + +// Test default arguments +template<typename T> +struct X0 { + void f(T = T()); // expected-error{{no matching}} +}; + +template<typename U> +void X0<U>::f(U) { } + +void test_x0(X0<int> xi) { + xi.f(); + xi.f(17); +} + +struct NotDefaultConstructible { // expected-note{{candidate}} + NotDefaultConstructible(int); // expected-note{{candidate}} +}; + +void test_x0_not_default_constructible(X0<NotDefaultConstructible> xn) { + xn.f(NotDefaultConstructible(17)); + xn.f(42); + xn.f(); // expected-note{{in instantiation of default function argument}} +} + +template<typename T> +struct X1 { + typedef T value_type; + X1(const value_type& value = value_type()); +}; + +void test_X1() { + X1<int> x1; +} diff --git a/test/SemaTemplate/dependent-base-member-init.cpp b/test/SemaTemplate/dependent-base-member-init.cpp new file mode 100644 index 000000000000..b3d707b632b1 --- /dev/null +++ b/test/SemaTemplate/dependent-base-member-init.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR4381 +template<class T> struct X {}; +template<typename T> struct Y : public X<T>::X { }; + +// PR4621 +class A1 { + A1(int x) {} +}; +template<class C> class B1 : public A1 { + B1(C x) : A1(x.x) {} +}; +class A2 { A2(int x, int y); }; +template <class C> class B2 { + A2 x; + B2(C x) : x(x.x, x.y) {} +}; +template <class C> class B3 { + C x; + B3() : x(1,2) {} +}; + +// PR4627 +template<typename _Container> class insert_iterator { + _Container* container; + insert_iterator(_Container& __x) : container(&__x) {} +}; + +// PR4763 +template<typename T> struct s0 {}; +template<typename T> struct s0_traits {}; +template<typename T> struct s1 : s0<typename s0_traits<T>::t0> { + s1() {} +}; + diff --git a/test/SemaTemplate/dependent-type-identity.cpp b/test/SemaTemplate/dependent-type-identity.cpp index 739cb7f39fa3..b7c9040e6cb5 100644 --- a/test/SemaTemplate/dependent-type-identity.cpp +++ b/test/SemaTemplate/dependent-type-identity.cpp @@ -59,7 +59,7 @@ struct X1 { void f6(typename N::X2<U>::template apply<U> *); void f6(typename N::X2<U>::template apply<T> *); void f6(typename ::N::X2<type>::template apply<U_type> *); // expected-error{{redeclar}} - + void f7(typename N::X2<T>::template apply<U> *); // expected-note{{previous}} void f7(typename N::X2<U>::template apply<U> *); void f7(typename N::X2<U>::template apply<T> *); diff --git a/test/SemaTemplate/destructor-template.cpp b/test/SemaTemplate/destructor-template.cpp new file mode 100644 index 000000000000..a7c8d247f021 --- /dev/null +++ b/test/SemaTemplate/destructor-template.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename A> class s0 { + + template<typename B> class s1 : public s0<A> { + ~s1() {} + s0<A> ms0; + }; + +}; + + diff --git a/test/SemaTemplate/example-dynarray.cpp b/test/SemaTemplate/example-dynarray.cpp index 680ee04ba18e..0b8d605b623d 100644 --- a/test/SemaTemplate/example-dynarray.cpp +++ b/test/SemaTemplate/example-dynarray.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc -fsyntax-only -verify %s +// RUN: clang %s -o %t #include <stddef.h> #include <stdlib.h> #include <assert.h> @@ -24,6 +24,9 @@ public: } ~dynarray() { + for (unsigned I = 0, N = size(); I != N; ++I) + Start[I].~T(); + free(Start); } @@ -33,7 +36,9 @@ public: for (unsigned I = 0, N = other.size(); I != N; ++I) new (NewStart + I) T(other[I]); - // FIXME: destroy everything in Start + for (unsigned I = 0, N = size(); I != N; ++I) + Start[I].~T(); + free(Start); Start = NewStart; Last = End = NewStart + other.size(); @@ -43,33 +48,11 @@ public: unsigned size() const { return Last - Start; } unsigned capacity() const { return End - Start; } - void push_back(const T& value) { - if (Last == End) { - unsigned NewCapacity = capacity() * 2; - if (NewCapacity == 0) - NewCapacity = 4; - - T* NewStart = (T*)malloc(sizeof(T) * NewCapacity); - - unsigned Size = size(); - for (unsigned I = 0; I != Size; ++I) - new (NewStart + I) T(Start[I]); - - // FIXME: destruct old values - free(Start); - - Start = NewStart; - Last = Start + Size; - End = Start + NewCapacity; - } - - new (Last) T(value); - ++Last; - } - + void push_back(const T& value); + void pop_back() { - // FIXME: destruct old value --Last; + Last->~T(); } T& operator[](unsigned Idx) { @@ -108,6 +91,32 @@ public: T* Start, *Last, *End; }; +template<typename T> +void dynarray<T>::push_back(const T& value) { + if (Last == End) { + unsigned NewCapacity = capacity() * 2; + if (NewCapacity == 0) + NewCapacity = 4; + + T* NewStart = (T*)malloc(sizeof(T) * NewCapacity); + + unsigned Size = size(); + for (unsigned I = 0; I != Size; ++I) + new (NewStart + I) T(Start[I]); + + for (unsigned I = 0, N = size(); I != N; ++I) + Start[I].~T(); + free(Start); + + Start = NewStart; + Last = Start + Size; + End = Start + NewCapacity; + } + + new (Last) T(value); + ++Last; +} + struct Point { Point() { x = y = z = 0.0; } Point(const Point& other) : x(other.x), y(other.y), z(other.z) { } diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp new file mode 100644 index 000000000000..b9a4ad282b9f --- /dev/null +++ b/test/SemaTemplate/explicit-instantiation.cpp @@ -0,0 +1,75 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template void *; // expected-error{{expected unqualified-id}} + +template typedef void f0; // expected-error{{explicit instantiation of typedef}} + +int v0; // expected-note{{refers here}} +template int v0; // expected-error{{does not refer}} + +template<typename T> +struct X0 { + static T value; + + T f0(T x) { + return x + 1; // expected-error{{invalid operands}} + } + T* f0(T*, T*); + + template<typename U> + T f0(T, U); +}; + +template int X0<int>::value; + +struct NotDefaultConstructible { + NotDefaultConstructible(int); +}; + +template NotDefaultConstructible X0<NotDefaultConstructible>::value; + +template int X0<int>::f0(int); +template int* X0<int>::f0(int*, int*); +template int X0<int>::f0(int, float); + +template int X0<int>::f0(int) const; // expected-error{{does not refer}} +template int* X0<int>::f0(int*, float*); // expected-error{{does not refer}} + +struct X1 { }; +typedef int X1::*MemPtr; + +template MemPtr X0<MemPtr>::f0(MemPtr); // expected-note{{requested here}} + +struct X2 { + int f0(int); // expected-note{{refers here}} + + template<typename T> T f1(T); + template<typename T> T* f1(T*); + + template<typename T, typename U> void f2(T, U*); // expected-note{{candidate}} + template<typename T, typename U> void f2(T*, U); // expected-note{{candidate}} +}; + +template int X2::f0(int); // expected-error{{not an instantiation}} + +template int *X2::f1(int *); // okay + +template void X2::f2(int *, int *); // expected-error{{ambiguous}} + + +template<typename T> void print_type(); + +template void print_type<int>(); +template void print_type<float>(); + +template<typename T> void print_type(T*); + +template void print_type(int*); +template void print_type<int>(float*); // expected-error{{does not refer}} + +void print_type(double*); +template void print_type<double>(double*); + +// PR5069 +template<int I> void foo0 (int (&)[I + 1]) { } +template void foo0<2> (int (&)[3]); diff --git a/test/SemaTemplate/explicit-specialization-member.cpp b/test/SemaTemplate/explicit-specialization-member.cpp new file mode 100644 index 000000000000..197dae5a15af --- /dev/null +++ b/test/SemaTemplate/explicit-specialization-member.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> +struct X0 { + typedef T* type; + + void f0(T); + void f1(type); +}; + +template<> void X0<char>::f0(char); +template<> void X0<char>::f1(type); diff --git a/test/SemaTemplate/ext-vector-type.cpp b/test/SemaTemplate/ext-vector-type.cpp index d6c02bb629ff..b6aebc102fb4 100644 --- a/test/SemaTemplate/ext-vector-type.cpp +++ b/test/SemaTemplate/ext-vector-type.cpp @@ -4,7 +4,7 @@ struct make1 { typedef T __attribute__((ext_vector_type(Length))) type; }; -int test_make1() { +void test_make1() { make1<int, 5>::type x; x.x = 4; } diff --git a/test/SemaTemplate/extern-templates.cpp b/test/SemaTemplate/extern-templates.cpp new file mode 100644 index 000000000000..28fda1a11e6b --- /dev/null +++ b/test/SemaTemplate/extern-templates.cpp @@ -0,0 +1,66 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +class X0 { +public: + void f(T t); + + struct Inner { + void g(T t); + }; +}; + +template<typename T> +void X0<T>::f(T t) { + t = 17; // expected-error{{incompatible}} +} + +extern template class X0<int>; + +extern template class X0<int*>; + +template<typename T> +void X0<T>::Inner::g(T t) { + t = 17; // expected-error{{incompatible}} +} + +void test_intptr(X0<int*> xi, X0<int*>::Inner xii) { + xi.f(0); + xii.g(0); +} + +// FIXME: we would like the notes to point to the explicit instantiation at the +// bottom. +extern template class X0<long*>; // expected-note 2{{instantiation}} + +void test_longptr(X0<long*> xl, X0<long*>::Inner xli) { + xl.f(0); + xli.g(0); +} + +template class X0<long*>; + +template<typename T> +class X1 { +public: + void f(T t) { t += 2; } + + void g(T t); +}; + +template<typename T> +void X1<T>::g(T t) { + t += 2; +} + +extern template class X1<void*>; + +void g_X1(X1<void*> x1, void *ptr) { + x1.g(ptr); +} + +extern template void X1<const void*>::g(const void*); + +void g_X1_2(X1<const void *> x1, const void *ptr) { + x1.g(ptr); +} diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp new file mode 100644 index 000000000000..761c13076d2a --- /dev/null +++ b/test/SemaTemplate/friend-template.cpp @@ -0,0 +1,64 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR5057 +namespace std { + class X { + public: + template<typename T> + friend struct Y; + }; +} + +namespace std { + template<typename T> + struct Y + { + }; +} + + +namespace N { + template<typename T> void f1(T) { } // expected-note{{here}} + + class X { + template<typename T> friend void f0(T); + template<typename T> friend void f1(T); + }; + + template<typename T> void f0(T) { } + template<typename T> void f1(T) { } // expected-error{{redefinition}} +} + +// PR4768 +template<typename T> +struct X0 { + template<typename U> friend struct X0; +}; + +template<typename T> +struct X0<T*> { + template<typename U> friend struct X0; +}; + +template<> +struct X0<int> { + template<typename U> friend struct X0; +}; + +template<typename T> +struct X1 { + template<typename U> friend void f2(U); + template<typename U> friend void f3(U); +}; + +template<typename U> void f2(U); + +X1<int> x1i; + +template<> void f2(int); + +// FIXME: Should this declaration of f3 be required for the specialization of +// f3<int> (further below) to work? GCC and EDG don't require it, we do... +template<typename U> void f3(U); + +template<> void f3(int); diff --git a/test/SemaTemplate/friend.cpp b/test/SemaTemplate/friend.cpp new file mode 100644 index 000000000000..27299523862e --- /dev/null +++ b/test/SemaTemplate/friend.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> struct A { + struct B { }; + + friend struct B; +}; + +void f() { + A<int>::B b; +} + +struct C0 { + friend struct A<int>; +}; diff --git a/test/SemaTemplate/fun-template-def.cpp b/test/SemaTemplate/fun-template-def.cpp index 8833ef4ddc1d..dee425007898 100644 --- a/test/SemaTemplate/fun-template-def.cpp +++ b/test/SemaTemplate/fun-template-def.cpp @@ -10,8 +10,13 @@ namespace std { class type_info {}; } struct dummy {}; +template<typename T> +int f0(T x) { + return (sizeof(x) == sizeof(int))? 0 : (sizeof(x) == sizeof(double))? 1 : 2; +} + template <typename T, typename U> -T f(T t1, U u1, int i1) +T f1(T t1, U u1, int i1) { T t2 = i1; t2 = i1 + u1; diff --git a/test/SemaTemplate/function-template-specialization.cpp b/test/SemaTemplate/function-template-specialization.cpp new file mode 100644 index 000000000000..90e38cc882fe --- /dev/null +++ b/test/SemaTemplate/function-template-specialization.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<int N> void f0(int (&array)[N]); + +// Simple function template specialization (using overloading) +template<> void f0(int (&array)[1]); + +void test_f0() { + int iarr1[1]; + f0(iarr1); +} + +// Function template specialization where there are no matches +template<> void f0(char (&array)[1]); // expected-error{{no function template matches}} +template<> void f0<2>(int (&array)[2]) { } + +// Function template specialization that requires partial ordering +template<typename T, int N> void f1(T (&array)[N]); // expected-note{{matches}} +template<int N> void f1(int (&array)[N]); // expected-note{{matches}} + +template<> void f1(float (&array)[1]); +template<> void f1(int (&array)[1]); + +// Function template specialization that results in an ambiguity +template<typename T> void f1(T (&array)[17]); // expected-note{{matches}} +template<> void f1(int (&array)[17]); // expected-error{{ambiguous}} + +// Resolving that ambiguity with explicitly-specified template arguments. +template<int N> void f2(double (&array)[N]); +template<typename T> void f2(T (&array)[42]); + +template<> void f2<double>(double (&array)[42]); +template<> void f2<42>(double (&array)[42]); + +void f2<25>(double (&array)[25]); // expected-error{{specialization}} diff --git a/test/SemaTemplate/implicit-instantiation-1.cpp b/test/SemaTemplate/implicit-instantiation-1.cpp index b8f9622001e1..d04bbd848407 100644 --- a/test/SemaTemplate/implicit-instantiation-1.cpp +++ b/test/SemaTemplate/implicit-instantiation-1.cpp @@ -22,4 +22,4 @@ void test_add(char *cp, int i, int *ip) { char* cp2 = add(cp, i); add(cp, cp); // expected-note{{instantiation of}} (void)sizeof(add(ip, ip)); -}
\ No newline at end of file +} diff --git a/test/SemaTemplate/injected-class-name.cpp b/test/SemaTemplate/injected-class-name.cpp index c5f826d849ca..f9674c39a58b 100644 --- a/test/SemaTemplate/injected-class-name.cpp +++ b/test/SemaTemplate/injected-class-name.cpp @@ -19,7 +19,7 @@ X<float>::X<int> xi = x; // [temp.local]p1: -// FIXME: test non-type and template template parameters +// FIXME: test template template parameters template<typename T, typename U> struct X0 { typedef T type; @@ -38,3 +38,11 @@ struct X0 { void f2(X0&); void f2(const ::X0<type, U_type2>&); // expected-error{{redecl}} }; + +template<typename T, T N> +struct X1 { + void f0(const X1&); // expected-note{{here}} + void f0(X1&); + void f0(const X1<T, N>&); // expected-error{{redecl}} +}; + diff --git a/test/SemaTemplate/instantiate-anonymous-union.cpp b/test/SemaTemplate/instantiate-anonymous-union.cpp new file mode 100644 index 000000000000..375c1da3ca59 --- /dev/null +++ b/test/SemaTemplate/instantiate-anonymous-union.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only %s -Wall + +template <typename T> class A { struct { }; }; + +A<int> a0; + +template <typename T> struct B { + union { + int a; + void* b; + }; + + void f() { + a = 10; + b = 0; + } +}; + +B<int> b0; + +template <typename T> struct C { + union { + int a; + void* b; + }; + + C(int a) : a(a) { } + C(void* b) : b(b) { } +}; + +C<int> c0(0); diff --git a/test/SemaTemplate/instantiate-cast.cpp b/test/SemaTemplate/instantiate-cast.cpp index d99f3e556602..6b3fc6e12534 100644 --- a/test/SemaTemplate/instantiate-cast.cpp +++ b/test/SemaTemplate/instantiate-cast.cpp @@ -1,6 +1,6 @@ // RUN: clang-cc -fsyntax-only -verify %s -struct A { int x; }; +struct A { int x; }; class Base { public: @@ -23,7 +23,7 @@ struct Constructible { template<typename T, typename U> struct CStyleCast0 { void f(T t) { - (void)((U)t); // FIXME:ugly expected-error{{operand}} + (void)((U)t); // expected-error{{C-style cast from 'struct A' to 'int'}} } }; @@ -36,7 +36,7 @@ template struct CStyleCast0<A, int>; // expected-note{{instantiation}} template<typename T, typename U> struct StaticCast0 { void f(T t) { - (void)static_cast<U>(t); // expected-error{{static_cast}} + (void)static_cast<U>(t); // expected-error{{static_cast from 'int' to 'struct A' is not allowed}} } }; @@ -89,7 +89,7 @@ template struct ConstCast0<int const *, float *>; // expected-note{{instantiatio template<typename T, typename U> struct FunctionalCast1 { void f(T t) { - (void)U(t); // FIXME:ugly expected-error{{operand}} + (void)U(t); // expected-error{{functional-style cast from 'struct A' to 'int'}} } }; diff --git a/test/SemaTemplate/instantiate-deeply.cpp b/test/SemaTemplate/instantiate-deeply.cpp new file mode 100644 index 000000000000..27e430be5cbe --- /dev/null +++ b/test/SemaTemplate/instantiate-deeply.cpp @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -Wall -verify %s + +template<typename a> struct A { + template <typename b> struct B { + template <typename c> struct C { + template <typename d> struct D { + template <typename e> struct E { + e field; + E() : field(0) { + d v1 = 4; + c v2 = v1 * v1; + b v3 = 8; + a v4 = v3 * v3; + field += v2 + v4; + } + }; + }; + }; + }; +}; + +A<int>::B<int>::C<int>::D<int>::E<int> global; diff --git a/test/SemaTemplate/instantiate-expr-2.cpp b/test/SemaTemplate/instantiate-expr-2.cpp index 80f403ed56fe..146e63c5bb00 100644 --- a/test/SemaTemplate/instantiate-expr-2.cpp +++ b/test/SemaTemplate/instantiate-expr-2.cpp @@ -130,3 +130,51 @@ struct X0 { void test_X0(X0<int> x, IntegralConstant<int, sizeof(int)> ic) { x.f(5,ic); } + +namespace N8 { + struct X { + X operator+(const X&) const; + }; + + template<typename T> + T test_plus(const T* xp, const T& x, const T& y) { + x.operator+(y); + return xp->operator+(y); + } + + void test_test_plus(X x) { + test_plus(&x, x, x); + } +} + +namespace N9 { + struct A { + bool operator==(int value); + }; + + template<typename T> struct B { + bool f(A a) { + return a == 1; + } + }; + + template struct B<int>; +} + +namespace N10 { + template <typename T> + class A { + struct X { }; + + public: + ~A() { + f(reinterpret_cast<X *>(0), reinterpret_cast<X *>(0)); + } + + private: + void f(X *); + void f(X *, X *); + }; + + template class A<int>; +} diff --git a/test/SemaTemplate/instantiate-expr-5.cpp b/test/SemaTemplate/instantiate-expr-5.cpp new file mode 100644 index 000000000000..b42c0fb2aaf8 --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-5.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only %s + +template <class A> int x(A x) { return x++; } +int y() { return x<int>(1); } diff --git a/test/SemaTemplate/instantiate-friend-class.cpp b/test/SemaTemplate/instantiate-friend-class.cpp new file mode 100644 index 000000000000..9a4a73cc8a52 --- /dev/null +++ b/test/SemaTemplate/instantiate-friend-class.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR4794 + +template <class T> class X +{ + friend class Y; +}; +X<int> y; + diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp index 023cc5437f69..2749ec24401b 100644 --- a/test/SemaTemplate/instantiate-function-1.cpp +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -140,7 +140,7 @@ template<typename T> struct Member0 { tp->f; this->f; - this.f; // expected-error{{member reference base type 'Member0<T> *const' is not a structure or union}} + this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}} } }; diff --git a/test/SemaTemplate/instantiate-function-1.mm b/test/SemaTemplate/instantiate-function-1.mm index aef2d9dbb7eb..be995e7ff615 100644 --- a/test/SemaTemplate/instantiate-function-1.mm +++ b/test/SemaTemplate/instantiate-function-1.mm @@ -1,3 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// XFAIL + template<typename T> struct Member0 { void f(T t) { t; diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp new file mode 100644 index 000000000000..870b27537fce --- /dev/null +++ b/test/SemaTemplate/instantiate-init.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct X0 { // expected-note 4{{candidate}} + X0(int*, float*); // expected-note 4{{candidate}} +}; + +template<typename T, typename U> +X0 f0(T t, U u) { + X0 x0(t, u); // expected-error{{no matching}} + return X0(t, u); // expected-error{{no matching}} +} + +void test_f0(int *ip, float *fp, double *dp) { + f0(ip, fp); + f0(ip, dp); // expected-note{{instantiation}} +} + +template<typename Ret, typename T, typename U> +Ret f1(Ret *retty, T t, U u) { + Ret r0(t, u); // expected-error{{no matching}} + return Ret(t, u); // expected-error{{no matching}} +} + +void test_f1(X0 *x0, int *ip, float *fp, double *dp) { + f1(x0, ip, fp); + f1(x0, ip, dp); // expected-note{{instantiation}} +} + diff --git a/test/SemaTemplate/instantiate-member-initializers.cpp b/test/SemaTemplate/instantiate-member-initializers.cpp new file mode 100644 index 000000000000..6fc70429a9d3 --- /dev/null +++ b/test/SemaTemplate/instantiate-member-initializers.cpp @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -Wall -verify %s + +template<typename T> struct A { + A() : a(1) { } // expected-error{{incompatible type passing 'int', expected 'void *'}} + + T a; +}; + +A<int> a0; +A<void*> a1; // expected-note{{in instantiation of member function 'A<void *>::A' requested here}} + +template<typename T> struct B { + // FIXME: This should warn about initialization order + B() : b(1), a(2) { } + + int a; + int b; +}; + +B<int> b0; + +template <class T> struct AA { AA(int); }; +template <class T> class BB : public AA<T> { + BB() : AA<T>(1) {} +}; +BB<int> x; diff --git a/test/SemaTemplate/instantiate-member-template.cpp b/test/SemaTemplate/instantiate-member-template.cpp new file mode 100644 index 000000000000..36f3b6fd490d --- /dev/null +++ b/test/SemaTemplate/instantiate-member-template.cpp @@ -0,0 +1,105 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +struct X0 { + template<typename U> T f0(U); + template<typename U> U& f1(T*, U); // expected-error{{pointer to a reference}} \ + // expected-note{{candidate}} +}; + +X0<int> x0i; +X0<void> x0v; +X0<int&> x0ir; // expected-note{{instantiation}} + +void test_X0(int *ip, double *dp) { + X0<int> xi; + int i1 = xi.f0(ip); + double *&dpr = xi.f1(ip, dp); + xi.f1(dp, dp); // expected-error{{no matching}} + + X0<void> xv; + double *&dpr2 = xv.f1(ip, dp); +} + +template<typename T> +struct X1 { + template<typename U> + struct Inner0 { + U x; + T y; // expected-error{{void}} + }; + + template<typename U> + struct Inner1 { + U x; // expected-error{{void}} + T y; + }; + + template<typename U> + struct Inner2 { + struct SuperInner { + U z; // expected-error{{void}} + }; + }; + + template<typename U> + struct Inner3 { + void f0(T t, U u) { + (void)(t + u); // expected-error{{invalid operands}} + } + + template<typename V> + V f1(T t, U u, V) { + return t + u; // expected-error{{incompatible type}} + } + }; + + template<typename U> + struct Inner4; +}; + +template<typename T> +template<typename U> +struct X1<T>::Inner4 { + template<typename V> + V f2(T t, U u, V); + + static U value; +}; + +template<typename T> +template<typename U> +U X1<T>::Inner4<U>::value; // expected-error{{reference variable}} + +template<typename T> +template<typename U> +template<typename V> +V X1<T>::Inner4<U>::f2(T t, U u, V) { + return t + u; // expected-error{{incompatible type}} +} + +void test_X1(int *ip, int i, double *dp) { + X1<void>::Inner0<int> *xvip; // okay + X1<void>::Inner0<int> xvi; // expected-note{{instantiation}} + + X1<int>::Inner1<void> *xivp; // okay + X1<int>::Inner1<void> xiv; // expected-note{{instantiation}} + + X1<int>::Inner2<void>::SuperInner *xisivp; // okay + X1<int>::Inner2<void>::SuperInner xisiv; // expected-note{{instantiation}} + + X1<int*>::Inner3<int> id3; + id3.f0(ip, i); + id3.f0(dp, i); // expected-error{{incompatible type}} + id3.f1(ip, i, ip); + id3.f1(ip, i, dp); // expected-note{{instantiation}} + + X1<int*>::Inner3<double*> id3b; + id3b.f0(ip, dp); // expected-note{{instantiation}} + + X1<int*>::Inner4<int> id4; + id4.f2(ip, i, dp); // expected-note{{instantiation}} + + X1<int*>::Inner4<int>::value = 17; + i = X1<int*>::Inner4<int&>::value; // expected-note{{instantiation}} +} diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp index daea7465dc12..f7c09ef87900 100644 --- a/test/SemaTemplate/instantiate-method.cpp +++ b/test/SemaTemplate/instantiate-method.cpp @@ -72,3 +72,12 @@ void test_converts_to(ConvertsTo<int> ci, ConvertsTo<int *> cip) { int i = ci; int *ip = cip; } + +// PR4660 +template<class T> struct A0 { operator T*(); }; +template<class T> struct A1; + +int *a(A0<int> &x0, A1<int> &x1) { + int *y0 = x0; + int *y1 = x1; // expected-error{{initializing}} +} diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp index 99e6b9cc06c3..96fa34cc2aff 100644 --- a/test/SemaTemplate/instantiate-static-var.cpp +++ b/test/SemaTemplate/instantiate-static-var.cpp @@ -16,3 +16,25 @@ class Y { }; Y<float> fy; // expected-note{{in instantiation of template class 'class Y<float>' requested here}} + + +// out-of-line static member variables + +template<typename T> +struct Z { + static T value; +}; + +template<typename T> +T Z<T>::value; // expected-error{{no matching constructor}} + +struct DefCon {}; + +struct NoDefCon { + NoDefCon(const NoDefCon&); +}; + +void test() { + DefCon &DC = Z<DefCon>::value; + NoDefCon &NDC = Z<NoDefCon>::value; // expected-note{{instantiation}} +} diff --git a/test/SemaTemplate/instantiate-typedef.cpp b/test/SemaTemplate/instantiate-typedef.cpp index d30309cc86ca..e092b531582b 100644 --- a/test/SemaTemplate/instantiate-typedef.cpp +++ b/test/SemaTemplate/instantiate-typedef.cpp @@ -12,5 +12,5 @@ add_pointer<float>::type test2(int * ptr) { } add_pointer<int&>::type // expected-note{{in instantiation of template class 'struct add_pointer<int &>' requested here}} \ -// expected-error {{unknown type name 'type'}} +// expected-error {{no type named 'type' in 'struct add_pointer<int &>'}} test3(); diff --git a/test/SemaTemplate/instantiate-using-decl.cpp b/test/SemaTemplate/instantiate-using-decl.cpp new file mode 100644 index 000000000000..fd9010fa4bbb --- /dev/null +++ b/test/SemaTemplate/instantiate-using-decl.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +struct A { + void f(); +}; + +template<typename T> +struct B : A<T> { + using A<T>::f; + + void g() { + f(); + } +}; + +template struct B<int>; diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp new file mode 100644 index 000000000000..f4922e8ff520 --- /dev/null +++ b/test/SemaTemplate/member-access-expr.cpp @@ -0,0 +1,77 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> +void call_f0(T x) { + x.Base::f0(); +} + +struct Base { + void f0(); +}; + +struct X0 : Base { + typedef Base CrazyBase; +}; + +void test_f0(X0 x0) { + call_f0(x0); +} + +template<typename TheBase, typename T> +void call_f0_through_typedef(T x) { + typedef TheBase Base2; + x.Base2::f0(); +} + +void test_f0_through_typedef(X0 x0) { + call_f0_through_typedef<Base>(x0); +} + +template<typename TheBase, typename T> +void call_f0_through_typedef2(T x) { + typedef TheBase CrazyBase; // expected-note{{current scope}} + x.CrazyBase::f0(); // expected-error{{ambiguous}} \ + // expected-error 2{{no member named}} +} + +struct OtherBase { }; + +struct X1 : Base, OtherBase { + typedef OtherBase CrazyBase; // expected-note{{object type}} +}; + +void test_f0_through_typedef2(X0 x0, X1 x1) { + call_f0_through_typedef2<Base>(x0); + call_f0_through_typedef2<OtherBase>(x1); // expected-note{{instantiation}} + call_f0_through_typedef2<Base>(x1); // expected-note{{instantiation}} +} + + +struct X2 { + operator int() const; +}; + +template<typename T, typename U> +T convert(const U& value) { + return value.operator T(); // expected-error{{operator long}} +} + +void test_convert(X2 x2) { + convert<int>(x2); + convert<long>(x2); // expected-note{{instantiation}} +} + +template<typename T> +void destruct(T* ptr) { + ptr->~T(); +} + +template<typename T> +void destruct_intptr(int *ip) { + ip->~T(); +} + +void test_destruct(X2 *x2p, int *ip) { + destruct(x2p); + destruct(ip); + destruct_intptr<int>(ip); +}
\ No newline at end of file diff --git a/test/SemaTemplate/member-function-template.cpp b/test/SemaTemplate/member-function-template.cpp new file mode 100644 index 000000000000..83bf16c69004 --- /dev/null +++ b/test/SemaTemplate/member-function-template.cpp @@ -0,0 +1,51 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct X { + template<typename T> T& f0(T); + + void g0(int i, double d) { + int &ir = f0(i); + double &dr = f0(d); + } + + template<typename T> T& f1(T); + template<typename T, typename U> U& f1(T, U); + + void g1(int i, double d) { + int &ir1 = f1(i); + int &ir2 = f1(d, i); + int &ir3 = f1(i, i); + } +}; + +void test_X_f0(X x, int i, float f) { + int &ir = x.f0(i); + float &fr = x.f0(f); +} + +void test_X_f1(X x, int i, float f) { + int &ir1 = x.f1(i); + int &ir2 = x.f1(f, i); + int &ir3 = x.f1(i, i); +} + +void test_X_f0_address() { + int& (X::*pm1)(int) = &X::f0; + float& (X::*pm2)(float) = &X::f0; +} + +void test_X_f1_address() { + int& (X::*pm1)(int) = &X::f1; + float& (X::*pm2)(float) = &X::f1; + int& (X::*pm3)(float, int) = &X::f1; +} + +void test_X_f0_explicit(X x, int i, long l) { + int &ir1 = x.f0<int>(i); + int &ir2 = x.f0<>(i); + long &il1 = x.f0<long>(i); +} + +// PR4608 +class A { template <class x> x a(x z) { return z+y; } int y; }; + diff --git a/test/SemaTemplate/member-initializers.cpp b/test/SemaTemplate/member-initializers.cpp new file mode 100644 index 000000000000..62077fabc721 --- /dev/null +++ b/test/SemaTemplate/member-initializers.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> struct A { + A() : j(10), i(10) { } + + int i; + int j; +}; + +template<typename T> struct B : A<T> { + B() : A<T>() { } +}; + diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp new file mode 100644 index 000000000000..20437aee39dc --- /dev/null +++ b/test/SemaTemplate/member-template-access-expr.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename U, typename T> +U f0(T t) { + return t.template get<U>(); +} + +template<typename U, typename T> +int &f1(T t) { + // FIXME: When we pretty-print this, we lose the "template" keyword. + return t.U::template get<int&>(); +} + +struct X { + template<typename T> T get(); +}; + +void test_f0(X x) { + int i = f0<int>(x); + int &ir = f0<int&>(x); +} + +struct XDerived : public X { +}; + +void test_f1(XDerived xd) { + // FIXME: Not quite functional yet. +// int &ir = f1<X>(xd); +} + diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp index 9261ed6a6c96..471b2ad3fae6 100644 --- a/test/SemaTemplate/metafun-apply.cpp +++ b/test/SemaTemplate/metafun-apply.cpp @@ -35,7 +35,8 @@ void test() { apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \ // FIXME: expected-error{{unexpected type name 'type': expected expression}} - apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} + apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \ + // FIXME: expected-error{{unexpected type name 'type': expected expression}} } diff --git a/test/SemaTemplate/nested-linkage.cpp b/test/SemaTemplate/nested-linkage.cpp new file mode 100644 index 000000000000..ffe9adc927d6 --- /dev/null +++ b/test/SemaTemplate/nested-linkage.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +extern "C" { extern "C++" { template<class C> C x(); } } diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp index 84b1d35ba91d..5ee2c9954005 100644 --- a/test/SemaTemplate/nested-template.cpp +++ b/test/SemaTemplate/nested-template.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify %s - class A; class S { @@ -14,3 +13,91 @@ public: int i; S::A<int>::Nested::type *ip = &i; +template<typename T> +struct Outer { + template<typename U> + class Inner0; + + template<typename U> + class Inner1 { + struct ReallyInner; + + T foo(U); + template<typename V> T bar(V); + template<typename V> T* bar(V); + + static T value1; + static U value2; + }; +}; + +template<typename X> +template<typename Y> +class Outer<X>::Inner0 { +public: + void f(X, Y); +}; + +template<typename X> +template<typename Y> +void Outer<X>::Inner0<Y>::f(X, Y) { +} + +template<typename X> +template<typename Y> +struct Outer<X>::Inner1<Y>::ReallyInner { + static Y value3; + + void g(X, Y); +}; + +template<typename X> +template<typename Y> +void Outer<X>::Inner1<Y>::ReallyInner::g(X, Y) { +} + +template<typename X> +template<typename Y> +X Outer<X>::Inner1<Y>::foo(Y) { + return X(); +} + +template<typename X> +template<typename Y> +template<typename Z> +X Outer<X>::Inner1<Y>::bar(Z) { + return X(); +} + +template<typename X> +template<typename Y> +template<typename Z> +X* Outer<X>::Inner1<Y>::bar(Z) { + return 0; +} + +template<typename X> +template<typename Y> +X Outer<X>::Inner1<Y>::value1 = 0; + +template<typename X> +template<typename Y> +Y Outer<X>::Inner1<Y>::value2 = Y(); + +template<typename X> +template<typename Y> +Y Outer<X>::Inner1<Y>::ReallyInner::value3 = Y(); + +template<typename X> +template<typename Y> +Y Outer<X>::Inner1<Y*>::ReallyInner::value4; // expected-error{{Outer<X>::Inner1<Y *>::ReallyInner::}} + + +template<typename T> +struct X0 { }; + +template<typename T> +struct X0<T*> { + template<typename U> + void f(U u = T()) { } +}; diff --git a/test/SemaTemplate/partial-spec-instantiate.cpp b/test/SemaTemplate/partial-spec-instantiate.cpp new file mode 100644 index 000000000000..8d1ae238977c --- /dev/null +++ b/test/SemaTemplate/partial-spec-instantiate.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only %s + +// PR4607 +template <class T> struct X {}; + +template <> struct X<char> +{ + static char* g(); +}; + +template <class T> struct X2 {}; + +template <class U> +struct X2<U*> { + static void f() { + X<U>::g(); + } +}; + +void a(char *a, char *b) {X2<char*>::f();} diff --git a/test/SemaTemplate/qualified-id.cpp b/test/SemaTemplate/qualified-id.cpp new file mode 100644 index 000000000000..85efab2b5cc9 --- /dev/null +++ b/test/SemaTemplate/qualified-id.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR5061 +namespace a { + template <typename T> class C {}; +} +namespace b { + template<typename T> void f0(a::C<T> &a0) { } +} diff --git a/test/SemaTemplate/qualified-names-diag.cpp b/test/SemaTemplate/qualified-names-diag.cpp index c875332905fb..1d53e5cb98ba 100644 --- a/test/SemaTemplate/qualified-names-diag.cpp +++ b/test/SemaTemplate/qualified-names-diag.cpp @@ -1,7 +1,7 @@ // RUN: clang-cc -fsyntax-only -verify %s namespace std { - template<typename T> class vector { }; + template<typename T> class vector { }; // expected-note{{candidate}} } typedef int INT; diff --git a/test/SemaTemplate/temp_class_order.cpp b/test/SemaTemplate/temp_class_order.cpp new file mode 100644 index 000000000000..4687ddf7d9e9 --- /dev/null +++ b/test/SemaTemplate/temp_class_order.cpp @@ -0,0 +1,42 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T, typename U> +struct X1 { + static const int value = 0; +}; + +template<typename T, typename U> +struct X1<T*, U*> { + static const int value = 1; +}; + +template<typename T> +struct X1<T*, T*> { + static const int value = 2; +}; + +template<typename T> +struct X1<const T*, const T*> { + static const int value = 3; +}; + +int array0[X1<int, int>::value == 0? 1 : -1]; +int array1[X1<int*, float*>::value == 1? 1 : -1]; +int array2[X1<int*, int*>::value == 2? 1 : -1]; +typedef const int* CIP; +int array3[X1<const int*, CIP>::value == 3? 1 : -1]; + +template<typename T, typename U> +struct X2 { }; + +template<typename T, typename U> +struct X2<T*, U> { }; // expected-note{{matches}} + +template<typename T, typename U> +struct X2<T, U*> { }; // expected-note{{matches}} + +template<typename T, typename U> +struct X2<const T*, const U*> { }; + +X2<int*, int*> x2a; // expected-error{{ambiguous}} +X2<const int*, const int*> x2b; diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp index 1a534236c8eb..dad857e8e66d 100644 --- a/test/SemaTemplate/temp_class_spec.cpp +++ b/test/SemaTemplate/temp_class_spec.cpp @@ -16,8 +16,7 @@ struct is_pointer<const T*> { int array0[is_pointer<int>::value? -1 : 1]; int array1[is_pointer<int*>::value? 1 : -1]; -int array2[is_pointer<const int*>::value? 1 : -1]; // expected-error{{partial ordering}} \ -// expected-error{{negative}} +int array2[is_pointer<const int*>::value? 1 : -1]; template<typename T> struct is_lvalue_reference { @@ -32,6 +31,38 @@ struct is_lvalue_reference<T&> { int lvalue_ref0[is_lvalue_reference<int>::value? -1 : 1]; int lvalue_ref1[is_lvalue_reference<const int&>::value? 1 : -1]; +template<typename T> +struct is_const { + static const bool value = false; +}; + +template<typename T> +struct is_const<const T> { + static const bool value = true; +}; + +int is_const0[is_const<int>::value? -1 : 1]; +int is_const1[is_const<const int>::value? 1 : -1]; +int is_const2[is_const<const volatile int>::value? 1 : -1]; +int is_const3[is_const<const int [3]>::value? 1 : -1]; +int is_const4[is_const<const volatile int[3]>::value? 1 : -1]; +int is_const5[is_const<volatile int[3]>::value? -1 : 1]; + +template<typename T> +struct is_volatile { + static const bool value = false; +}; + +template<typename T> +struct is_volatile<volatile T> { + static const bool value = true; +}; + +int is_volatile0[is_volatile<int>::value? -1 : 1]; +int is_volatile1[is_volatile<volatile int>::value? 1 : -1]; +int is_volatile2[is_volatile<const volatile int>::value? 1 : -1]; +int is_volatile3[is_volatile<volatile char[3]>::value? 1 : -1]; + template<typename T, typename U> struct is_same { static const bool value = false; @@ -62,7 +93,20 @@ struct remove_reference<T&> { int remove_ref0[is_same<remove_reference<int>::type, int>::value? 1 : -1]; int remove_ref1[is_same<remove_reference<int&>::type, int>::value? 1 : -1]; - + +template<typename T> +struct remove_const { + typedef T type; +}; + +template<typename T> +struct remove_const<const T> { + typedef T type; +}; + +int remove_const0[is_same<remove_const<const int>::type, int>::value? 1 : -1]; +int remove_const1[is_same<remove_const<const int[3]>::type, int[3]>::value? 1 : -1]; + template<typename T> struct is_incomplete_array { static const bool value = false; @@ -104,6 +148,24 @@ struct get_array_size<T[N]> { int array_size0[get_array_size<int[12]>::value == 12? 1 : -1]; template<typename T> +struct remove_extent { + typedef T type; +}; + +template<typename T> +struct remove_extent<T[]> { + typedef T type; +}; + +template<typename T, unsigned N> +struct remove_extent<T[N]> { + typedef T type; +}; + +int remove_extent0[is_same<remove_extent<int[][5]>::type, int[5]>::value? 1 : -1]; +int remove_extent1[is_same<remove_extent<const int[][5]>::type, const int[5]>::value? 1 : -1]; + +template<typename T> struct is_unary_function { static const bool value = false; }; @@ -261,3 +323,10 @@ template<class T, int I> class A<T, T*, I> { }; //#2 template<class T1, class T2, int I> class A<T1*, T2, I> { }; //#3 template<class T> class A<int, T*, 5> { }; //#4 template<class T1, class T2, int I> class A<T1, T2*, I> { }; //#5 + +// Redefinition of class template partial specializations +template<typename T, T N, typename U> class A0; + +template<typename T, T N> class A0<T, N, int> { }; // expected-note{{here}} +template<typename T, T N> class A0<T, N, int>; +template<typename T, T N> class A0<T, N, int> { }; // expected-error{{redef}} diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp index b50bd8f634aa..a029f474fc58 100644 --- a/test/SemaTemplate/temp_class_spec_neg.cpp +++ b/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; diff --git a/test/SemaTemplate/temp_func_order.cpp b/test/SemaTemplate/temp_func_order.cpp new file mode 100644 index 000000000000..5fd7c8d74571 --- /dev/null +++ b/test/SemaTemplate/temp_func_order.cpp @@ -0,0 +1,95 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> +int &f0(T); + +template<typename T> +float &f0(T*); + +void test_f0(int i, int *ip) { + int &ir = f0(i); + float &fr = f0(ip); +} + +template<typename T, typename U> +int &f1(T, U); + +template<typename T> +float &f1(T, T); + +void test_f1(int i, float f) { + int &ir = f1(i, f); + float &fr1 = f1(i, i); + float &fr2 = f1(f, f); +} + +template<typename T, typename U> +struct A { }; + +template<typename T> +int &f2(T); + +template<typename T, typename U> +float &f2(A<T, U>); + +template<typename T> +double &f2(A<T, T>); + +void test_f2(int i, A<int, float> aif, A<int, int> aii) { + int &ir = f2(i); + float &fr = f2(aif); + double &dr = f2(aii); +} + +template<typename T, typename U> +int &f3(T*, U); // expected-note{{candidate}} + +template<typename T, typename U> +float &f3(T, U*); // expected-note{{candidate}} + +void test_f3(int i, int *ip, float *fp) { + int &ir = f3(ip, i); + float &fr = f3(i, fp); + f3(ip, ip); // expected-error{{ambiguous}} +} + +template<typename T> +int &f4(T&); + +template<typename T> +float &f4(const T&); + +void test_f4(int i, const int ic) { + int &ir1 = f4(i); + float &fr1 = f4(ic); +} + +template<typename T, typename U> +int &f5(T&, const U&); // expected-note{{candidate}} + +template<typename T, typename U> +float &f5(const T&, U&); // expected-note{{candidate}} + +void test_f5(int i, const int ic) { + f5(i, i); // expected-error{{ambiguous}} +} + +template<typename T, typename U> +int &f6(T&, U&); + +template<typename T, typename U> +float &f6(const T&, U&); + +void test_f6(int i, const int ic) { + int &ir = f6(i, i); + float &fr = f6(ic, ic); +} + +struct CrazyFun { + template<typename T, typename U> operator A<T, U>(); + template<typename T> operator A<T, T>(); +}; + +void fun(CrazyFun cf) { + A<int, float> aif = cf; + A<int, int> aii = cf; +} diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp new file mode 100644 index 000000000000..c7484c19fca7 --- /dev/null +++ b/test/SemaTemplate/typename-specifier-4.cpp @@ -0,0 +1,70 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename MetaFun, typename T1, typename T2> +struct metafun_apply2 { + typedef typename MetaFun::template apply<T1, T2> inner; + typedef typename inner::type type; +}; + +template<typename T, typename U> struct pair; + +struct make_pair { + template<typename T1, typename T2> + struct apply { + typedef pair<T1, T2> type; + }; +}; + +int a0[is_same<metafun_apply2<make_pair, int, float>::type, + pair<int, float> >::value? 1 : -1]; +int a1[is_same< + typename make_pair::template apply<int, float>, + make_pair::apply<int, float> + >::value? 1 : -1]; + +template<typename MetaFun> +struct swap_and_apply2 { + template<typename T1, typename T2> + struct apply { + typedef typename MetaFun::template apply<T2, T1> new_metafun; + typedef typename new_metafun::type type; + }; +}; + +int a2[is_same<swap_and_apply2<make_pair>::apply<int, float>::type, + pair<float, int> >::value? 1 : -1]; + +template<typename MetaFun> +struct swap_and_apply2b { + template<typename T1, typename T2> + struct apply { + typedef typename MetaFun::template apply<T2, T1>::type type; + }; +}; + +int a3[is_same<swap_and_apply2b<make_pair>::apply<int, float>::type, + pair<float, int> >::value? 1 : -1]; + +template<typename T> +struct X0 { + template<typename U, typename V> + struct Inner; + + void f0(X0<T>::Inner<T*, T&>); // expected-note{{here}} + void f0(typename X0<T>::Inner<T*, T&>); // expected-error{{redecl}} + + void f1(X0<T>::Inner<T*, T&>); // expected-note{{here}} + void f1(typename X0<T>::template Inner<T*, T&>); // expected-error{{redecl}} + + void f2(typename X0<T>::Inner<T*, T&>::type); // expected-note{{here}} + void f2(typename X0<T>::template Inner<T*, T&>::type); // expected-error{{redecl}} +}; diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp index d3fca3eacad5..2501b8d048ff 100644 --- a/test/SemaTemplate/typename-specifier.cpp +++ b/test/SemaTemplate/typename-specifier.cpp @@ -16,7 +16,7 @@ namespace N { int i; typename N::A::type *ip1 = &i; -typename N::B::type *ip2 = &i; // expected-error{{ no type named 'type' in 'B'}} +typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'struct N::B'}} typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} void test(double d) { @@ -33,7 +33,8 @@ void test(double d) { namespace N { template<typename T> struct X { - typedef typename T::type type; // expected-error 2{{no type named 'type' in 'B'}} \ + typedef typename T::type type; // expected-error {{no type named 'type' in 'struct N::B'}} \ + // expected-error {{no type named 'type' in 'struct B'}} \ // FIXME: location info for error above isn't very good \ // expected-error 2{{typename specifier refers to non-type member 'type'}} \ // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} @@ -42,12 +43,12 @@ namespace N { N::X<N::A>::type *ip4 = &i; N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::B>' requested here}} \ -// expected-error{{unknown type name 'type'}} +// expected-error{{no type named 'type' in}} N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::C>' requested here}} \ -// expected-error{{unknown type name 'type'}} +// expected-error{{no type named 'type' in}} N::X<int>::type fail1; // expected-note{{in instantiation of template class 'struct N::X<int>' requested here}} \ -// expected-error{{unknown type name 'type'}} +// expected-error{{no type named 'type' in}} template<typename T> struct Y { @@ -69,6 +70,6 @@ struct C { ::Y<A>::type ip7 = &i; ::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'struct Y<struct B>' requested here}} \ -// expected-error{{unknown type name 'type'}} +// expected-error{{no type named 'type' in}} ::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'struct Y<struct C>' requested here}} \ -// expected-error{{unknown type name 'type'}} +// expected-error{{no type named 'type' in}} diff --git a/test/SemaTemplate/value-dependent-null-pointer-constant.cpp b/test/SemaTemplate/value-dependent-null-pointer-constant.cpp new file mode 100644 index 000000000000..8bde1277edd5 --- /dev/null +++ b/test/SemaTemplate/value-dependent-null-pointer-constant.cpp @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only %s + +template<typename T, int N> +struct X0 { + const char *f0(bool Cond) { + return Cond? "honk" : N; + } + + const char *f1(bool Cond) { + return Cond? N : "honk"; + } + + bool f2(const char *str) { + return str == N; + } +}; + +// PR4996 +template<unsigned I> int f0() { + return __builtin_choose_expr(I, 0, 1); +} + +// PR5041 +struct A { }; + +template <typename T> void f(T *t) +{ + (void)static_cast<void*>(static_cast<A*>(t)); +}
\ No newline at end of file |