aboutsummaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r--test/SemaTemplate/ackermann.cpp7
-rw-r--r--test/SemaTemplate/ambiguous-ovl-print.cpp9
-rw-r--r--test/SemaTemplate/canonical-expr-type-0x.cpp16
-rw-r--r--test/SemaTemplate/canonical-expr-type.cpp53
-rw-r--r--test/SemaTemplate/class-template-spec.cpp34
-rw-r--r--test/SemaTemplate/constructor-template.cpp53
-rw-r--r--test/SemaTemplate/copy-ctor-assign.cpp36
-rw-r--r--test/SemaTemplate/current-instantiation.cpp73
-rw-r--r--test/SemaTemplate/default-arguments.cpp20
-rw-r--r--test/SemaTemplate/default-expr-arguments.cpp86
-rw-r--r--test/SemaTemplate/dependent-base-member-init.cpp36
-rw-r--r--test/SemaTemplate/dependent-type-identity.cpp2
-rw-r--r--test/SemaTemplate/destructor-template.cpp12
-rw-r--r--test/SemaTemplate/example-dynarray.cpp63
-rw-r--r--test/SemaTemplate/explicit-instantiation.cpp75
-rw-r--r--test/SemaTemplate/explicit-specialization-member.cpp11
-rw-r--r--test/SemaTemplate/ext-vector-type.cpp2
-rw-r--r--test/SemaTemplate/extern-templates.cpp66
-rw-r--r--test/SemaTemplate/friend-template.cpp64
-rw-r--r--test/SemaTemplate/friend.cpp14
-rw-r--r--test/SemaTemplate/fun-template-def.cpp7
-rw-r--r--test/SemaTemplate/function-template-specialization.cpp35
-rw-r--r--test/SemaTemplate/implicit-instantiation-1.cpp2
-rw-r--r--test/SemaTemplate/injected-class-name.cpp10
-rw-r--r--test/SemaTemplate/instantiate-anonymous-union.cpp31
-rw-r--r--test/SemaTemplate/instantiate-cast.cpp8
-rw-r--r--test/SemaTemplate/instantiate-deeply.cpp22
-rw-r--r--test/SemaTemplate/instantiate-expr-2.cpp48
-rw-r--r--test/SemaTemplate/instantiate-expr-5.cpp4
-rw-r--r--test/SemaTemplate/instantiate-friend-class.cpp9
-rw-r--r--test/SemaTemplate/instantiate-function-1.cpp2
-rw-r--r--test/SemaTemplate/instantiate-function-1.mm3
-rw-r--r--test/SemaTemplate/instantiate-init.cpp28
-rw-r--r--test/SemaTemplate/instantiate-member-initializers.cpp26
-rw-r--r--test/SemaTemplate/instantiate-member-template.cpp105
-rw-r--r--test/SemaTemplate/instantiate-method.cpp9
-rw-r--r--test/SemaTemplate/instantiate-static-var.cpp22
-rw-r--r--test/SemaTemplate/instantiate-typedef.cpp2
-rw-r--r--test/SemaTemplate/instantiate-using-decl.cpp17
-rw-r--r--test/SemaTemplate/member-access-expr.cpp77
-rw-r--r--test/SemaTemplate/member-function-template.cpp51
-rw-r--r--test/SemaTemplate/member-initializers.cpp13
-rw-r--r--test/SemaTemplate/member-template-access-expr.cpp30
-rw-r--r--test/SemaTemplate/metafun-apply.cpp3
-rw-r--r--test/SemaTemplate/nested-linkage.cpp3
-rw-r--r--test/SemaTemplate/nested-template.cpp89
-rw-r--r--test/SemaTemplate/partial-spec-instantiate.cpp20
-rw-r--r--test/SemaTemplate/qualified-id.cpp9
-rw-r--r--test/SemaTemplate/qualified-names-diag.cpp2
-rw-r--r--test/SemaTemplate/temp_class_order.cpp42
-rw-r--r--test/SemaTemplate/temp_class_spec.cpp75
-rw-r--r--test/SemaTemplate/temp_class_spec_neg.cpp4
-rw-r--r--test/SemaTemplate/temp_func_order.cpp95
-rw-r--r--test/SemaTemplate/typename-specifier-4.cpp70
-rw-r--r--test/SemaTemplate/typename-specifier.cpp15
-rw-r--r--test/SemaTemplate/value-dependent-null-pointer-constant.cpp29
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