diff options
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r-- | test/SemaTemplate/alias-church-numerals.cpp | 34 | ||||
-rw-r--r-- | test/SemaTemplate/alias-nested-nontag.cpp | 6 | ||||
-rw-r--r-- | test/SemaTemplate/alias-template-template-param.cpp | 7 | ||||
-rw-r--r-- | test/SemaTemplate/alias-templates.cpp | 70 | ||||
-rw-r--r-- | test/SemaTemplate/deduction-crash.cpp | 36 | ||||
-rw-r--r-- | test/SemaTemplate/dependent-names-no-std.cpp | 21 | ||||
-rw-r--r-- | test/SemaTemplate/dependent-names.cpp | 135 | ||||
-rw-r--r-- | test/SemaTemplate/friend-template.cpp | 8 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-call.cpp | 5 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-function-1.cpp | 22 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-init.cpp | 52 | ||||
-rw-r--r-- | test/SemaTemplate/partial-spec-instantiate.cpp | 10 | ||||
-rw-r--r-- | test/SemaTemplate/rdar9173693.cpp | 6 | ||||
-rw-r--r-- | test/SemaTemplate/typename-specifier.cpp | 31 |
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; |