aboutsummaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r--test/SemaTemplate/alias-church-numerals.cpp34
-rw-r--r--test/SemaTemplate/alias-nested-nontag.cpp6
-rw-r--r--test/SemaTemplate/alias-template-template-param.cpp7
-rw-r--r--test/SemaTemplate/alias-templates.cpp70
-rw-r--r--test/SemaTemplate/deduction-crash.cpp36
-rw-r--r--test/SemaTemplate/dependent-names-no-std.cpp21
-rw-r--r--test/SemaTemplate/dependent-names.cpp135
-rw-r--r--test/SemaTemplate/friend-template.cpp8
-rw-r--r--test/SemaTemplate/instantiate-call.cpp5
-rw-r--r--test/SemaTemplate/instantiate-function-1.cpp22
-rw-r--r--test/SemaTemplate/instantiate-init.cpp52
-rw-r--r--test/SemaTemplate/partial-spec-instantiate.cpp10
-rw-r--r--test/SemaTemplate/rdar9173693.cpp6
-rw-r--r--test/SemaTemplate/typename-specifier.cpp31
14 files changed, 437 insertions, 6 deletions
diff --git a/test/SemaTemplate/alias-church-numerals.cpp b/test/SemaTemplate/alias-church-numerals.cpp
new file mode 100644
index 000000000000..751cac73ae0f
--- /dev/null
+++ b/test/SemaTemplate/alias-church-numerals.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<template<template<typename> class, typename> class T, template<typename> class V> struct PartialApply {
+ template<typename W> using R = T<V, W>;
+};
+
+template<typename T> using Id = T;
+template<template<typename> class, typename X> using Zero = X;
+template<template<template<typename> class, typename> class N, template<typename> class F, typename X> using Succ = F<N<F,X>>;
+
+template<template<typename> class F, typename X> using One = Succ<Zero, F, X>;
+template<template<typename> class F, typename X> using Two = Succ<One, F, X>;
+
+template<template<template<typename> class, typename> class A,
+ template<template<typename> class, typename> class B,
+ template<typename> class F,
+ typename X> using Add = A<F, B<F, X>>;
+
+template<template<template<typename> class, typename> class A,
+ template<template<typename> class, typename> class B,
+ template<typename> class F,
+ typename X> using Mul = A<PartialApply<B,F>::template R, X>;
+
+template<template<typename> class F, typename X> using Four = Add<Two, Two, F, X>;
+template<template<typename> class F, typename X> using Sixteen = Mul<Four, Four, F, X>;
+template<template<typename> class F, typename X> using TwoHundredAndFiftySix = Mul<Sixteen, Sixteen, F, X>;
+
+template<typename T, T N> struct Const { static const T value = N; };
+template<typename A> struct IncrementHelper;
+template<typename T, T N> struct IncrementHelper<Const<T, N>> { using Result = Const<T, N+1>; };
+template<typename A> using Increment = typename IncrementHelper<A>::Result;
+
+using Arr = int[TwoHundredAndFiftySix<Increment, Const<int, 0>>::value];
+using Arr = int[256];
diff --git a/test/SemaTemplate/alias-nested-nontag.cpp b/test/SemaTemplate/alias-nested-nontag.cpp
new file mode 100644
index 000000000000..1bb5ce336f90
--- /dev/null
+++ b/test/SemaTemplate/alias-nested-nontag.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+template<typename T> using Id = T; // expected-note {{type alias template 'Id' declared here}}
+struct U { static Id<int> V; };
+Id<int> ::U::V; // expected-error {{type 'Id<int>' (aka 'int') cannot be used prior to '::' because it has no members}} \
+ expected-error {{C++ requires a type specifier}}
diff --git a/test/SemaTemplate/alias-template-template-param.cpp b/test/SemaTemplate/alias-template-template-param.cpp
new file mode 100644
index 000000000000..a847b0672a2a
--- /dev/null
+++ b/test/SemaTemplate/alias-template-template-param.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+template<template<typename> class D> using C = D<int>;
+
+// Substitution of the alias template transforms the TemplateSpecializationType
+// 'D<int>' into the DependentTemplateSpecializationType 'T::template U<int>'.
+template<typename T> void f(C<T::template U>);
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp
new file mode 100644
index 000000000000..f4c917c5ebc2
--- /dev/null
+++ b/test/SemaTemplate/alias-templates.cpp
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename S>
+struct A {
+ typedef S B;
+ template<typename T> using C = typename T::B;
+ template<typename T> struct D {
+ template<typename U> using E = typename A<U>::template C<A<T>>;
+ template<typename U> using F = A<E<U>>;
+ template<typename U> using G = C<F<U>>;
+ G<T> g;
+ };
+ typedef decltype(D<B>().g) H;
+ D<H> h;
+ template<typename T> using I = A<decltype(h.g)>;
+ template<typename T> using J = typename A<decltype(h.g)>::template C<I<T>>;
+};
+
+A<int> a;
+A<char>::D<double> b;
+
+template<typename T> T make();
+
+namespace X {
+ template<typename T> struct traits {
+ typedef T thing;
+ typedef decltype(val(make<thing>())) inner_ptr;
+
+ template<typename U> using rebind_thing = typename thing::template rebind<U>;
+ template<typename U> using rebind = traits<rebind_thing<U>>;
+
+ inner_ptr &&alloc();
+ void free(inner_ptr&&);
+ };
+
+ template<typename T> struct ptr_traits {
+ typedef T *type;
+ };
+ template<typename T> using ptr = typename ptr_traits<T>::type;
+
+ template<typename T> struct thing {
+ typedef T inner;
+ typedef ptr<inner> inner_ptr;
+ typedef traits<thing<inner>> traits_type;
+
+ template<typename U> using rebind = thing<U>;
+
+ thing(traits_type &traits) : traits(traits), val(traits.alloc()) {}
+ ~thing() { traits.free(static_cast<inner_ptr&&>(val)); }
+
+ traits_type &traits;
+ inner_ptr val;
+
+ friend inner_ptr val(const thing &t) { return t.val; }
+ };
+
+ template<> struct ptr_traits<bool> {
+ typedef bool &type;
+ };
+ template<> bool &traits<thing<bool>>::alloc() { static bool b; return b; }
+ template<> void traits<thing<bool>>::free(bool&) {}
+}
+
+typedef X::traits<X::thing<int>> itt;
+
+itt::thing::traits_type itr;
+itt::thing ith(itr);
+
+itt::rebind<bool> btr;
+itt::rebind_thing<bool> btt(btr);
diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp
index ec97311e5d72..fb23eda5bb9d 100644
--- a/test/SemaTemplate/deduction-crash.cpp
+++ b/test/SemaTemplate/deduction-crash.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only %s 2>&1| FileCheck %s
-// PR7511
-
// Note that the error count below doesn't matter. We just want to
// make sure that the parser doesn't crash.
-// CHECK: 13 errors
+// CHECK: 14 errors
+
+// PR7511
template<a>
struct int_;
@@ -57,3 +57,33 @@ int a()
state_machine<int> p;
p.ant(0);
}
+
+// PR9974
+template <int> struct enable_if;
+template <class > struct remove_reference ;
+template <class _Tp> struct remove_reference<_Tp&> ;
+
+template <class > struct __tuple_like;
+
+template <class _Tp, class _Up, int = __tuple_like<typename remove_reference<_Tp>::type>::value>
+struct __tuple_convertible;
+
+struct pair
+{
+template<class _Tuple, int = enable_if<__tuple_convertible<_Tuple, pair>::value>::type>
+pair(_Tuple&& );
+};
+
+template <class> struct basic_ostream;
+
+template <int>
+void endl( ) ;
+
+extern basic_ostream<char> cout;
+
+int operator<<( basic_ostream<char> , pair ) ;
+
+void register_object_imp ( )
+{
+cout << endl<1>;
+}
diff --git a/test/SemaTemplate/dependent-names-no-std.cpp b/test/SemaTemplate/dependent-names-no-std.cpp
new file mode 100644
index 000000000000..e9ac99faf65b
--- /dev/null
+++ b/test/SemaTemplate/dependent-names-no-std.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+//
+// The whole point of this test is to verify certain diagnostics work in the
+// absence of namespace 'std'.
+
+namespace PR10053 {
+ namespace ns {
+ struct Data {};
+ }
+
+ template<typename T> struct A {
+ T t;
+ A() {
+ f(t); // expected-error {{call to function 'f' that is neither visible in the template definition nor found by argument dependent lookup}}
+ }
+ };
+
+ void f(ns::Data); // expected-note {{in namespace 'PR10053::ns'}}
+
+ A<ns::Data> a; // expected-note {{in instantiation of member function}}
+}
diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp
index 5776ddca2c49..2a50df5b7f14 100644
--- a/test/SemaTemplate/dependent-names.cpp
+++ b/test/SemaTemplate/dependent-names.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
typedef double A;
template<typename T> class B {
@@ -129,3 +129,136 @@ namespace PR8966 {
template <class T>
const char* MyClass<T>::array [MyClass<T>::N] = { "A", "B", "C" };
}
+
+namespace std {
+ inline namespace v1 {
+ template<typename T> struct basic_ostream;
+ }
+ namespace inner {
+ template<typename T> struct vector {};
+ }
+ using inner::vector;
+ template<typename T, typename U> struct pair {};
+ typedef basic_ostream<char> ostream;
+ extern ostream cout;
+ std::ostream &operator<<(std::ostream &out, const char *);
+}
+
+namespace PR10053 {
+ template<typename T> struct A {
+ T t;
+ A() {
+ f(t); // expected-error {{call to function 'f' that is neither visible in the template definition nor found by argument dependent lookup}}
+ }
+ };
+
+ void f(int&); // expected-note {{'f' should be declared prior to the call site}}
+
+ A<int> a; // expected-note {{in instantiation of member function}}
+
+
+ namespace N {
+ namespace M {
+ template<typename T> int g(T t) {
+ f(t); // expected-error {{call to function 'f' that is neither visible in the template definition nor found by argument dependent lookup}}
+ };
+ }
+
+ void f(char&); // expected-note {{'f' should be declared prior to the call site}}
+ }
+
+ void f(char&);
+
+ int k = N::M::g<char>(0);; // expected-note {{in instantiation of function}}
+
+
+ namespace O {
+ void f(char&); // expected-note {{candidate function not viable}}
+
+ template<typename T> struct C {
+ static const int n = f(T()); // expected-error {{no matching function}}
+ };
+ }
+
+ int f(double); // no note, shadowed by O::f
+ O::C<double> c; // expected-note {{requested here}}
+
+
+ // Example from www/compatibility.html
+ namespace my_file {
+ template <typename T> T Squared(T x) {
+ return Multiply(x, x); // expected-error {{neither visible in the template definition nor found by argument dependent lookup}}
+ }
+
+ int Multiply(int x, int y) { // expected-note {{should be declared prior to the call site}}
+ return x * y;
+ }
+
+ int main() {
+ Squared(5); // expected-note {{here}}
+ }
+ }
+
+ // Example from www/compatibility.html
+ namespace my_file2 {
+ template<typename T>
+ void Dump(const T& value) {
+ std::cout << value << "\n"; // expected-error {{neither visible in the template definition nor found by argument dependent lookup}}
+ }
+
+ namespace ns {
+ struct Data {};
+ }
+
+ std::ostream& operator<<(std::ostream& out, ns::Data data) { // expected-note {{should be declared prior to the call site or in namespace 'PR10053::my_file2::ns'}}
+ return out << "Some data";
+ }
+
+ void Use() {
+ Dump(ns::Data()); // expected-note {{here}}
+ }
+ }
+
+ namespace my_file2_a {
+ template<typename T>
+ void Dump(const T &value) {
+ print(std::cout, value); // expected-error 4{{neither visible in the template definition nor found by argument dependent lookup}}
+ }
+
+ namespace ns {
+ struct Data {};
+ }
+ namespace ns2 {
+ struct Data {};
+ }
+
+ std::ostream &print(std::ostream &out, int); // expected-note-re {{should be declared prior to the call site$}}
+ std::ostream &print(std::ostream &out, ns::Data); // expected-note {{should be declared prior to the call site or in namespace 'PR10053::my_file2_a::ns'}}
+ std::ostream &print(std::ostream &out, std::vector<ns2::Data>); // expected-note {{should be declared prior to the call site or in namespace 'PR10053::my_file2_a::ns2'}}
+ std::ostream &print(std::ostream &out, std::pair<ns::Data, ns2::Data>); // expected-note {{should be declared prior to the call site or in an associated namespace of one of its arguments}}
+
+ void Use() {
+ Dump(0); // expected-note {{requested here}}
+ Dump(ns::Data()); // expected-note {{requested here}}
+ Dump(std::vector<ns2::Data>()); // expected-note {{requested here}}
+ Dump(std::pair<ns::Data, ns2::Data>()); // expected-note {{requested here}}
+ }
+ }
+
+ namespace unary {
+ template<typename T>
+ T Negate(const T& value) {
+ return !value; // expected-error {{call to function 'operator!' that is neither visible in the template definition nor found by argument dependent lookup}}
+ }
+
+ namespace ns {
+ struct Data {};
+ }
+
+ ns::Data operator!(ns::Data); // expected-note {{should be declared prior to the call site or in namespace 'PR10053::unary::ns'}}
+
+ void Use() {
+ Negate(ns::Data()); // expected-note {{requested here}}
+ }
+ }
+}
diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp
index 703daea3e630..d1284de35f18 100644
--- a/test/SemaTemplate/friend-template.cpp
+++ b/test/SemaTemplate/friend-template.cpp
@@ -216,3 +216,11 @@ namespace PR8649 {
X<int, float, 7> x;
}
+
+// Don't crash, and error on invalid friend type template.
+namespace friend_type_template_no_tag {
+ template <typename T> struct S {
+ template <typename U> friend S<U>; // expected-error{{friend type templates must use an elaborated type}}
+ };
+ template struct S<int>;
+}
diff --git a/test/SemaTemplate/instantiate-call.cpp b/test/SemaTemplate/instantiate-call.cpp
index ad06be33aa2b..a0e48c8dec77 100644
--- a/test/SemaTemplate/instantiate-call.cpp
+++ b/test/SemaTemplate/instantiate-call.cpp
@@ -24,7 +24,8 @@ namespace N3 {
template<typename T, typename Result>
struct call_f0 {
void test_f0(T t) {
- Result &result = f0(t); // expected-error 2{{undeclared identifier}}
+ Result &result = f0(t); // expected-error {{undeclared identifier}} \
+ expected-error {{neither visible in the template definition nor found by argument dependent lookup}}
}
};
}
@@ -32,7 +33,7 @@ namespace N3 {
template struct N3::call_f0<int, char&>; // expected-note{{instantiation}}
template struct N3::call_f0<N1::X0, int&>;
-short& f0(char);
+short& f0(char); // expected-note {{should be declared prior to the call site}}
namespace N4 {
template<typename T, typename Result>
struct call_f0 {
diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp
index 688d0095267a..5406fbcd1baf 100644
--- a/test/SemaTemplate/instantiate-function-1.cpp
+++ b/test/SemaTemplate/instantiate-function-1.cpp
@@ -225,3 +225,25 @@ namespace PR7016 {
template<typename T> void f() { T x = x; }
template void f<int>();
}
+
+namespace PR9880 {
+ struct lua_State;
+ struct no_tag { char a; }; // (A)
+ struct yes_tag { long a; long b; }; // (A)
+
+ template <typename T>
+ struct HasIndexMetamethod {
+ template <typename U>
+ static no_tag check(...);
+ template <typename U>
+ static yes_tag check(char[sizeof(&U::luaIndex)]);
+ enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
+ };
+
+ class SomeClass {
+ public:
+ int luaIndex(lua_State* L);
+ };
+
+ int i = HasIndexMetamethod<SomeClass>::value;
+}
diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp
index e292aa3c5f76..f0ca9a5b21e9 100644
--- a/test/SemaTemplate/instantiate-init.cpp
+++ b/test/SemaTemplate/instantiate-init.cpp
@@ -55,3 +55,55 @@ namespace PR6657 {
f0<int>();
}
}
+
+// Instantiate out-of-line definitions of static data members which complete
+// types through an initializer even when the only use of the member that would
+// cause instantiation is in an unevaluated context, but one requiring its
+// complete type.
+namespace PR10001 {
+ template <typename T> struct S {
+ static const int arr[];
+ static const int x;
+ static int f();
+ };
+
+ template <typename T> const int S<T>::arr[] = { 1, 2, 3 };
+ template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]);
+ template <typename T> int S<T>::f() { return x; }
+
+ int x = S<int>::f();
+}
+
+namespace PR7985 {
+ template<int N> struct integral_c { };
+
+ template <typename T, int N>
+ integral_c<N> array_lengthof(T (&x)[N]) { return integral_c<N>(); } // expected-note 2{{candidate template ignored: failed template argument deduction}}
+
+ template<typename T>
+ struct Data {
+ T x;
+ };
+
+ template<typename T>
+ struct Description {
+ static const Data<T> data[];
+ };
+
+ template<typename T>
+ const Data<T> Description<T>::data[] = {{ 1 }}; // expected-error{{cannot initialize a member subobject of type 'int *' with an rvalue of type 'int'}}
+
+ template<>
+ Data<float*> Description<float*>::data[];
+
+ void test() {
+ integral_c<1> ic1 = array_lengthof(Description<int>::data);
+ (void)sizeof(array_lengthof(Description<float>::data));
+
+ sizeof(array_lengthof( // expected-error{{no matching function for call to 'array_lengthof'}}
+ Description<int*>::data // expected-note{{in instantiation of static data member 'PR7985::Description<int *>::data' requested here}}
+ ));
+
+ array_lengthof(Description<float*>::data); // expected-error{{no matching function for call to 'array_lengthof'}}
+ }
+}
diff --git a/test/SemaTemplate/partial-spec-instantiate.cpp b/test/SemaTemplate/partial-spec-instantiate.cpp
index 68b4964816e4..a93af5026d37 100644
--- a/test/SemaTemplate/partial-spec-instantiate.cpp
+++ b/test/SemaTemplate/partial-spec-instantiate.cpp
@@ -38,3 +38,13 @@ namespace WonkyAccess {
return y.m + y2.m;
}
}
+
+// <rdar://problem/9169404>
+namespace rdar9169404 {
+ template<typename T, T N> struct X { };
+ template<bool C> struct X<bool, C> {
+ typedef int type;
+ };
+
+ X<bool, -1>::type value;
+}
diff --git a/test/SemaTemplate/rdar9173693.cpp b/test/SemaTemplate/rdar9173693.cpp
new file mode 100644
index 000000000000..86b49545a308
--- /dev/null
+++ b/test/SemaTemplate/rdar9173693.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/9173693>
+template< bool C > struct assert { };
+template< bool > struct assert_arg_pred_impl { }; // expected-note 3 {{declared here}}
+template< typename Pred > assert<false> assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ); // expected-error 5 {{}}
diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp
index 4c788f6a8a3c..7898a20d6e17 100644
--- a/test/SemaTemplate/typename-specifier.cpp
+++ b/test/SemaTemplate/typename-specifier.cpp
@@ -71,3 +71,34 @@ struct C {
::Y<A>::type ip7 = &i;
::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'Y<B>' requested here}}
::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'Y<C>' requested here}}
+
+template<typename T> struct D {
+ typedef typename T::foo foo; // expected-error {{type 'long' cannot be used prior to '::' because it has no members}}
+ typedef typename foo::bar bar;
+};
+
+D<long> struct_D; // expected-note {{in instantiation of template class 'D<long>' requested here}}
+
+template<typename T> struct E {
+ typedef typename T::foo foo;
+ typedef typename foo::bar bar; // expected-error {{type 'foo' (aka 'double') cannot be used prior to '::' because it has no members}}
+};
+
+struct F {
+ typedef double foo;
+};
+
+E<F> struct_E; // expected-note {{in instantiation of template class 'E<F>' requested here}}
+
+template<typename T> struct G {
+ typedef typename T::foo foo;
+ typedef typename foo::bar bar;
+};
+
+struct H {
+ struct foo {
+ typedef double bar;
+ };
+};
+
+G<H> struct_G;