diff options
author | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
---|---|---|
committer | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
commit | be1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch) | |
tree | 1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/test/SemaTemplate | |
parent | c4626a62754862d20b41e8a46a3574264ea80e6d (diff) | |
parent | f1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff) |
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/test/SemaTemplate')
177 files changed, 12320 insertions, 0 deletions
diff --git a/clang/test/SemaTemplate/ackermann.cpp b/clang/test/SemaTemplate/ackermann.cpp new file mode 100644 index 0000000..9525bfc --- /dev/null +++ b/clang/test/SemaTemplate/ackermann.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// template<unsigned M, unsigned N> +// struct Ackermann { +// enum { +// value = M ? (N ? Ackermann<M-1, Ackermann<M, N-1> >::value +// : Ackermann<M-1, 1>::value) +// : N + 1 +// }; +// }; + +template<unsigned M, unsigned N> +struct Ackermann { + enum { + value = Ackermann<M-1, Ackermann<M, N-1>::value >::value + }; +}; + +template<unsigned M> struct Ackermann<M, 0> { + enum { + value = Ackermann<M-1, 1>::value + }; +}; + +template<unsigned N> struct Ackermann<0, N> { + enum { + value = N + 1 + }; +}; + +template<> struct Ackermann<0, 0> { + enum { + value = 1 + }; +}; + +int g0[Ackermann<3, 4>::value == 125 ? 1 : -1]; + diff --git a/clang/test/SemaTemplate/address-spaces.cpp b/clang/test/SemaTemplate/address-spaces.cpp new file mode 100644 index 0000000..eda03db --- /dev/null +++ b/clang/test/SemaTemplate/address-spaces.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -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; +}; + +typedef int __attribute__((address_space(1))) int_1;; +typedef int __attribute__((address_space(2))) int_2;; +typedef int __attribute__((address_space(1))) *int_1_ptr; +typedef int_2 *int_2_ptr; + +// Check that we maintain address spaces through template argument +// deduction from a type. +template<typename T> +struct remove_pointer { + typedef T type; +}; + +template<typename T> +struct remove_pointer<T *> { + typedef T type; +}; + +int check_remove0[is_same<remove_pointer<int_1_ptr>::type, int_1>::value? 1 : -1]; +int check_remove1[is_same<remove_pointer<int_2_ptr>::type, int_2>::value? 1 : -1]; +int check_remove2[is_same<remove_pointer<int_2_ptr>::type, int>::value? -1 : 1]; +int check_remove3[is_same<remove_pointer<int_2_ptr>::type, int_1>::value? -1 : 1]; + +template<typename T> +struct is_pointer_in_address_space_1 { + static const bool value = false; +}; + +template<typename T> +struct is_pointer_in_address_space_1<T __attribute__((address_space(1))) *> { + static const bool value = true; +}; + +int check_ptr_in_as1[is_pointer_in_address_space_1<int_1_ptr>::value? 1 : -1]; +int check_ptr_in_as2[is_pointer_in_address_space_1<int_2_ptr>::value? -1 : 1]; +int check_ptr_in_as3[is_pointer_in_address_space_1<int*>::value? -1 : 1]; + +// Check that we maintain address spaces through template argument +// deduction for a call. +template<typename T> +void accept_any_pointer(T*) { + T *x = 1; // expected-error{{cannot initialize a variable of type '__attribute__((address_space(1))) int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type '__attribute__((address_space(3))) int *' with an rvalue of type 'int'}} +} + +void test_accept_any_pointer(int_1_ptr ip1, int_2_ptr ip2) { + static __attribute__((address_space(3))) int array[17]; + accept_any_pointer(ip1); // expected-note{{in instantiation of}} + accept_any_pointer(array); // expected-note{{in instantiation of}} +} + +template<typename T> struct identity {}; + +template<typename T> +identity<T> accept_arg_in_address_space_1(__attribute__((address_space(1))) T &ir1); + +template<typename T> +identity<T> accept_any_arg(T &ir1); + +void test_arg_in_address_space_1() { + static int __attribute__((address_space(1))) int_1; + identity<int> ii = accept_arg_in_address_space_1(int_1); + identity<int __attribute__((address_space(1)))> ii2 = accept_any_arg(int_1); +} + +// Partial ordering +template<typename T> int &order1(__attribute__((address_space(1))) T&); +template<typename T> float &order1(T&); + +void test_order1() { + static __attribute__((address_space(1))) int i1; + int i; + int &ir = order1(i1); + float &fr = order1(i); +} diff --git a/clang/test/SemaTemplate/alias-church-numerals.cpp b/clang/test/SemaTemplate/alias-church-numerals.cpp new file mode 100644 index 0000000..69d7716 --- /dev/null +++ b/clang/test/SemaTemplate/alias-church-numerals.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/SemaTemplate/alias-nested-nontag.cpp b/clang/test/SemaTemplate/alias-nested-nontag.cpp new file mode 100644 index 0000000..4b5226b --- /dev/null +++ b/clang/test/SemaTemplate/alias-nested-nontag.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %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/clang/test/SemaTemplate/alias-template-template-param.cpp b/clang/test/SemaTemplate/alias-template-template-param.cpp new file mode 100644 index 0000000..c22fccb --- /dev/null +++ b/clang/test/SemaTemplate/alias-template-template-param.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %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/clang/test/SemaTemplate/alias-templates.cpp b/clang/test/SemaTemplate/alias-templates.cpp new file mode 100644 index 0000000..75615ee --- /dev/null +++ b/clang/test/SemaTemplate/alias-templates.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -std=c++11 -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); + +namespace PR11848 { + template<typename T> using U = int; + + template<typename T, typename ...Ts> + void f(U<T> i, U<Ts> ...is) { // expected-error {{type 'U<Ts>' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}} + return i + f<Ts...>(is...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} + } + + template<typename ...Ts> + struct S { + S(U<Ts>...ts); // expected-error {{does not contain any unexpanded parameter packs}} + }; + + template<typename T> + struct Hidden1 { + template<typename ...Ts> + Hidden1(typename T::template U<Ts> ...ts); // expected-error{{type 'typename Hide::U<Ts>' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}} + }; + + template<typename T, typename ...Ts> + struct Hidden2 { + Hidden2(typename T::template U<Ts> ...ts); + }; + + struct Hide { + template<typename T> using U = int; + }; + + Hidden1<Hide> h1; // expected-note{{in instantiation of template class 'PR11848::Hidden1<PR11848::Hide>' requested here}} + Hidden2<Hide, double, char> h2(1, 2); +} diff --git a/clang/test/SemaTemplate/ambiguous-ovl-print.cpp b/clang/test/SemaTemplate/ambiguous-ovl-print.cpp new file mode 100644 index 0000000..7e3fa24 --- /dev/null +++ b/clang/test/SemaTemplate/ambiguous-ovl-print.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f(void*, int); // expected-note{{candidate function}} +template<typename T> + void f(T*, long); // expected-note{{candidate function}} + +void test_f(int *ip, int i) { + f(ip, i); // expected-error{{ambiguous}} +} diff --git a/clang/test/SemaTemplate/anonymous-union.cpp b/clang/test/SemaTemplate/anonymous-union.cpp new file mode 100644 index 0000000..97ecd6e --- /dev/null +++ b/clang/test/SemaTemplate/anonymous-union.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5868 +struct T0 { + int x; + union { + void *m0; + }; +}; +template <typename T> +struct T1 : public T0, public T { + void f0() { + m0 = 0; // expected-error{{ambiguous conversion}} + } +}; + +struct A : public T0 { }; + +void f1(T1<A> *S) { S->f0(); } // expected-note{{instantiation of member function}} + +namespace rdar8635664 { + template<typename T> + struct X { + struct inner; + + struct inner { + union { + int x; + float y; + }; + + typedef T type; + }; + }; + + void test() { + X<int>::inner i; + i.x = 0; + } +} diff --git a/clang/test/SemaTemplate/array-to-pointer-decay.cpp b/clang/test/SemaTemplate/array-to-pointer-decay.cpp new file mode 100644 index 0000000..072c0e5 --- /dev/null +++ b/clang/test/SemaTemplate/array-to-pointer-decay.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct mystruct { + int member; +}; + +template <int i> +int foo() { + mystruct s[1]; + return s->member; +} + +int main() { + foo<1>(); +} + +// PR7405 +struct hb_sanitize_context_t { + int start; +}; +template <typename Type> static bool sanitize() { + hb_sanitize_context_t c[1]; + return !c->start; +} +bool closure = sanitize<int>(); diff --git a/clang/test/SemaTemplate/atomics.cpp b/clang/test/SemaTemplate/atomics.cpp new file mode 100644 index 0000000..e9fdc9d --- /dev/null +++ b/clang/test/SemaTemplate/atomics.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR8345 +template<typename T> T f(T* value) { + return __sync_add_and_fetch(value, 1); +} +int g(long long* x) { return f(x); } +int g(int* x) { return f(x); } + +namespace PR11320 { + template<typename T> + void g(unsigned *x) { + __sync_bool_compare_and_swap(x, 1, 4); + } + void h() { g<int>(0); } +} diff --git a/clang/test/SemaTemplate/attributes.cpp b/clang/test/SemaTemplate/attributes.cpp new file mode 100644 index 0000000..495f4a7 --- /dev/null +++ b/clang/test/SemaTemplate/attributes.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace attribute_aligned { + template<int N> + struct X { + char c[1] __attribute__((__aligned__((N)))); // expected-error {{alignment is not a power of 2}} + }; + + template <bool X> struct check { + int check_failed[X ? 1 : -1]; // expected-error {{array with a negative size}} + }; + + template <int N> struct check_alignment { + typedef check<N == sizeof(X<N>)> t; // expected-note {{in instantiation}} + }; + + check_alignment<1>::t c1; + check_alignment<2>::t c2; + check_alignment<3>::t c3; // expected-note 2 {{in instantiation}} + check_alignment<4>::t c4; +} + +namespace PR9049 { + extern const void *CFRetain(const void *ref); + + template<typename T> __attribute__((cf_returns_retained)) + inline T WBCFRetain(T aValue) { return aValue ? (T)CFRetain(aValue) : (T)0; } + + + extern void CFRelease(const void *ref); + + template<typename T> + inline void WBCFRelease(__attribute__((cf_consumed)) T aValue) { if(aValue) CFRelease(aValue); } +} diff --git a/clang/test/SemaTemplate/canonical-expr-type-0x.cpp b/clang/test/SemaTemplate/canonical-expr-type-0x.cpp new file mode 100644 index 0000000..d7379ea --- /dev/null +++ b/clang/test/SemaTemplate/canonical-expr-type-0x.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +void f(); + +// Test typeof(expr) canonicalization +template<typename T, T N> +void f0(T x, decltype(f(N, x)) y) { } // expected-note{{previous}} + +template<typename T, T N> +void f0(T x, decltype((f)(N, x)) y) { } + +template<typename U, U M> +void f0(U u, decltype(f(M, u))) { } // expected-error{{redefinition}} + +// PR12438: Test sizeof...() canonicalization +template<int> struct N {}; + +template<typename...T> +N<sizeof...(T)> f1() {} // expected-note{{previous}} + +template<typename, typename...T> +N<sizeof...(T)> f1() {} + +template<class...U> +N<sizeof...(U)> f1() {} // expected-error{{redefinition}} diff --git a/clang/test/SemaTemplate/canonical-expr-type.cpp b/clang/test/SemaTemplate/canonical-expr-type.cpp new file mode 100644 index 0000000..7582df5 --- /dev/null +++ b/clang/test/SemaTemplate/canonical-expr-type.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -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/clang/test/SemaTemplate/class-template-ctor-initializer.cpp b/clang/test/SemaTemplate/class-template-ctor-initializer.cpp new file mode 100644 index 0000000..44bb4bd --- /dev/null +++ b/clang/test/SemaTemplate/class-template-ctor-initializer.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class X> struct A {}; + +template<class X> struct B : A<X> { + B() : A<X>() {} +}; +B<int> x; + +template<class X> struct B1 : A<X> { + typedef A<X> Base; + B1() : Base() {} +}; +B1<int> x1; + + +template<typename T> struct Tmpl { }; + +template<typename T> struct TmplB { }; + +struct TmplC : Tmpl<int> { + TmplC() : + Tmpl<int>(), + TmplB<int>() { } // expected-error {{type 'TmplB<int>' is not a direct or virtual base of 'TmplC'}} +}; + + +struct TmplD : Tmpl<char>, TmplB<char> { + TmplD(): + Tmpl<int>(), // expected-error {{type 'Tmpl<int>' is not a direct or virtual base of 'TmplD'}} + TmplB<char>() {} +}; + +namespace PR7259 { + class Base { + public: + Base() {} + }; + + template <class ParentClass> + class Derived : public ParentClass { + public: + Derived() : Base() {} + }; + + class Final : public Derived<Base> { + }; + + int + main (void) + { + Final final; + return 0; + } +} diff --git a/clang/test/SemaTemplate/class-template-decl.cpp b/clang/test/SemaTemplate/class-template-decl.cpp new file mode 100644 index 0000000..ec4e016 --- /dev/null +++ b/clang/test/SemaTemplate/class-template-decl.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> class A; + +extern "C++" { + template<typename T> class B; +} + +namespace N { + template<typename T> class C; +} + +extern "C" { + template<typename T> class D; // expected-error{{templates must have C++ linkage}} +} + +template<class U> class A; // expected-note{{previous template declaration is here}} + +template<int N> class A; // expected-error{{template parameter has a different kind in template redeclaration}} + +template<int N> class NonTypeTemplateParm; + +typedef int INT; + +template<INT M> class NonTypeTemplateParm; // expected-note{{previous non-type template parameter with type 'INT' (aka 'int') is here}} + +template<long> class NonTypeTemplateParm; // expected-error{{template non-type parameter has a different type 'long' in template redeclaration}} + +template<template<typename T> class X> class TemplateTemplateParm; + +template<template<class> class Y> class TemplateTemplateParm; // expected-note{{previous template declaration is here}} \ + // expected-note{{previous template template parameter is here}} + +template<typename> class TemplateTemplateParm; // expected-error{{template parameter has a different kind in template redeclaration}} + +template<template<typename T, int> class X> class TemplateTemplateParm; // expected-error{{too many template parameters in template template parameter redeclaration}} + +template<typename T> +struct test {}; // expected-note{{previous definition}} + +template<typename T> +struct test : T {}; // expected-error{{redefinition}} + +class X { +public: + template<typename T> class C; +}; + +void f() { + template<typename T> class X; // expected-error{{expression}} +} + +template<typename T> class X1 var; // expected-error{{declared as a template}} + +namespace M { +} + +template<typename T> class M::C3 { }; // expected-error{{out-of-line definition of 'C3' does not match any declaration in namespace 'M'}} + +namespace PR8001 { + template<typename T1> + struct Foo { + template<typename T2> class Bar; + typedef Bar<T1> Baz; + + template<typename T2> + struct Bar { + Bar() {} + }; + }; + + void pr8001() { + Foo<int>::Baz x; + Foo<int>::Bar<int> y(x); + } +} + +namespace rdar9676205 { + template <unsigned, class _Tp> class tuple_element; + + template <class _T1, class _T2> class pair; + + template <class _T1, class _T2> + class tuple_element<0, pair<_T1, _T2> > + { + template <class _Tp> + struct X + { + template <class _Up, bool = X<_Up>::value> + struct Y + : public X<_Up>, + public Y<_Up> + { }; + }; + }; +} + diff --git a/clang/test/SemaTemplate/class-template-id-2.cpp b/clang/test/SemaTemplate/class-template-id-2.cpp new file mode 100644 index 0000000..d09f524 --- /dev/null +++ b/clang/test/SemaTemplate/class-template-id-2.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace N { + template<typename T> class A { }; + + template<> class A<int> { }; + + template<> class A<float>; // expected-note{{forward declaration of 'N::A<float>'}} + + class B : public A<int> { }; +} + +class C1 : public N::A<int> { }; + +class C2 : public N::A<float> { }; // expected-error{{base class has incomplete type}} + +struct D1 { + operator N::A<int>(); +}; + +namespace N { + struct D2 { + operator A<int>(); + }; +} diff --git a/clang/test/SemaTemplate/class-template-id.cpp b/clang/test/SemaTemplate/class-template-id.cpp new file mode 100644 index 0000000..3b02778 --- /dev/null +++ b/clang/test/SemaTemplate/class-template-id.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U = float> struct A { }; + +typedef A<int> A_int; + +typedef float FLOAT; + +A<int, FLOAT> *foo(A<int> *ptr, A<int> const *ptr2, A<int, double> *ptr3) { + if (ptr) + return ptr; // okay + else if (ptr2) + return ptr2; // expected-error{{cannot initialize return object of type 'A<int, FLOAT> *' with an lvalue of type 'const A<int> *'}} + else { + return ptr3; // expected-error{{cannot initialize return object of type 'A<int, FLOAT> *' with an lvalue of type 'A<int, double> *'}} + } +} + +template<int I> struct B; + +const int value = 12; +B<17 + 2> *bar(B<(19)> *ptr1, B< (::value + 7) > *ptr2, B<19 - 3> *ptr3) { + if (ptr1) + return ptr1; + else if (ptr2) + return ptr2; + else + return ptr3; // expected-error{{cannot initialize return object of type 'B<17 + 2> *' with an lvalue of type 'B<19 - 3>}} +} + +typedef B<5> B5; + + +namespace N { + template<typename T> struct C {}; +} + +N::C<int> c1; +typedef N::C<float> c2; + +// PR5655 +template<typename T> struct Foo { }; // expected-note{{template is declared here}} + +void f(void) { Foo bar; } // expected-error{{without a template argument list}} + +// rdar://problem/8254267 +template <typename T> class Party; +template <> class Party<T> { friend struct Party<>; }; // expected-error {{use of undeclared identifier 'T'}} diff --git a/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp new file mode 100644 index 0000000..f9015b3 --- /dev/null +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +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}} + +template<> struct A<float, float> { // expected-note{{previous definition}} + int x; +}; + +template<> struct A<float> { // expected-note{{previous definition}} + int y; +}; + +int test_specs(A<float, float> *a1, A<float, int> *a2) { + return a1->x + a2->y; +} + +int test_incomplete_specs(A<double, double> *a1, + A<double> *a2) +{ + (void)a1->x; // expected-error{{member access into incomplete type}} + (void)a2->x; // expected-error{{implicit instantiation of undefined template 'A<double, int>'}} +} + +typedef float FLOAT; + +template<> struct A<float, FLOAT>; + +template<> struct A<FLOAT, float> { }; // expected-error{{redefinition}} + +template<> struct A<float, int> { }; // expected-error{{redefinition}} + +template<typename T, typename U = int> struct X; + +template <> struct X<int, int> { int foo(); }; // #1 +template <> struct X<float> { int bar(); }; // #2 + +typedef int int_type; +void testme(X<int_type> *x1, X<float, int> *x2) { + (void)x1->foo(); // okay: refers to #1 + (void)x2->bar(); // okay: refers to #2 +} + +// Make sure specializations are proper classes. +template<> +struct A<char> { + A(); +}; + +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<>'}} + +template<> struct ::A<double>; + +namespace N { + template<typename T> struct B; // expected-note 2{{explicitly specialized}} + + template<> struct ::N::B<char>; // okay + template<> struct ::N::B<short>; // okay + template<> struct ::N::B<int>; // okay + + int f(int); +} + +template<> struct N::B<int> { }; // okay + +template<> struct N::B<float> { }; // expected-warning{{C++11 extension}} + +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{{originally}} +} + +template<> struct N::B<char> { + int testf(int x) { return f(x); } +}; + +// PR5264 +template <typename T> class Foo; +Foo<int>* v; +Foo<int>& F() { return *v; } +template <typename T> class Foo {}; +Foo<int> x; + + +// Template template parameters +template<template<class T> class Wibble> +class Wibble<int> { }; // expected-error{{cannot specialize a template template parameter}} + +namespace rdar9676205 { + template<typename T> + struct X { + template<typename U> + struct X<U*> { // expected-error{{explicit specialization of 'X' in class scope}} + }; + }; + +} diff --git a/clang/test/SemaTemplate/constexpr-instantiate.cpp b/clang/test/SemaTemplate/constexpr-instantiate.cpp new file mode 100644 index 0000000..2f9fe0e --- /dev/null +++ b/clang/test/SemaTemplate/constexpr-instantiate.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace UseBeforeDefinition { + struct A { + template<typename T> static constexpr T get() { return T(); } + // ok, not a constant expression. + int n = get<int>(); + }; + + // ok, constant expression. + constexpr int j = A::get<int>(); + + template<typename T> constexpr int consume(T); + // ok, not a constant expression. + const int k = consume(0); // expected-note {{here}} + + template<typename T> constexpr int consume(T) { return 0; } + // ok, constant expression. + constexpr int l = consume(0); + + constexpr int m = k; // expected-error {{constant expression}} expected-note {{initializer of 'k'}} +} + +namespace IntegralConst { + template<typename T> constexpr T f(T n) { return n; } + enum E { + v = f(0), w = f(1) // ok + }; + static_assert(w == 1, ""); + + char arr[f('x')]; // ok + static_assert(sizeof(arr) == 'x', ""); +} + +namespace ConvertedConst { + template<typename T> constexpr T f(T n) { return n; } + int f() { + switch (f()) { + case f(4): return 0; + } + return 1; + } +} + +namespace OverloadResolution { + template<typename T> constexpr T f(T t) { return t; } + + template<int n> struct S { }; + + template<typename T> auto g(T t) -> S<f(sizeof(T))> &; + char &f(...); + + template<typename T> auto h(T t[f(sizeof(T))]) -> decltype(&*t) { + return t; + } + + S<4> &k = g(0); + int *p, *q = h(p); +} + +namespace DataMember { + template<typename T> struct S { static const int k; }; + const int n = S<int>::k; // expected-note {{here}} + template<typename T> const int S<T>::k = 0; + constexpr int m = S<int>::k; // ok + constexpr int o = n; // expected-error {{constant expression}} expected-note {{initializer of 'n'}} +} + +namespace Reference { + const int k = 5; + template<typename T> struct S { + static volatile int &r; + }; + template<typename T> volatile int &S<T>::r = const_cast<volatile int&>(k); + constexpr int n = const_cast<int&>(S<int>::r); + static_assert(n == 5, ""); +} diff --git a/clang/test/SemaTemplate/constructor-template.cpp b/clang/test/SemaTemplate/constructor-template.cpp new file mode 100644 index 0000000..cf3fdfb --- /dev/null +++ b/clang/test/SemaTemplate/constructor-template.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct X0 { // expected-note{{candidate}} + X0(int); // expected-note{{candidate}} + template<typename T> X0(T); // expected-note {{candidate}} + template<typename T, typename U> X0(T*, U*); // expected-note {{candidate}} + + // PR4761 + template<typename T> X0() : f0(T::foo) {} // expected-note {{candidate}} + 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) {} }; + +struct X2 { + X2(); // expected-note{{candidate constructor}} + X2(X2&); // expected-note {{candidate constructor}} + template<typename T> X2(T); +}; + +X2 test(bool Cond, X2 x2) { + if (Cond) + return x2; // okay, uses copy constructor + + return X2(); // expected-error{{no matching constructor}} +} + +struct X3 { + template<typename T> X3(T); +}; + +template<> X3::X3(X3); // expected-error{{must pass its first argument by reference}} + +struct X4 { + X4(); + ~X4(); + X4(X4&); + template<typename T> X4(const T&, int = 17); +}; + +X4 test_X4(bool Cond, X4 x4) { + X4 a(x4, 17); // okay, constructor template + X4 b(x4); // okay, copy constructor + return X4(); +} + +// Instantiation of a non-dependent use of a constructor +struct DefaultCtorHasDefaultArg { + explicit DefaultCtorHasDefaultArg(int i = 17); +}; + +template<typename T> +void default_ctor_inst() { + DefaultCtorHasDefaultArg def; +} + +template void default_ctor_inst<int>(); + +template<typename T> +struct X5 { + X5(); + X5(const T &); +}; + +struct X6 { + template<typename T> X6(T); +}; + +void test_X5_X6() { + X5<X6> tf; + X5<X6> tf2(tf); +} + +namespace PR8182 { + struct foo { + foo(); + template<class T> foo(T&); + + private: + foo(const foo&); + }; + + void test_foo() { + foo f1; + foo f2(f1); + foo f3 = f1; + } + +} diff --git a/clang/test/SemaTemplate/copy-ctor-assign.cpp b/clang/test/SemaTemplate/copy-ctor-assign.cpp new file mode 100644 index 0000000..ae6dc9c --- /dev/null +++ b/clang/test/SemaTemplate/copy-ctor-assign.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -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}} +} + +struct X1 { + X1 &operator=(const X1&); +}; + +template<typename T> +struct X2 : X1 { + template<typename U> X2 &operator=(const U&); +}; + +struct X3 : X2<int> { +}; + +void test_X2(X3 &to, X3 from) { + to = from; +} diff --git a/clang/test/SemaTemplate/crash-10438657.cpp b/clang/test/SemaTemplate/crash-10438657.cpp new file mode 100644 index 0000000..2ee64bd --- /dev/null +++ b/clang/test/SemaTemplate/crash-10438657.cpp @@ -0,0 +1,15 @@ +// RUN: not %clang_cc1 -fsyntax-only %s 2> %t +// RUN: FileCheck %s < %t +// CHECK: 10 errors +template<typename _CharT> +class collate : public locale::facet { + +protected: +virtual ~collate() {} + class wxObject; + class __attribute__ ((visibility("default"))) wxGDIRefData + : public wxObjectRefData {}; + class __attribute__ ((visibility("default"))) wxGDIObject : public wxObject { \ + public: + virtual bool IsOk() const { + return m_refData && static_cast<wxGDIRefData *>(m_refData)->IsOk(); diff --git a/clang/test/SemaTemplate/crash-8204126.cpp b/clang/test/SemaTemplate/crash-8204126.cpp new file mode 100644 index 0000000..eb96560 --- /dev/null +++ b/clang/test/SemaTemplate/crash-8204126.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A +{ + template<int> template<typename T> friend void foo(T) {} // expected-error{{extraneous template parameter list}} + void bar() { foo(0); } // expected-error{{use of undeclared identifier 'foo'}} +}; diff --git a/clang/test/SemaTemplate/current-instantiation.cpp b/clang/test/SemaTemplate/current-instantiation.cpp new file mode 100644 index 0000000..ccef811 --- /dev/null +++ b/clang/test/SemaTemplate/current-instantiation.cpp @@ -0,0 +1,237 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test concerns the identity of dependent types within the +// canonical type system, specifically focusing on the difference +// between members of the current instantiation and membmers of an +// unknown specialization. This considers C++ [temp.type], which +// specifies type equivalence within a template, and C++0x +// [temp.dep.type], which defines what it means to be a member of the +// current instantiation. + +template<typename T, typename U> +struct X0 { + typedef T T_type; + typedef U U_type; + + 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}} + + struct X1 { + 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 X1::my_T_type&); // expected-error{{redecl}} + + void g5(T&); // expected-note{{previous}} + void g5(typename X0::U_type&); + void g5(typename X0::X1::my_T_type&); // expected-error{{redecl}} + + void g6(T&); // expected-note{{previous}} + void g6(typename X0::U_type&); + void g6(typename X0<T, U>::X1::my_T_type&); // expected-error{{redecl}} + + void g7(T&); // expected-note{{previous}} + void g7(typename X0::U_type&); + void g7(typename ::X0<typename X1::my_T_type, U_type>::X1::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>::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}} + }; +}; + +template<typename T> +struct X1 { + static int *a; + void f(float *b) { + X1<T>::a = b; // expected-error{{incompatible}} + X1<T*>::a = b; + } +}; + +namespace ConstantInCurrentInstantiation { + template<typename T> + struct X { + static const int value = 2; + static int array[value]; + }; + + template<typename T> const int X<T>::value; + + template<typename T> + int X<T>::array[X<T>::value] = { 1, 2 }; +} + +namespace Expressions { + template <bool b> + struct Bool { + enum anonymous_enum { value = b }; + }; + struct True : public Bool<true> {}; + struct False : public Bool<false> {}; + + template <typename T1, typename T2> + struct Is_Same : public False {}; + template <typename T> + struct Is_Same<T, T> : public True {}; + + template <bool b, typename T = void> + struct Enable_If {}; + template <typename T> + struct Enable_If<true, T> { + typedef T type; + }; + + template <typename T> + class Class { + public: + template <typename U> + typename Enable_If<Is_Same<U, Class>::value, void>::type + foo(); + }; + + + template <typename T> + template <typename U> + typename Enable_If<Is_Same<U, Class<T> >::value, void>::type + Class<T>::foo() {} +} + +namespace PR9255 { + template<typename T> + class X0 { + public: + class Inner1; + + class Inner2 { + public: + void f() + { + Inner1::f.g(); + } + }; + }; +} + +namespace rdar10194295 { + template<typename XT> + class X { + public: + enum Enum { Yes, No }; + template<Enum> void foo(); + template<Enum> class Inner; + }; + + template<typename XT> + template<typename X<XT>::Enum> + void X<XT>::foo() + { + } + + template<typename XT> + template<typename X<XT>::Enum> + class X<XT>::Inner { }; +} diff --git a/clang/test/SemaTemplate/deduction-crash.cpp b/clang/test/SemaTemplate/deduction-crash.cpp new file mode 100644 index 0000000..cf3899f --- /dev/null +++ b/clang/test/SemaTemplate/deduction-crash.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only %s 2>&1| FileCheck %s + +// Note that the error count below doesn't matter. We just want to +// make sure that the parser doesn't crash. +// CHECK: 13 errors + +// PR7511 +template<a> +struct int_; + +template<a> +template<int,typename T1,typename> +struct ac +{ + typedef T1 ae +}; + +template<class>struct aaa +{ + typedef ac<1,int,int>::ae ae +}; + +template<class> +struct state_machine +{ + typedef aaa<int>::ae aaa; + int start() + { + ant(0); + } + + template<class> + struct region_processing_helper + { + template<class,int=0> + struct In; + + template<int my> + struct In<a::int_<aaa::a>,my>; + + template<class Event> + int process(Event) + { + In<a::int_<0> > a; + } + } + template<class Event> + int ant(Event) + { + region_processing_helper<int>* helper; + helper->process(0) + } +}; + +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/clang/test/SemaTemplate/deduction.cpp b/clang/test/SemaTemplate/deduction.cpp new file mode 100644 index 0000000..aecb5ee --- /dev/null +++ b/clang/test/SemaTemplate/deduction.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Template argument deduction with template template parameters. +template<typename T, template<T> class A> +struct X0 { + static const unsigned value = 0; +}; + +template<template<int> class A> +struct X0<int, A> { + static const unsigned value = 1; +}; + +template<int> struct X0i; +template<long> struct X0l; +int array_x0a[X0<long, X0l>::value == 0? 1 : -1]; +int array_x0b[X0<int, X0i>::value == 1? 1 : -1]; + +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 T> struct allocator { }; +template<typename T, typename Alloc = allocator<T> > struct vector {}; + +// Fun with meta-lambdas! +struct _1 {}; +struct _2 {}; + +// Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T. +template<typename T, typename Arg1, typename Arg2> +struct Replace { + typedef T type; +}; + +// Replacement of the whole type. +template<typename Arg1, typename Arg2> +struct Replace<_1, Arg1, Arg2> { + typedef Arg1 type; +}; + +template<typename Arg1, typename Arg2> +struct Replace<_2, Arg1, Arg2> { + typedef Arg2 type; +}; + +// Replacement through cv-qualifiers +template<typename T, typename Arg1, typename Arg2> +struct Replace<const T, Arg1, Arg2> { + typedef typename Replace<T, Arg1, Arg2>::type const type; +}; + +// Replacement of templates +template<template<typename> class TT, typename T1, typename Arg1, typename Arg2> +struct Replace<TT<T1>, Arg1, Arg2> { + typedef TT<typename Replace<T1, Arg1, Arg2>::type> type; +}; + +template<template<typename, typename> class TT, typename T1, typename T2, + typename Arg1, typename Arg2> +struct Replace<TT<T1, T2>, Arg1, Arg2> { + typedef TT<typename Replace<T1, Arg1, Arg2>::type, + typename Replace<T2, Arg1, Arg2>::type> type; +}; + +// Just for kicks... +template<template<typename, typename> class TT, typename T1, + typename Arg1, typename Arg2> +struct Replace<TT<T1, _2>, Arg1, Arg2> { + typedef TT<typename Replace<T1, Arg1, Arg2>::type, Arg2> type; +}; + +int array0[is_same<Replace<_1, int, float>::type, int>::value? 1 : -1]; +int array1[is_same<Replace<const _1, int, float>::type, const int>::value? 1 : -1]; +int array2[is_same<Replace<vector<_1>, int, float>::type, vector<int> >::value? 1 : -1]; +int array3[is_same<Replace<vector<const _1>, int, float>::type, vector<const int> >::value? 1 : -1]; +int array4[is_same<Replace<vector<int, _2>, double, float>::type, vector<int, float> >::value? 1 : -1]; + +// PR5911 +template <typename T, int N> void f(const T (&a)[N]); +int iarr[] = { 1 }; +void test_PR5911() { f(iarr); } + +// Must not examine base classes of incomplete type during template argument +// deduction. +namespace PR6257 { + template <typename T> struct X { + template <typename U> X(const X<U>& u); + }; + struct A; + void f(A& a); + void f(const X<A>& a); + void test(A& a) { (void)f(a); } +} + +// PR7463 +namespace PR7463 { + const int f (); + template <typename T_> void g (T_&); // expected-note{{T_ = int}} + void h (void) { g(f()); } // expected-error{{no matching function for call}} +} + +namespace test0 { + template <class T> void make(const T *(*fn)()); // expected-note {{candidate template ignored: can't deduce a type for 'T' which would make 'const T' equal 'char'}} + char *char_maker(); + void test() { + make(char_maker); // expected-error {{no matching function for call to 'make'}} + } +} + +namespace test1 { + template<typename T> void foo(const T a[3][3]); + void test() { + int a[3][3]; + foo(a); + } +} + +// PR7708 +namespace test2 { + template<typename T> struct Const { typedef void const type; }; + + template<typename T> void f(T, typename Const<T>::type*); + template<typename T> void f(T, void const *); + + void test() { + void *p = 0; + f(0, p); + } +} + +// rdar://problem/8537391 +namespace test3 { + struct Foo { + template <void F(char)> static inline void foo(); + }; + + class Bar { + template<typename T> static inline void wobble(T ch); + + public: + static void madness() { + Foo::foo<wobble<char> >(); + } + }; +} + +// Verify that we can deduce enum-typed arguments correctly. +namespace test14 { + enum E { E0, E1 }; + template <E> struct A {}; + template <E e> void foo(const A<e> &a) {} + + void test() { + A<E0> a; + foo(a); + } +} diff --git a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp new file mode 100644 index 0000000..7714313 --- /dev/null +++ b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// Test default template arguments for function templates. +template<typename T = int> +void f0(); + +template<typename T> +void f0(); + +void g0() { + f0(); // okay! +} + +template<typename T, int N = T::value> +int &f1(T); + +float &f1(...); + +struct HasValue { + static const int value = 17; +}; + +void g1() { + float &fr = f1(15); + int &ir = f1(HasValue()); +} diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp new file mode 100644 index 0000000..6391369 --- /dev/null +++ b/clang/test/SemaTemplate/default-arguments.cpp @@ -0,0 +1,138 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, int N = 2> struct X; // expected-note{{template is declared here}} + +X<int, 1> *x1; +X<int> *x2; + +X<> *x3; // expected-error{{too few template arguments for class template 'X'}} + +template<typename U = float, int M> struct X; + +X<> *x4; + +template<typename T = int> struct Z { }; +template struct Z<>; + +// PR4362 +template<class T> struct a { }; +template<> struct a<int> { static const bool v = true; }; + +template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member named 'v'}} + +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; +}; + +// Nested default arguments for template parameters. +template<typename T> struct X1 { }; + +template<typename T> +struct X2 { + template<typename U = typename X1<T>::type> // expected-error{{no type named}} + struct Inner1 { }; + + template<T Value = X1<T>::value> // expected-error{{no member named 'value'}} + struct NonType1 { }; + + template<T Value> + struct Inner2 { }; + + template<typename U> + struct Inner3 { + template<typename X = T, typename V = U> + struct VeryInner { }; + + template<T Value1 = sizeof(T), T Value2 = sizeof(U), + T Value3 = Value1 + Value2> + struct NonType2 { }; + }; +}; + +X2<int> x2i; +X2<int>::Inner1<float> x2iif; + +X2<int>::Inner1<> x2bad; // expected-note{{instantiation of default argument}} + +X2<int>::NonType1<'a'> x2_nontype1; +X2<int>::NonType1<> x2_nontype1_bad; // expected-note{{instantiation of default argument}} + +// Check multi-level substitution into template type arguments +X2<int>::Inner3<float>::VeryInner<> vi; +X2<char>::Inner3<int>::NonType2<> x2_deep_nontype; + +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; }; + +int array1[is_same<__typeof__(vi), + X2<int>::Inner3<float>::VeryInner<int, float> >::value? 1 : -1]; + +int array2[is_same<__typeof(x2_deep_nontype), + X2<char>::Inner3<int>::NonType2<sizeof(char), sizeof(int), + sizeof(char)+sizeof(int)> >::value? 1 : -1]; + +// Template template parameter defaults +template<template<typename T> class X = X2> struct X3 { }; +int array3[is_same<X3<>, X3<X2> >::value? 1 : -1]; + +struct add_pointer { + template<typename T> + struct apply { + typedef T* type; + }; +}; + +template<typename T, template<typename> class X = T::template apply> + struct X4; +int array4[is_same<X4<add_pointer>, + X4<add_pointer, add_pointer::apply> >::value? 1 : -1]; + +template<int> struct X5 {}; // expected-note{{has a different type 'int'}} +template<long> struct X5b {}; +template<typename T, + template<T> class B = X5> // expected-error{{template template argument has different}} \ + // expected-note{{previous non-type template parameter}} + struct X6 {}; + +X6<int> x6a; +X6<long> x6b; // expected-note{{while checking a default template argument}} +X6<long, X5b> x6c; + + +template<template<class> class X = B<int> > struct X7; // expected-error{{must be a class template}} + +namespace PR9643 { + template<typename T> class allocator {}; + template<typename T, typename U = allocator<T> > class vector {}; + + template<template<typename U, typename = allocator<U> > class container, + typename DT> + container<DT> initializer(const DT& d) { + return container<DT>(); + } + + void f() { + vector<int, allocator<int> > v = initializer<vector>(5); + } +} diff --git a/clang/test/SemaTemplate/default-expr-arguments-2.cpp b/clang/test/SemaTemplate/default-expr-arguments-2.cpp new file mode 100644 index 0000000..378999d --- /dev/null +++ b/clang/test/SemaTemplate/default-expr-arguments-2.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s + +// This is a wacky test to ensure that we're actually instantiating +// the default arguments of the constructor when the function type is +// otherwise non-dependent. +namespace PR6733 { + template <class T> + class bar { + public: enum { kSomeConst = 128 }; + bar(int x = kSomeConst) {} + }; + + // CHECK: void f() + void f() { + // CHECK: bar<int> tmp = + // CHECK: CXXDefaultArgExpr{{.*}}'int' + bar<int> tmp; + } +} diff --git a/clang/test/SemaTemplate/default-expr-arguments.cpp b/clang/test/SemaTemplate/default-expr-arguments.cpp new file mode 100644 index 0000000..1eefa9f --- /dev/null +++ b/clang/test/SemaTemplate/default-expr-arguments.cpp @@ -0,0 +1,305 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +class C { C(int a0 = 0); }; + +template<> +C<char>::C(int a0); + +struct S { }; // expected-note 3 {{candidate constructor (the implicit copy constructor)}} + +template<typename T> void f1(T a, T b = 10) { } // expected-error{{no viable conversion}} \ +// expected-note{{passing argument to parameter 'b' here}} + +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 ('S' and 'S')}} + +void g() { + f1(10); + f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1<S>' required here}} + + f2(10); + f2(S()); + + f3(10); + f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<S>' required here}} +} + +template<typename T> struct F { + F(T t = 10); // expected-error{{no viable conversion}} \ + // expected-note{{passing argument to parameter 't' here}} + void f(T t = 10); // expected-error{{no viable conversion}} \ + // expected-note{{passing argument to parameter 't' here}} +}; + +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<S>' required here}} + + F<int> f2; + F<S> s2; // expected-note{{in instantiation of default function argument expression for 'F<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 2{{candidate}} + NotDefaultConstructible(int); // expected-note 2{{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; +} + +template<typename T> +struct X2 { + void operator()(T = T()); // expected-error{{no matching}} +}; + +void test_x2(X2<int> x2i, X2<NotDefaultConstructible> x2n) { + x2i(); + x2i(17); + x2n(NotDefaultConstructible(17)); + x2n(); // expected-note{{in instantiation of default function argument}} +} + +// PR5283 +namespace PR5283 { +template<typename T> struct A { + A(T = 1); // expected-error 3 {{cannot initialize a parameter of type 'int *' with an rvalue of type 'int'}} \ + // expected-note 3{{passing argument to parameter here}} +}; + +struct B : A<int*> { + B(); +}; +B::B() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}} + +struct C : virtual A<int*> { + C(); +}; +C::C() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}} + +struct D { + D(); + + A<int*> a; +}; +D::D() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}} +} + +// PR5301 +namespace pr5301 { + void f(int, int = 0); + + template <typename T> + void g(T, T = 0); + + template <int I> + void i(int a = I); + + template <typename T> + void h(T t) { + f(0); + g(1); + g(t); + i<2>(); + } + + void test() { + h(0); + } +} + +// PR5810 +namespace PR5810 { + template<typename T> + struct allocator { + allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array with a negative size}} + }; + + template<typename T> + struct vector { + vector(const allocator<T>& = allocator<T>()) {} // expected-note2 {{instantiation of}} + }; + + struct A { }; + struct B { }; + + template<typename> + void FilterVTs() { + vector<A> Result; + } + + void f() { + vector<A> Result; + } + + template<typename T> + struct X { + vector<B> bs; + X() { } + }; + + void f2() { + X<float> x; // expected-note{{member function}} + } +} + +template<typename T> void f4(T, int = 17); +template<> void f4<int>(int, int); + +void f4_test(int i) { + f4(i); +} + +// Instantiate for initialization +namespace InstForInit { + template<typename T> + struct Ptr { + typedef T* type; + Ptr(type); + }; + + template<typename T> + struct Holder { + Holder(int i, Ptr<T> ptr = 0); + }; + + void test_holder(int i) { + Holder<int> h(i); + } +}; + +namespace PR5810b { + template<typename T> + T broken() { + T t; + double**** not_it = t; + } + + void f(int = broken<int>()); + void g() { f(17); } +} + +namespace PR5810c { + template<typename T> + struct X { + X() { + T t; + double *****p = t; // expected-error{{cannot initialize a variable of type 'double *****' with an lvalue of type 'int'}} + } + X(const X&) { } + }; + + struct Y : X<int> { // expected-note{{instantiation of}} + }; + + void f(Y y = Y()); + + void g() { f(); } +} + +namespace PR8127 { + template< typename T > class PointerClass { + public: + PointerClass( T * object_p ) : p_( object_p ) { + p_->acquire(); + } + private: + T * p_; + }; + + class ExternallyImplementedClass; + + class MyClass { + void foo( PointerClass<ExternallyImplementedClass> = 0 ); + }; +} + +namespace rdar8427926 { + template<typename T> + struct Boom { + ~Boom() { + T t; + double *******ptr = t; // expected-error 2{{cannot initialize}} + } + }; + + Boom<float> *bfp; + + struct X { + void f(Boom<int> = Boom<int>()) { } // expected-note{{requested here}} + void g(int x = (delete bfp, 0)); // expected-note{{requested here}} + }; + + void test(X *x) { + x->f(); + x->g(); + } +} + +namespace PR8401 { + template<typename T> + struct A { + A() { T* x = 1; } // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + }; + + template<typename T> + struct B { + B(const A<T>& a = A<T>()); // expected-note{{in instantiation of}} + }; + + void f(B<int> b = B<int>()); + + void g() { + f(); + } +} + +namespace PR12581 { + const int a = 0; + template < typename > struct A; + template < typename MatrixType, int = + A < MatrixType >::Flags ? : A < MatrixType >::Flags & a > class B; + void + fn1 () + { + } +} diff --git a/clang/test/SemaTemplate/delegating-constructors.cpp b/clang/test/SemaTemplate/delegating-constructors.cpp new file mode 100644 index 0000000..e177b50 --- /dev/null +++ b/clang/test/SemaTemplate/delegating-constructors.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +namespace PR10457 { + + class string + { + string(const char* str, unsigned); + + public: + template <unsigned N> + string(const char (&str)[N]) + : string(str) {} // expected-error{{constructor for 'string<6>' creates a delegation cycle}} + }; + + void f() { + string s("hello"); + } + + struct Foo { + Foo(int) { } + + + template <typename T> + Foo(T, int i) : Foo(i) { } +}; + + void test_Foo() + { + Foo f(1, 1); + } +} diff --git a/clang/test/SemaTemplate/dependent-base-classes.cpp b/clang/test/SemaTemplate/dependent-base-classes.cpp new file mode 100644 index 0000000..895eacc --- /dev/null +++ b/clang/test/SemaTemplate/dependent-base-classes.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, typename U> +struct X0 : T::template apply<U> { + X0(U u) : T::template apply<U>(u) { } +}; + +template<typename T, typename U> +struct X1 : T::apply<U> { }; // expected-error{{use 'template' keyword to treat 'apply' as a dependent template name}} + +template<typename T> +struct X2 : vector<T> { }; // expected-error{{unknown template name 'vector'}} + +namespace PR6031 { + template<typename T> + struct A; + + template <class X> + struct C { }; + + template <class TT> + struct II { + typedef typename A<TT>::type type; + }; + + template <class TT> + struct FI : II<TT> + { + C<typename FI::type> a; + }; + + template <class TT> + struct FI2 + { + C<typename FI2::type> a; // expected-error{{no type named 'type' in 'FI2<TT>'}} \ + // expected-error{{C++ requires a type specifier for all declarations}} + }; + + template<typename T> + struct Base { + class Nested { }; + template<typename U> struct MemberTemplate { }; + int a; + }; + + template<typename T> + struct HasDepBase : Base<T> { + int foo() { + class HasDepBase::Nested nested; + typedef typename HasDepBase::template MemberTemplate<T>::type type; + return HasDepBase::a; + } + }; + + template<typename T> + struct NoDepBase { + int foo() { + class NoDepBase::Nested nested; // expected-error{{no class named 'Nested' in 'NoDepBase<T>'}} + typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \ + // FIXME: expected-error{{unqualified-id}} + return NoDepBase::a; // expected-error{{no member named 'a' in 'NoDepBase<T>'}} + } + }; +} + +namespace Ambig { + template<typename T> + struct Base1 { + typedef int type; // expected-note{{member found by ambiguous name lookup}} + }; + + struct Base2 { + typedef float type; // expected-note{{member found by ambiguous name lookup}} + }; + + template<typename T> + struct Derived : Base1<T>, Base2 { + typedef typename Derived::type type; // expected-error{{member 'type' found in multiple base classes of different types}} + type *foo(float *fp) { return fp; } + }; + + Derived<int> di; // expected-note{{instantiation of}} +} + +namespace PR6081 { + template<typename T> + struct A { }; + + template<typename T> + class B : public A<T> + { + public: + template< class X > + void f0(const X & k) + { + this->template f1<int>()(k); + } + }; + + template<typename T> + class C + { + public: + template< class X > + void f0(const X & k) + { + this->template f1<int>()(k); // expected-error{{'f1' following the 'template' keyword does not refer to a template}} \ + // FIXME: expected-error{{unqualified-id}} \ + // expected-error{{function-style cast or type construction}} \ + // expected-error{{expected expression}} + } + }; +} + +namespace PR6413 { + template <typename T> class Base_A { }; + + class Base_B { }; + + template <typename T> + class Derived + : public virtual Base_A<T> + , public virtual Base_B + { }; +} + +namespace PR5812 { + template <class T> struct Base { + Base* p; + }; + + template <class T> struct Derived: public Base<T> { + typename Derived::Base* p; // meaning Derived::Base<T> + }; + + Derived<int> di; +} diff --git a/clang/test/SemaTemplate/dependent-base-member-init.cpp b/clang/test/SemaTemplate/dependent-base-member-init.cpp new file mode 100644 index 0000000..1d4fed3 --- /dev/null +++ b/clang/test/SemaTemplate/dependent-base-member-init.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -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() {} +}; + +// PR6062 +namespace PR6062 { + template <typename T> + class A : public T::type + { + A() : T::type() + { + } + + template <typename U> + A(U const& init) + : T::type(init) + { } + + template<typename U> + A(U& init) : U::other_type(init) { } + }; +} + +template<typename T, typename U> +struct X0 : T::template apply<U> { + X0(int i) : T::template apply<U>(i) { } +}; + +// PR7698 +namespace PR7698 { + template<typename Type> + class A { + char mA[sizeof(Type *)]; + A(): mA() {} + }; +} diff --git a/clang/test/SemaTemplate/dependent-class-member-operator.cpp b/clang/test/SemaTemplate/dependent-class-member-operator.cpp new file mode 100644 index 0000000..d70a60c --- /dev/null +++ b/clang/test/SemaTemplate/dependent-class-member-operator.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR7837 + +template<class T> struct C1 { void operator()(T); }; +template<class T> struct C2; // expected-note {{template is declared here}} +template<class T> void foo(T); +void wrap() { + foo(&C1<int>::operator()); + foo(&C1<int>::operator+); // expected-error {{no member named 'operator+' in 'C1<int>'}} + foo(&C2<int>::operator+); // expected-error {{implicit instantiation of undefined template 'C2<int>'}} +} diff --git a/clang/test/SemaTemplate/dependent-expr.cpp b/clang/test/SemaTemplate/dependent-expr.cpp new file mode 100644 index 0000000..a1ddd24 --- /dev/null +++ b/clang/test/SemaTemplate/dependent-expr.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5908 +template <typename Iterator> +void Test(Iterator it) { + *(it += 1); +} + +namespace PR6045 { + template<unsigned int r> + class A + { + static const unsigned int member = r; + void f(); + }; + + template<unsigned int r> + const unsigned int A<r>::member; + + template<unsigned int r> + void A<r>::f() + { + unsigned k; + (void)(k % member); + } +} + +namespace PR7198 { + struct A + { + ~A() { } + }; + + template<typename T> + struct B { + struct C : A {}; + void f() + { + C c = C(); + } + }; +} + +namespace PR7724 { + template<typename OT> int myMethod() + { return 2 && sizeof(OT); } +} + +namespace test4 { + template <typename T> T *addressof(T &v) { + return reinterpret_cast<T*>( + &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); + } +} + +namespace test5 { + template <typename T> class chained_map { + int k; + void lookup() const { + int &v = (int &)k; + } + }; +} + +namespace PR8795 { + template <class _CharT> int test(_CharT t) + { + int data [] = { + sizeof(_CharT) > sizeof(char) + }; + return data[0]; + } +} diff --git a/clang/test/SemaTemplate/dependent-names-no-std.cpp b/clang/test/SemaTemplate/dependent-names-no-std.cpp new file mode 100644 index 0000000..2fb9d99 --- /dev/null +++ b/clang/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/clang/test/SemaTemplate/dependent-names.cpp b/clang/test/SemaTemplate/dependent-names.cpp new file mode 100644 index 0000000..924bad9 --- /dev/null +++ b/clang/test/SemaTemplate/dependent-names.cpp @@ -0,0 +1,326 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +typedef double A; +template<typename T> class B { + typedef int A; +}; + +template<typename T> struct X : B<T> { + static A a; +}; + +int a0[sizeof(X<int>::a) == sizeof(double) ? 1 : -1]; + +// PR4365. +template<class T> class Q; +template<class T> class R : Q<T> {T current;}; + + +namespace test0 { + template <class T> class Base { + public: + void instance_foo(); + static void static_foo(); + class Inner { + public: + void instance_foo(); + static void static_foo(); + }; + }; + + template <class T> class Derived1 : Base<T> { + public: + void test0() { + Base<T>::static_foo(); + Base<T>::instance_foo(); + } + + void test1() { + Base<T>::Inner::static_foo(); + Base<T>::Inner::instance_foo(); // expected-error {{call to non-static member function without an object argument}} + } + + static void test2() { + Base<T>::static_foo(); + Base<T>::instance_foo(); // expected-error {{call to non-static member function without an object argument}} + } + + static void test3() { + Base<T>::Inner::static_foo(); + Base<T>::Inner::instance_foo(); // expected-error {{call to non-static member function without an object argument}} + } + }; + + template <class T> class Derived2 : Base<T>::Inner { + public: + void test0() { + Base<T>::static_foo(); + Base<T>::instance_foo(); // expected-error {{call to non-static member function without an object argument}} + } + + void test1() { + Base<T>::Inner::static_foo(); + Base<T>::Inner::instance_foo(); + } + + static void test2() { + Base<T>::static_foo(); + Base<T>::instance_foo(); // expected-error {{call to non-static member function without an object argument}} + } + + static void test3() { + Base<T>::Inner::static_foo(); + Base<T>::Inner::instance_foo(); // expected-error {{call to non-static member function without an object argument}} + } + }; + + void test0() { + Derived1<int> d1; + d1.test0(); + d1.test1(); // expected-note {{in instantiation of member function}} + d1.test2(); // expected-note {{in instantiation of member function}} + d1.test3(); // expected-note {{in instantiation of member function}} + + Derived2<int> d2; + d2.test0(); // expected-note {{in instantiation of member function}} + d2.test1(); + d2.test2(); // expected-note {{in instantiation of member function}} + d2.test3(); // expected-note {{in instantiation of member function}} + } +} + +namespace test1 { + template <class T> struct Base { + void foo(T); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + }; + + template <class T> struct Derived : Base<T> { + void doFoo(T v) { + foo(v); // expected-error {{use of undeclared identifier}} + } + }; + + template struct Derived<int>; // expected-note {{requested here}} +} + +namespace PR8966 { + template <class T> + class MyClassCore + { + }; + + template <class T> + class MyClass : public MyClassCore<T> + { + public: + enum { + N + }; + + // static member declaration + static const char* array [N]; + + void f() { + MyClass<T>::InBase = 17; + } + }; + + // static member definition + 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}} + } + } +} + +namespace PR10187 { + namespace A { + template<typename T> + struct S { + void f() { + for (auto &a : e) + __range(a); // expected-error {{undeclared identifier '__range'}} + } + int e[10]; + }; + void g() { + S<int>().f(); // expected-note {{here}} + } + } + + namespace B { + template<typename T> void g(); // expected-note {{not viable}} + template<typename T> void f() { + g<int>(T()); // expected-error {{no matching function}} + } + + namespace { + struct S {}; + } + void g(S); + + template void f<S>(); // expected-note {{here}} + } +} + +namespace rdar11242625 { + +template <typename T> +struct Main { + struct default_names { + typedef int id; + }; + + template <typename T2 = typename default_names::id> + struct TS { + T2 q; + }; +}; + +struct Sub : public Main<int> { + TS<> ff; +}; + +int arr[sizeof(Sub)]; + +} + +namespace PR11421 { +template < unsigned > struct X { + static const unsigned dimension = 3; + template<unsigned dim=dimension> + struct Y: Y<dim> { }; // expected-error {{incomplete type}} expected-note {{is not complete until the closing}} +}; +typedef X<3> X3; +X3::Y<>::iterator it; // expected-note {{requested here}} +} diff --git a/clang/test/SemaTemplate/dependent-sized_array.cpp b/clang/test/SemaTemplate/dependent-sized_array.cpp new file mode 100644 index 0000000..cf0e0f3 --- /dev/null +++ b/clang/test/SemaTemplate/dependent-sized_array.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s + +template<int N> +void f() { + int a[] = { 1, 2, 3, N }; + unsigned numAs = sizeof(a) / sizeof(int); +} + +template void f<17>(); + + +template<int N> +void f1() { + int a0[] = {}; // expected-warning{{zero}} + int a1[] = { 1, 2, 3, N }; + int a3[sizeof(a1)/sizeof(int) != 4? 1 : -1]; // expected-error{{negative}} +} diff --git a/clang/test/SemaTemplate/dependent-template-recover.cpp b/clang/test/SemaTemplate/dependent-template-recover.cpp new file mode 100644 index 0000000..3c01f65 --- /dev/null +++ b/clang/test/SemaTemplate/dependent-template-recover.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U, int N> +struct X { + void f(T* t) { + t->f0<U>(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}} + t->f0<int>(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}} + + t->operator+<U const, 1>(); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}} + t->f1<int const, 2>(); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}} + + T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} + t->T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} + + // FIXME: We can't recover from these yet + (*t).f2<N>(); // expected-error{{expected expression}} + (*t).f2<0>(); // expected-error{{expected expression}} + } +}; + +namespace PR9401 { + // From GCC PR c++/45558 + template <typename S, typename T> + struct C + { + template <typename U> + struct B + { + template <typename W> + struct E + { + explicit E(const W &x) : w(x) {} + const W &w; + }; + }; + }; + + struct F; + template <typename X> + struct D + { + D() {} + }; + + const D<F> g; + template <typename S, typename T> + struct A + { + template <typename U> + struct B : C<S, T>::template B<U> + { + typedef typename C<S, T>::template B<U> V; + static const D<typename V::template E<D<F> > > a; + }; + }; + + template <typename S, typename T> + template <typename U> + const D<typename C<S, T>::template B<U>::template E<D<F> > > + A<S, T>::B<U>::a = typename C<S, T>::template B<U>::template E<D<F> >(g); +} diff --git a/clang/test/SemaTemplate/dependent-type-identity.cpp b/clang/test/SemaTemplate/dependent-type-identity.cpp new file mode 100644 index 0000000..731013c --- /dev/null +++ b/clang/test/SemaTemplate/dependent-type-identity.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test concerns the identity of dependent types within the +// canonical type system. This corresponds to C++ [temp.type], which +// specifies type equivalence within a template. +// +// FIXME: template template parameters + +namespace N { + template<typename T> + struct X2 { + template<typename U> + struct apply { + typedef U* type; + }; + }; +} + +namespace Nalias = N; + +template<typename T> +struct X0 { }; + +using namespace N; + +template<typename T, typename U> +struct X1 { + typedef T type; + typedef U U_type; + + void f0(T); // expected-note{{previous}} + void f0(U); + void f0(type); // expected-error{{redeclar}} + + void f1(T*); // expected-note{{previous}} + void f1(U*); + void f1(type*); // expected-error{{redeclar}} + + void f2(X0<T>*); // expected-note{{previous}} + void f2(X0<U>*); + void f2(X0<type>*); // expected-error{{redeclar}} + + void f3(X0<T>*); // expected-note{{previous}} + void f3(X0<U>*); + void f3(::X0<type>*); // expected-error{{redeclar}} + + void f4(typename T::template apply<U>*); // expected-note{{previous}} + void f4(typename U::template apply<U>*); + void f4(typename type::template apply<T>*); + void f4(typename type::template apply<U_type>*); // expected-error{{redeclar}} + + void f5(typename T::template apply<U>::type*); // expected-note{{previous}} + void f5(typename U::template apply<U>::type*); + void f5(typename U::template apply<T>::type*); + void f5(typename type::template apply<T>::type*); + void f5(typename type::template apply<U_type>::type*); // expected-error{{redeclar}} + + void f6(typename N::X2<T>::template apply<U> *); // expected-note{{previous}} + 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> *); + void f7(typename X2<type>::template apply<U_type> *); // expected-error{{redeclar}} + + void f8(typename N::X2<T>::template apply<U> *); // expected-note{{previous}} + void f8(typename N::X2<U>::template apply<U> *); + void f8(typename N::X2<U>::template apply<T> *); + void f8(typename ::Nalias::X2<type>::template apply<U_type> *); // expected-error{{redeclar}} +}; + +namespace PR6851 { + template <bool v> + struct S; + + struct N { + template <bool w> + S< S<w>::cond && 1 > foo(); + }; + + struct Alien; + bool operator&&(const Alien&, const Alien&); + + template <bool w> + S< S<w>::cond && 1 > N::foo() { } +} + +namespace PR7460 { + template <typename T> + struct TemplateClass2 + { + enum { SIZE = 100 }; + static T member[SIZE]; + }; + + template <typename T> + T TemplateClass2<T>::member[TemplateClass2<T>::SIZE]; +} diff --git a/clang/test/SemaTemplate/destructor-template.cpp b/clang/test/SemaTemplate/destructor-template.cpp new file mode 100644 index 0000000..07beda4 --- /dev/null +++ b/clang/test/SemaTemplate/destructor-template.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename A> class s0 { + + template<typename B> class s1 : public s0<A> { + ~s1() {} + s0<A> ms0; + }; + +}; + +struct Incomplete; + +template<typename T> +void destroy_me(T me) { + me.~T(); +} + +template void destroy_me(Incomplete*); + +namespace PR6152 { + template<typename T> struct X { void f(); }; + template<typename T> struct Y { }; + template<typename T> + void X<T>::f() { + Y<T> *y; + y->template Y<T>::~Y(); + y->template Y<T>::~Y<T>(); + y->~Y(); + } + + template struct X<int>; +} + +namespace cvquals { + template<typename T> + void f(int *ptr) { + ptr->~T(); + } + + template void f<const volatile int>(int *); +} + +namespace PR7239 { + template<class E> class A { }; + class B { + void f() { + A<int>* x; + x->A<int>::~A<int>(); + } + }; +} + +namespace PR7904 { + struct Foo { + template <int i> ~Foo() {} // expected-error{{destructor cannot be declared as a template}} + }; + Foo f; +} diff --git a/clang/test/SemaTemplate/elaborated-type-specifier.cpp b/clang/test/SemaTemplate/elaborated-type-specifier.cpp new file mode 100644 index 0000000..514c5f2 --- /dev/null +++ b/clang/test/SemaTemplate/elaborated-type-specifier.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR6915 { + template <typename T> + class D { + enum T::X v; // expected-error{{use of 'X' with tag type that does not match previous declaration}} \ + // expected-error{{no enum named 'X' in 'PR6915::D3'}} + }; + + struct D1 { + enum X { value }; + }; + struct D2 { + class X { }; // expected-note{{previous use is here}} + }; + struct D3 { }; + + template class D<D1>; + template class D<D2>; // expected-note{{in instantiation of}} + template class D<D3>; // expected-note{{in instantiation of}} +} + +template<typename T> +struct DeclOrDef { + enum T::foo; // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}} + enum T::bar { // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}} + value + }; +}; + +namespace PR6649 { + template <typename T> struct foo { + class T::bar; // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}} + class T::bar { int x; }; // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}} + }; +} + +namespace rdar8568507 { + template <class T> struct A *makeA(T t); +} diff --git a/clang/test/SemaTemplate/enum-argument.cpp b/clang/test/SemaTemplate/enum-argument.cpp new file mode 100644 index 0000000..7d23757 --- /dev/null +++ b/clang/test/SemaTemplate/enum-argument.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +enum Enum { val = 1 }; +template <Enum v> struct C { + typedef C<v> Self; +}; +template struct C<val>; + +template<typename T> +struct get_size { + static const unsigned value = sizeof(T); +}; + +template<typename T> +struct X0 { + enum { + Val1 = get_size<T>::value, + Val2, + SumOfValues = Val1 + Val2 + }; +}; + +X0<int> x0i; + +namespace rdar8020920 { + template<typename T> + struct X { + enum { e0 = 32 }; + + unsigned long long bitfield : e0; + + void f(int j) { + bitfield + j; + } + }; +} diff --git a/clang/test/SemaTemplate/enum-forward.cpp b/clang/test/SemaTemplate/enum-forward.cpp new file mode 100644 index 0000000..b25c21f --- /dev/null +++ b/clang/test/SemaTemplate/enum-forward.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -fms-compatibility %s + +template<typename T> +struct X { + enum E *e; +}; + +X<int> xi; diff --git a/clang/test/SemaTemplate/example-dynarray.cpp b/clang/test/SemaTemplate/example-dynarray.cpp new file mode 100644 index 0000000..999521e --- /dev/null +++ b/clang/test/SemaTemplate/example-dynarray.cpp @@ -0,0 +1,177 @@ +// RUN: %clangxx -emit-llvm -c -o - %s +#include <stddef.h> +#include <stdlib.h> +#include <assert.h> + +// Placement new requires <new> to be included, but we don't support that yet. +void* operator new(size_t, void* ptr) throw() { + return ptr; +} +void operator delete(void*, void*) throw() { +} + +template<typename T> +class dynarray { +public: + dynarray() { Start = Last = End = 0; } + + dynarray(const dynarray &other) { + Start = (T*)malloc(sizeof(T) * other.size()); + Last = End = Start + other.size(); + + for (unsigned I = 0, N = other.size(); I != N; ++I) + new (Start + I) T(other[I]); + } + + ~dynarray() { + for (unsigned I = 0, N = size(); I != N; ++I) + Start[I].~T(); + + free(Start); + } + + dynarray &operator=(const dynarray &other) { + T* NewStart = (T*)malloc(sizeof(T) * other.size()); + + for (unsigned I = 0, N = other.size(); I != N; ++I) + new (NewStart + I) T(other[I]); + + for (unsigned I = 0, N = size(); I != N; ++I) + Start[I].~T(); + + free(Start); + Start = NewStart; + Last = End = NewStart + other.size(); + return *this; + } + + unsigned size() const { return Last - Start; } + unsigned capacity() const { return End - Start; } + + void push_back(const T& value); + + void pop_back() { + --Last; + Last->~T(); + } + + T& operator[](unsigned Idx) { + return Start[Idx]; + } + + const T& operator[](unsigned Idx) const { + return Start[Idx]; + } + + typedef T* iterator; + typedef const T* const_iterator; + + iterator begin() { return Start; } + const_iterator begin() const { return Start; } + + iterator end() { return Last; } + const_iterator end() const { return Last; } + + bool operator==(const dynarray &other) const { + if (size() != other.size()) + return false; + + for (unsigned I = 0, N = size(); I != N; ++I) + if ((*this)[I] != other[I]) + return false; + + return true; + } + + bool operator!=(const dynarray &other) const { + return !(*this == other); + } + +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) { } + + float x, y, z; +}; + +int main() { + dynarray<int> di; + di.push_back(0); + di.push_back(1); + di.push_back(2); + di.push_back(3); + di.push_back(4); + assert(di.size() == 5); + for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I) + assert(*I == I - di.begin()); + + for (int I = 0, N = di.size(); I != N; ++I) + assert(di[I] == I); + + di.pop_back(); + assert(di.size() == 4); + di.push_back(4); + + dynarray<int> di2 = di; + assert(di2.size() == 5); + assert(di.begin() != di2.begin()); + for (dynarray<int>::iterator I = di2.begin(), IEnd = di2.end(); + I != IEnd; ++I) + assert(*I == I - di2.begin()); + + dynarray<int> di3(di); + assert(di3.size() == 5); + assert(di.begin() != di3.begin()); + for (dynarray<int>::iterator I = di3.begin(), IEnd = di3.end(); + I != IEnd; ++I) + assert(*I == I - di3.begin()); + + dynarray<int> di4; + assert(di4.size() == 0); + di4 = di; + assert(di4.size() == 5); + assert(di.begin() != di4.begin()); + for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end(); + I != IEnd; ++I) + assert(*I == I - di4.begin()); + + assert(di4 == di); + di4[3] = 17; + assert(di4 != di); + + dynarray<Point> dp; + dp.push_back(Point()); + assert(dp.size() == 1); + + return 0; +} diff --git a/clang/test/SemaTemplate/example-typelist.cpp b/clang/test/SemaTemplate/example-typelist.cpp new file mode 100644 index 0000000..082aeb8 --- /dev/null +++ b/clang/test/SemaTemplate/example-typelist.cpp @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A simple cons-style typelist +struct nil { }; + +template<typename Head, typename Tail = nil> +struct cons { + typedef Head head; + typedef Tail tail; +}; + +// is_same trait, for testing +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; +}; + +// metaprogram that computes the length of a list +template<typename T> struct length; + +template<typename Head, typename Tail> +struct length<cons<Head, Tail> > { + static const unsigned value = length<Tail>::value + 1; +}; + +template<> +struct length<nil> { + static const unsigned value = 0; +}; + +typedef cons<unsigned char, + cons<unsigned short, + cons<unsigned int, + cons<unsigned long> > > > unsigned_inttypes; +int length0[length<unsigned_inttypes>::value == 4? 1 : -1]; + +// metaprogram that reverses a list + +// FIXME: I would prefer that this be a partial specialization, but +// that requires partial ordering of class template partial +// specializations. +template<typename T> +class reverse { + typedef typename reverse<typename T::tail>::type reversed_tail; + + typedef typename reverse<typename reversed_tail::tail>::type most_of_tail; + +public: + typedef cons<typename reversed_tail::head, + typename reverse<cons<typename T::head, most_of_tail> >::type> type; +}; + +template<typename Head> +class reverse<cons<Head> > { +public: + typedef cons<Head> type; +}; + +template<> +class reverse<nil> { +public: + typedef nil type; +}; + +int reverse0[is_same<reverse<unsigned_inttypes>::type, + cons<unsigned long, + cons<unsigned int, + cons<unsigned short, + cons<unsigned char> > > > >::value? 1 : -1]; + +// metaprogram that finds a type within a list + +// FIXME: I would prefer that this be a partial specialization, but +// that requires partial ordering of class template partial +// specializations. +template<typename List, typename T> +struct find : find<typename List::tail, T> { }; + +template<typename Tail, typename T> +struct find<cons<T, Tail>, T> { + typedef cons<T, Tail> type; +}; + +template<typename T> +struct find<nil, T> { + typedef nil type; +}; + +int find0[is_same<find<unsigned_inttypes, unsigned int>::type, + cons<unsigned int, cons<unsigned long> > >::value? + 1 : -1]; +int find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1]; + diff --git a/clang/test/SemaTemplate/explicit-instantiation.cpp b/clang/test/SemaTemplate/explicit-instantiation.cpp new file mode 100644 index 0000000..13d76be --- /dev/null +++ b/clang/test/SemaTemplate/explicit-instantiation.cpp @@ -0,0 +1,107 @@ +// RUN: %clang_cc1 -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*) { return T(); } + + template<typename U> + T f0(T, U) { return T(); } +}; + +template<typename T> +T X0<T>::value; // expected-error{{no matching constructor}} + +template int X0<int>::value; + +struct NotDefaultConstructible { // expected-note{{candidate constructor (the implicit copy constructor)}} + NotDefaultConstructible(int); // expected-note{{candidate constructor}} +}; + +template NotDefaultConstructible X0<NotDefaultConstructible>::value; // expected-note{{instantiation}} + +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) { return T(); } + template<typename T> T* f1(T*) { return 0; } + + 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]); + +namespace explicit_instantiation_after_implicit_instantiation { + template <int I> struct X0 { static int x; }; + template <int I> int X0<I>::x; + void test1() { (void)&X0<1>::x; } + template struct X0<1>; +} + +template<typename> struct X3 { }; +inline template struct X3<int>; // expected-warning{{ignoring 'inline' keyword on explicit template instantiation}} +static template struct X3<float>; // expected-warning{{ignoring 'static' keyword on explicit template instantiation}} + +namespace PR7622 { + template<typename,typename=int> + struct basic_streambuf; + + template<typename,typename> + struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \ + // expected-error{{expected member name or ';' after declaration specifiers}} + template struct basic_streambuf<int>; +} + +// Test that we do not crash. +class TC1 { + class TC2 { + template // FIXME: error here. + void foo() { } + }; +}; diff --git a/clang/test/SemaTemplate/explicit-specialization-member.cpp b/clang/test/SemaTemplate/explicit-specialization-member.cpp new file mode 100644 index 0000000..7fe6bf3 --- /dev/null +++ b/clang/test/SemaTemplate/explicit-specialization-member.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -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); + +namespace PR6161 { + template<typename _CharT> + class numpunct : public locale::facet // expected-error{{use of undeclared identifier 'locale'}} \ + // expected-error{{expected class name}} + { + static locale::id id; // expected-error{{use of undeclared identifier}} + }; + numpunct<char>::~numpunct(); // expected-error{{expected the class name after '~' to name a destructor}} +} diff --git a/clang/test/SemaTemplate/ext-vector-type.cpp b/clang/test/SemaTemplate/ext-vector-type.cpp new file mode 100644 index 0000000..f968c13 --- /dev/null +++ b/clang/test/SemaTemplate/ext-vector-type.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, unsigned Length> +struct make1 { + typedef T __attribute__((ext_vector_type(Length))) type; +}; + +void test_make1() { + make1<int, 5>::type x; + x.x = 4; +} + +template<typename T, unsigned Length> +struct make2 { + typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{zero vector size}} +}; + +int test_make2() { + make2<int, 0> x; // expected-note{{in instantiation of}} +} + +template<typename T, unsigned Length> +struct make3 { + typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector element type 's'}} +}; + +struct s {}; + +int test_make3() { + make3<s, 3>x; // expected-note{{in instantiation of}} +} + +template<typename T, T Length> +struct make4 { + typedef T __attribute__((ext_vector_type(Length))) type; +}; + +int test_make4() { + make4<int, 4>::type x; + x.w = 7; +} + +typedef int* int_ptr; +template<unsigned Length> +struct make5 { + typedef int_ptr __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector element type}} +}; + +template<int Length> +struct make6 { + typedef int __attribute__((ext_vector_type(Length))) type; +}; + +int test_make6() { + make6<4>::type x; + x.w = 7; + + make6<2>::type y; + y.x = -1; + y.w = -1; // expected-error{{vector component access exceeds type}} +} + +namespace Deduction { + template<typename T> struct X0; + + template<typename T, unsigned N> + struct X0<T __attribute__((ext_vector_type(N)))> { + static const unsigned value = 0; + }; + + template<typename T> + struct X0<T __attribute__((ext_vector_type(4)))> { + static const unsigned value = 1; + }; + + template<unsigned N> + struct X0<float __attribute__((ext_vector_type(N)))> { + static const unsigned value = 2; + }; + + template<> + struct X0<float __attribute__((ext_vector_type(4)))> { + static const unsigned value = 3; + }; + + typedef int __attribute__((ext_vector_type(2))) int2; + typedef int __attribute__((ext_vector_type(4))) int4; + typedef float __attribute__((ext_vector_type(2))) float2; + typedef float __attribute__((ext_vector_type(4))) float4; + + int array0[X0<int2>::value == 0? 1 : -1]; + int array1[X0<int4>::value == 1? 1 : -1]; + int array2[X0<float2>::value == 2? 1 : -1]; + int array3[X0<float4>::value == 3? 1 : -1]; +} diff --git a/clang/test/SemaTemplate/extern-templates.cpp b/clang/test/SemaTemplate/extern-templates.cpp new file mode 100644 index 0000000..eca64ed --- /dev/null +++ b/clang/test/SemaTemplate/extern-templates.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -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); +} + +extern template class X0<long*>; + +void test_longptr(X0<long*> xl, X0<long*>::Inner xli) { + xl.f(0); + xli.g(0); +} + +template class X0<long*>; // expected-note 2{{instantiation}} + +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/clang/test/SemaTemplate/fibonacci.cpp b/clang/test/SemaTemplate/fibonacci.cpp new file mode 100644 index 0000000..ff1711f --- /dev/null +++ b/clang/test/SemaTemplate/fibonacci.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<unsigned I> +struct FibonacciEval; + +template<unsigned I> +struct Fibonacci { + enum { value = FibonacciEval<I-1>::value + FibonacciEval<I-2>::value }; +}; + +template<unsigned I> +struct FibonacciEval { + enum { value = Fibonacci<I>::value }; +}; + +template<> struct Fibonacci<0> { + enum { value = 0 }; +}; + +template<> struct Fibonacci<1> { + enum { value = 1 }; +}; + +int array5[Fibonacci<5>::value == 5? 1 : -1]; +int array10[Fibonacci<10>::value == 55? 1 : -1]; + +template<unsigned I> +struct FibonacciEval2; + +template<unsigned I> +struct Fibonacci2 { + static const unsigned value + = FibonacciEval2<I-1>::value + FibonacciEval2<I-2>::value; +}; + +template<unsigned I> +struct FibonacciEval2 { + static const unsigned value = Fibonacci2<I>::value; +}; + +template<> struct Fibonacci2<0> { + static const unsigned value = 0; +}; + +template<> struct Fibonacci2<1> { + static const unsigned value = 1; +}; + +int array5_2[Fibonacci2<5>::value == 5? 1 : -1]; +int array10_2[Fibonacci2<10>::value == 55? 1 : -1]; + +template<unsigned I> +struct Fibonacci3 { + static const unsigned value = Fibonacci3<I-1>::value + Fibonacci3<I-2>::value; +}; + +template<> struct Fibonacci3<0> { + static const unsigned value = 0; +}; + +template<> struct Fibonacci3<1> { + static const unsigned value = 1; +}; + +int array5_3[Fibonacci3<5>::value == 5? 1 : -1]; +int array10_3[Fibonacci3<10>::value == 55? 1 : -1]; diff --git a/clang/test/SemaTemplate/friend-template.cpp b/clang/test/SemaTemplate/friend-template.cpp new file mode 100644 index 0000000..9c95fa0 --- /dev/null +++ b/clang/test/SemaTemplate/friend-template.cpp @@ -0,0 +1,245 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR5057 +namespace test0 { + namespace std { + class X { + public: + template<typename T> friend struct Y; + }; + } + + namespace std { + template<typename T> struct Y {}; + } +} + +namespace test1 { + 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 +namespace test2 { + 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; + X0<int*> x0ip; + + 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); +} + +// PR5332 +namespace test3 { + template <typename T> class Foo { + template <typename U> + friend class Foo; + }; + + Foo<int> foo; + + template<typename T, T Value> struct X2a; + + template<typename T, int Size> struct X2b; + + template<typename T> + class X3 { + template<typename U, U Value> friend struct X2a; + + // FIXME: the redeclaration note ends up here because redeclaration + // lookup ends up finding the friend target from X3<int>. + template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \ + // expected-note {{previous non-type template parameter with type 'int' is here}} + }; + + X3<int> x3i; // okay + + X3<long> x3l; // expected-note {{in instantiation}} +} + +// PR5716 +namespace test4 { + template<typename> struct A { + template<typename T> friend void f(const A<T>&); + }; + + template<typename T> void f(const A<T>&) { + int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}} + } + + void f() { + f(A<int>()); // expected-note {{in instantiation of function template specialization}} + } +} + +namespace test5 { + class outer { + class foo; + template <typename T> friend struct cache; + }; + class outer::foo { + template <typename T> friend struct cache; + }; +} + +// PR6022 +namespace PR6022 { + template <class T1, class T2 , class T3 > class A; + + namespace inner { + template<class T1, class T2, class T3, class T> + A<T1, T2, T3>& f0(A<T1, T2, T3>&, T); + } + + template<class T1, class T2, class T3> + class A { + template<class U1, class U2, class U3, class T> + friend A<U1, U2, U3>& inner::f0(A<U1, U2, U3>&, T); + }; +} + +namespace FriendTemplateDefinition { + template<unsigned > struct int_c { }; + + template<typename T> + struct X { + template<unsigned N> + friend void f(X, int_c<N>) { + int value = N; + }; + }; + + void test_X(X<int> x, int_c<5> i5) { + f(x, i5); + } +} + +namespace PR7013a { + template<class > struct X0 + { + typedef int type; + }; + template<typename > struct X1 + { + }; + template<typename , typename T> struct X2 + { + typename T::type e; + }; + namespace N + { + template <typename = int, typename = X1<int> > struct X3 + { + template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B); + }; + template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B) + { + X2<int, Tr> s; + } + } + int n() + { + X2<int, X0<int> > ngs; + N::X3<> b; + op(ngs, b); + return 0; + } +} + +namespace PR7013b { + template<class > struct X0 + { + typedef int type; + }; + template<typename > struct X1 + { + }; + template<typename , typename T> struct X2 + { + typename T::type e; + }; + namespace N + { + template <typename = X1<int> > struct X3 + { + template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B); + }; + template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B) + { + X2<int, Tr> s; + } + } + int n() + { + X2<int, X0<int> > ngs; + N::X3<> b; + op(ngs, b); + return 0; + } + +} + +namespace PR8649 { + template<typename T, typename U, unsigned N> + struct X { + template<unsigned M> friend class X<T, U, M>; // expected-error{{partial specialization cannot be declared as a friend}} + }; + + 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>; +} + +namespace PR10660 { + struct A { + template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}} + }; +} + +namespace rdar11147355 { + template <class T> + struct A { + template <class U> class B; + template <class S> template <class U> friend class A<S>::B; + }; + + template <class S> template <class U> class A<S>::B { + }; + + A<double>::B<double> ab; +} diff --git a/clang/test/SemaTemplate/friend.cpp b/clang/test/SemaTemplate/friend.cpp new file mode 100644 index 0000000..e78a067 --- /dev/null +++ b/clang/test/SemaTemplate/friend.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -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>; +}; + +namespace PR6770 { + namespace N { + int f1(int); + } + using namespace N; + + namespace M { + float f1(float); + } + using M::f1; + + template<typename T> void f1(T, T); + template <class T> + void f() { + friend class f; // expected-error{{'friend' used outside of class}} + friend class f1; // expected-error{{'friend' used outside of class}} + } +} diff --git a/clang/test/SemaTemplate/fun-template-def.cpp b/clang/test/SemaTemplate/fun-template-def.cpp new file mode 100644 index 0000000..0427781 --- /dev/null +++ b/clang/test/SemaTemplate/fun-template-def.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Tests that dependent expressions are always allowed, whereas non-dependent +// are checked as usual. + +#include <stddef.h> + +// Fake typeid, lacking a typeinfo header. +namespace std { class type_info {}; } + +struct dummy {}; // expected-note 3 {{candidate constructor (the implicit copy constructor)}} + +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 f1(T t1, U u1, int i1) +{ + T t2 = i1; + t2 = i1 + u1; + ++u1; + u1++; + int i2 = u1; + + i1 = t1[u1]; + i1 *= t1; + + i1(u1, t1); // error + u1(i1, t1); + + U u2 = (T)i1; + static_cast<void>(static_cast<U>(reinterpret_cast<T>( + dynamic_cast<U>(const_cast<T>(i1))))); + + new U(i1, t1); + new int(t1, u1); + new (t1, u1) int; + delete t1; + + dummy d1 = sizeof(t1); // expected-error {{no viable conversion}} + dummy d2 = offsetof(T, foo); // expected-error {{no viable conversion}} + dummy d3 = __alignof(u1); // expected-error {{no viable conversion}} + i1 = typeid(t1); // expected-error {{assigning to 'int' from incompatible type 'const std::type_info'}} + + return u1; +} diff --git a/clang/test/SemaTemplate/function-template-specialization.cpp b/clang/test/SemaTemplate/function-template-specialization.cpp new file mode 100644 index 0000000..a0d41b2 --- /dev/null +++ b/clang/test/SemaTemplate/function-template-specialization.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -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}} + +// PR5833 +namespace PR5833 { + template <typename T> bool f0(T &t1); + template <> bool f0<float>(float &t1); +} +template <> bool PR5833::f0<float>(float &t1) {} + +// PR8295 +namespace PR8295 { + template <typename T> void f(T t) {} + template <typename T> void f<T*>(T* t) {} // expected-error{{function template partial specialization is not allowed}} +} diff --git a/clang/test/SemaTemplate/implicit-instantiation-1.cpp b/clang/test/SemaTemplate/implicit-instantiation-1.cpp new file mode 100644 index 0000000..d1bc5a8 --- /dev/null +++ b/clang/test/SemaTemplate/implicit-instantiation-1.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U> +struct X { + T f(T x, U y) { return x + y; } + + unsigned g(T x, U y) { return sizeof(f(x, y)); } +}; + +void test(X<int, int> *xii, X<int*, int> *xpi, X<int, int*> *xip) { + (void)xii->f(1, 2); + (void)xpi->f(0, 2); + (void)sizeof(xip->f(2, 0)); // okay: does not instantiate + (void)xip->g(2, 0); // okay: does not instantiate +} + +template<typename T, typename U> +T add(T t, U u) { + return t + u; // expected-error{{invalid operands}} +} + +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)); +} diff --git a/clang/test/SemaTemplate/inject-templated-friend-post.cpp b/clang/test/SemaTemplate/inject-templated-friend-post.cpp new file mode 100644 index 0000000..39c445c --- /dev/null +++ b/clang/test/SemaTemplate/inject-templated-friend-post.cpp @@ -0,0 +1,72 @@ +// RUN: %clang %s -S -emit-llvm -o - | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE" +// RUN: %clang %s -S -emit-llvm -o - -DPROTOTYPE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE" +// RUN: %clang %s -S -emit-llvm -o - -DINSTANTIATE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE" +// RUN: %clang %s -S -emit-llvm -o - -DPROTOTYPE -DINSTANTIATE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE" +// RUN: %clang_cc1 %s -DREDEFINE -verify +// RUN: %clang_cc1 %s -DPROTOTYPE -DREDEFINE -verify +// PR8007: friend function not instantiated, reordered version. +// Corresponds to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38392 + +struct std_ostream +{ + int dummy; +}; + +std_ostream cout; + +template <typename STRUCT_TYPE> +struct Streamer; + +typedef struct Foo {} Foo; + +std_ostream& operator << (std_ostream&, const Streamer<Foo>&); + +void test(const Streamer<Foo>& foo) +{ + cout << foo; +} + +template <typename STRUCT_TYPE> +struct Streamer +{ + friend std_ostream& operator << (std_ostream& o, const Streamer& f) // expected-error{{redefinition of 'operator<<'}} + { + Streamer s(f); + s(o); + return o; + } + + Streamer(const STRUCT_TYPE& s) : s(s) {} + + const STRUCT_TYPE& s; + void operator () (std_ostream&) const; +}; + +#ifdef PROTOTYPE +std_ostream& operator << (std_ostream&, const Streamer<Foo>&); +#endif + +#ifdef INSTANTIATE +template struct Streamer<Foo>; +#endif + +#ifdef REDEFINE +std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}} +{ + return o; +} +#endif + +#ifndef INSTANTIATE +template <> +void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}} +{ +} +#endif + +int main(void) +{ + Foo foo; + test(foo); +} + diff --git a/clang/test/SemaTemplate/inject-templated-friend.cpp b/clang/test/SemaTemplate/inject-templated-friend.cpp new file mode 100644 index 0000000..7be613b --- /dev/null +++ b/clang/test/SemaTemplate/inject-templated-friend.cpp @@ -0,0 +1,48 @@ +// RUN: %clang %s -S -emit-llvm -o - | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE" +// RUN: %clang_cc1 %s -DREDEFINE -verify +// PR8007: friend function not instantiated. + +struct std_ostream +{ + int dummy; +}; + +std_ostream cout; + +template <typename STRUCT_TYPE> +struct Streamer +{ + friend std_ostream& operator << (std_ostream& o, const Streamer& f) // expected-error{{redefinition of 'operator<<'}} + { + Streamer s(f); + s(o); + return o; + } + + Streamer(const STRUCT_TYPE& s) : s(s) {} + + const STRUCT_TYPE& s; + void operator () (std_ostream&) const; +}; + +typedef struct Foo {} Foo; + +std_ostream& operator << (std_ostream&, const Streamer<Foo>&); +#ifdef REDEFINE +std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}} +{ + // Sema should flag this as a redefinition + return o; +} +#endif + +template <> +void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}} +{ +} + +int main(void) +{ + Foo foo; + cout << foo; +} diff --git a/clang/test/SemaTemplate/injected-class-name.cpp b/clang/test/SemaTemplate/injected-class-name.cpp new file mode 100644 index 0000000..4c21d25 --- /dev/null +++ b/clang/test/SemaTemplate/injected-class-name.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +struct X { + X<T*> *ptr; +}; + +X<int> x; + +template<> +struct X<int***> { + typedef X<int***> *ptr; +}; + +X<float>::X<int> xi = x; // expected-error{{qualified reference to 'X' is a constructor name rather than a template name wherever a constructor can be declared}} + +// [temp.local]p1: + +// FIXME: test template template parameters +template<typename T, typename U> +struct X0 { + typedef T type; + typedef U U_type; + typedef U_type U_type2; + + void f0(const X0&); // expected-note{{here}} + void f0(X0&); + void f0(const X0<T, U>&); // expected-error{{redecl}} + + void f1(const X0&); // expected-note{{here}} + void f1(X0&); + void f1(const X0<type, U_type2>&); // expected-error{{redecl}} + + void f2(const X0&); // expected-note{{here}} + 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}} +}; + +namespace pr6326 { + template <class T> class A { + friend class A; + }; + template class A<int>; +} + +namespace ForwardDecls { + template<typename T> + struct X; + + template<typename T> + struct X { + typedef T foo; + typedef X<T> xt; + typename xt::foo *t; + }; +} diff --git a/clang/test/SemaTemplate/instantiate-anonymous-union.cpp b/clang/test/SemaTemplate/instantiate-anonymous-union.cpp new file mode 100644 index 0000000..68b233a --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-anonymous-union.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -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); + +namespace PR7088 { + template<typename T> + void f() { + union { + int a; + union { + float real; + T d; + }; + }; + + a = 17; + d = 3.14; + } + + template void f<double>(); +} + +// Check for problems related to PR7402 that occur when template instantiation +// instantiates implicit initializers. +namespace PR7402 { + struct X { + union { + struct { + int x; + int y; + }; + int v[2]; + }; + + // Check that this requirement survives instantiation. + template <typename T> X(const T& t) : x(t), y(t) {} + }; + + X x(42.0); +} + +namespace PR9188 { + struct X0 { + union { + int member; + }; + }; + + static union { + int global; + }; + + struct X1 : X0 { + template<typename T> + int f() { + return this->X0::member + PR9188::global; + } + }; + + template int X1::f<int>(); +} diff --git a/clang/test/SemaTemplate/instantiate-array.cpp b/clang/test/SemaTemplate/instantiate-array.cpp new file mode 100644 index 0000000..b8229d3 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-array.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) +#define __CONCAT1(__X, __Y) __X ## __Y + +#define static_assert(__b, __m) \ + typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1] +#endif + +template <int N> class IntArray { + int elems[N]; +}; + +static_assert(sizeof(IntArray<10>) == sizeof(int) * 10, "Array size mismatch"); +static_assert(sizeof(IntArray<1>) == sizeof(int) * 1, "Array size mismatch"); + +template <typename T> class TenElementArray { + int elems[10]; +}; + +static_assert(sizeof(TenElementArray<int>) == sizeof(int) * 10, "Array size mismatch"); + +template<typename T, int N> class Array { + T elems[N]; +}; + +static_assert(sizeof(Array<int, 10>) == sizeof(int) * 10, "Array size mismatch"); diff --git a/clang/test/SemaTemplate/instantiate-attr.cpp b/clang/test/SemaTemplate/instantiate-attr.cpp new file mode 100644 index 0000000..bbadb63 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-attr.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template <typename T> +struct A { + char a __attribute__((aligned(16))); + + struct B { + typedef T __attribute__((aligned(16))) i16; + i16 x; + }; +}; +int a[sizeof(A<int>) == 16 ? 1 : -1]; +int a2[sizeof(A<int>::B) == 16 ? 1 : -1]; + +// rdar://problem/8243419 +namespace test1 { + template <typename T> struct A { + int a; + T b[0]; + } __attribute__((packed)); + + typedef A<unsigned long> type; + + int test0[sizeof(type) == 4 ? 1 : -1]; + int test1[__builtin_offsetof(type, a) == 0 ? 1 : -1]; + int test2[__builtin_offsetof(type, b) == 4 ? 1 : -1]; +} diff --git a/clang/test/SemaTemplate/instantiate-c99.cpp b/clang/test/SemaTemplate/instantiate-c99.cpp new file mode 100644 index 0000000..ae15528 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-c99.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test template instantiation for C99-specific features. + +// --------------------------------------------------------------------- +// Designated initializers +// --------------------------------------------------------------------- +template<typename T, typename XType, typename YType> +struct DesigInit0 { + void f(XType x, YType y) { + T agg = { + .y = y, // expected-error{{does not refer}} + .x = x // expected-error{{does not refer}} + }; + } +}; + +struct Point2D { + float x, y; +}; + +template struct DesigInit0<Point2D, int, double>; + +struct Point3D { + float x, y, z; +}; + +template struct DesigInit0<Point3D, int, double>; + +struct Color { + unsigned char red, green, blue; +}; + +struct ColorPoint3D { + Color color; + float x, y, z; +}; + +template struct DesigInit0<ColorPoint3D, int, double>; +template struct DesigInit0<Color, int, double>; // expected-note{{instantiation}} + +template<typename T, int Subscript1, int Subscript2, + typename Val1, typename Val2> +struct DesigArrayInit0 { + void f(Val1 val1, Val2 val2) { + T array = { + [Subscript1] = val1, + [Subscript2] = val2 // expected-error{{exceeds array bounds}} + }; + + int array2[10] = { [5] = 3 }; + } +}; + +template struct DesigArrayInit0<int[8], 5, 3, float, int>; +template struct DesigArrayInit0<int[8], 5, 13, float, int>; // expected-note{{instantiation}} + +template<typename T, int Subscript1, int Subscript2, + typename Val1> +struct DesigArrayRangeInit0 { + void f(Val1 val1) { + T array = { + [Subscript1...Subscript2] = val1 // expected-error{{exceeds}} + }; + } +}; + +template struct DesigArrayRangeInit0<int[8], 3, 5, float>; +template struct DesigArrayRangeInit0<int[8], 5, 13, float>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Compound literals +// --------------------------------------------------------------------- +template<typename T, typename Arg1, typename Arg2> +struct CompoundLiteral0 { + T f(Arg1 a1, Arg2 a2) { + return (T){a1, a2}; + } +}; + +template struct CompoundLiteral0<Point2D, int, float>; diff --git a/clang/test/SemaTemplate/instantiate-call.cpp b/clang/test/SemaTemplate/instantiate-call.cpp new file mode 100644 index 0000000..da1eb49 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-call.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N1 { + struct X0 { }; + + int& f0(X0); +} + +namespace N2 { + char& f0(char); + + template<typename T, typename Result> + struct call_f0 { + void test_f0(T t) { + Result result = f0(t); + } + }; +} + +template struct N2::call_f0<int, char&>; +template struct N2::call_f0<N1::X0, int&>; + +namespace N3 { + template<typename T, typename Result> + struct call_f0 { + void test_f0(T t) { + Result &result = f0(t); // expected-error {{undeclared identifier}} \ + expected-error {{neither visible in the template definition nor found by argument-dependent lookup}} + } + }; +} + +template struct N3::call_f0<int, char&>; // expected-note{{instantiation}} +template struct N3::call_f0<N1::X0, int&>; + +short& f0(char); // expected-note {{should be declared prior to the call site}} +namespace N4 { + template<typename T, typename Result> + struct call_f0 { + void test_f0(T t) { + Result &result = f0(t); + } + }; +} + +template struct N4::call_f0<int, short&>; +template struct N4::call_f0<N1::X0, int&>; +template struct N3::call_f0<int, short&>; // expected-note{{instantiation}} + +// FIXME: test overloaded function call operators, calls to member +// functions, etc. diff --git a/clang/test/SemaTemplate/instantiate-case.cpp b/clang/test/SemaTemplate/instantiate-case.cpp new file mode 100644 index 0000000..1cc2d5d --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-case.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> +static int alpha(T c) +{ + return *c; // expected-error{{indirection requires pointer operand}} +} + +template<class T> +static void +_shexp_match() +{ + switch(1) { + case 1: + alpha(1); // expected-note{{instantiation of function template}} + } +} +int main() { + _shexp_match<char>(); // expected-note{{instantiation of function template}} + return 0; +} diff --git a/clang/test/SemaTemplate/instantiate-cast.cpp b/clang/test/SemaTemplate/instantiate-cast.cpp new file mode 100644 index 0000000..b3babf1 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-cast.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { int x; }; // expected-note 2 {{candidate constructor}} + +class Base { +public: + virtual void f(); +}; + +class Derived : public Base { }; + +struct ConvertibleToInt { + operator int() const; +}; + +struct Constructible { + Constructible(int, float); +}; + +// --------------------------------------------------------------------- +// C-style casts +// --------------------------------------------------------------------- +template<typename T, typename U> +struct CStyleCast0 { + void f(T t) { + (void)((U)t); // expected-error{{cannot convert 'A' to 'int' without a conversion operator}} + } +}; + +template struct CStyleCast0<int, float>; +template struct CStyleCast0<A, int>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// static_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct StaticCast0 { + void f(T t) { + (void)static_cast<U>(t); // expected-error{{no matching conversion for static_cast from 'int' to 'A'}} + } +}; + +template struct StaticCast0<ConvertibleToInt, bool>; +template struct StaticCast0<int, float>; +template struct StaticCast0<int, A>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// dynamic_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct DynamicCast0 { + void f(T t) { + (void)dynamic_cast<U>(t); // expected-error{{not a reference or pointer}} + } +}; + +template struct DynamicCast0<Base*, Derived*>; +template struct DynamicCast0<Base*, A>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// reinterpret_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct ReinterpretCast0 { + void f(T t) { + (void)reinterpret_cast<U>(t); // expected-error{{qualifiers}} + } +}; + +template struct ReinterpretCast0<void (*)(int), void (*)(float)>; +template struct ReinterpretCast0<int const *, float *>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// const_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct ConstCast0 { + void f(T t) { + (void)const_cast<U>(t); // expected-error{{not allowed}} + } +}; + +template struct ConstCast0<int const * *, int * *>; +template struct ConstCast0<int const *, float *>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// C++ functional cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct FunctionalCast1 { + void f(T t) { + (void)U(t); // expected-error{{cannot convert 'A' to 'int' without a conversion operator}} + } +}; + +template struct FunctionalCast1<int, float>; +template struct FunctionalCast1<A, int>; // expected-note{{instantiation}} + +// Generates temporaries, which we cannot handle yet. +template<int N, long M> +struct FunctionalCast2 { + void f() { + (void)Constructible(N, M); + } +}; + +template struct FunctionalCast2<1, 3>; + +// --------------------------------------------------------------------- +// implicit casting +// --------------------------------------------------------------------- +template<typename T> +struct Derived2 : public Base { }; + +void test_derived_to_base(Base *&bp, Derived2<int> *dp) { + bp = dp; +} diff --git a/clang/test/SemaTemplate/instantiate-clang.cpp b/clang/test/SemaTemplate/instantiate-clang.cpp new file mode 100644 index 0000000..34d68c4 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-clang.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test template instantiation for Clang-specific features. + +// --------------------------------------------------------------------- +// Vector types +// --------------------------------------------------------------------- +typedef __attribute__(( ext_vector_type(2) )) double double2; +typedef __attribute__(( ext_vector_type(4) )) double double4; + +template<typename T> +struct ExtVectorAccess0 { + void f(T v1, double4 v2) { + v1.xy = v2.yx; + } +}; + +template struct ExtVectorAccess0<double2>; +template struct ExtVectorAccess0<double4>; + +typedef __attribute__(( ext_vector_type(2) )) double double2; + +template<typename T, typename U, int N, int M> +struct ShuffleVector0 { + void f(T t, U u, double2 a, double2 b) { + (void)__builtin_shufflevector(t, u, N, M); // expected-error{{index}} + (void)__builtin_shufflevector(a, b, N, M); // expected-error{{index}} + (void)__builtin_shufflevector(a, b, 2, 1); + } +}; + +template struct ShuffleVector0<double2, double2, 2, 1>; +template struct ShuffleVector0<double2, double2, 4, 3>; // expected-note{{instantiation}} + + diff --git a/clang/test/SemaTemplate/instantiate-complete.cpp b/clang/test/SemaTemplate/instantiate-complete.cpp new file mode 100644 index 0000000..68d5ae3 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-complete.cpp @@ -0,0 +1,146 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Tests various places where requiring a complete type involves +// instantiation of that type. + +template<typename T> +struct X { + X(T); + + T f; // expected-error{{data member instantiated with function type 'float (int)'}} \ + // expected-error{{data member instantiated with function type 'int (int)'}} \ + // expected-error{{data member instantiated with function type 'char (char)'}} \ + // expected-error{{data member instantiated with function type 'short (short)'}} \ + // expected-error{{data member instantiated with function type 'float (float)'}} +}; + +X<int> f() { return 0; } + +struct XField { + X<float(int)> xf; // expected-note{{in instantiation of template class 'X<float (int)>' requested here}} +}; + +void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) { + (void)ptr1[i]; + (void)ptr2[i]; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}} +} + +void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2, + X<char(char)> *ptr3, X<short(short)> *ptr4) { + (void)(ptr1 + 5); + (void)(5 + ptr2); + (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'X<char (char)>' requested here}} + (void)(5 + ptr4); // expected-note{{in instantiation of template class 'X<short (short)>' requested here}} +} + +void test_new() { + (void)new X<float>(0); + (void)new X<float(float)>; // expected-note{{in instantiation of template class 'X<float (float)>' requested here}} +} + +void test_memptr(X<long> *p1, long X<long>::*pm1, + X<long(long)> *p2, + long (X<long(long)>::*pm2)(long)) { + (void)(p1->*pm1); +} + +// Reference binding to a base +template<typename T> +struct X1 { }; + +template<typename T> +struct X2 : public T { }; + +void refbind_base(X2<X1<int> > &x2) { + X1<int> &x1 = x2; +} + +// Enumerate constructors for user-defined conversion. +template<typename T> +struct X3 { + X3(T); +}; + +void enum_constructors(X1<float> &x1) { + X3<X1<float> > x3 = x1; +} + +namespace PR6376 { + template<typename T, typename U> struct W { }; + + template<typename T> + struct X { + template<typename U> + struct apply { + typedef W<T, U> type; + }; + }; + + template<typename T, typename U> + struct Y : public X<T>::template apply<U>::type { }; + + template struct Y<int, float>; +} + +namespace TemporaryObjectCopy { + // Make sure we instantiate classes when we create a temporary copy. + template<typename T> + struct X { + X(T); + }; + + template<typename T> + void f(T t) { + const X<int> &x = X<int>(t); + } + + template void f(int); +} + +namespace PR7080 { + template <class T, class U> + class X + { + typedef char true_t; + class false_t { char dummy[2]; }; + static true_t dispatch(U); + static false_t dispatch(...); + static T trigger(); + public: + enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) }; + }; + + template <class T> + class rv : public T + { }; + + bool x = X<int, rv<int>&>::value; +} + +namespace pr7199 { + template <class T> class A; // expected-note {{template is declared here}} + template <class T> class B { + class A<T>::C field; // expected-error {{implicit instantiation of undefined template 'pr7199::A<int>'}} + }; + + template class B<int>; // expected-note {{in instantiation}} +} + +namespace PR8425 { + template <typename T> + class BaseT {}; + + template <typename T> + class DerivedT : public BaseT<T> {}; + + template <typename T> + class FromT { + public: + operator DerivedT<T>() const { return DerivedT<T>(); } + }; + + void test() { + FromT<int> ft; + BaseT<int> bt(ft); + } +} diff --git a/clang/test/SemaTemplate/instantiate-decl-dtor.cpp b/clang/test/SemaTemplate/instantiate-decl-dtor.cpp new file mode 100644 index 0000000..193d976 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-decl-dtor.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify + +template <typename T> struct A { + T x; + A(int y) { x = y; } + ~A() { *x = 10; } // expected-error {{indirection requires pointer operand}} +}; + +void a() { + A<int> b = 10; // expected-note {{requested here}} +} diff --git a/clang/test/SemaTemplate/instantiate-decl-init.cpp b/clang/test/SemaTemplate/instantiate-decl-init.cpp new file mode 100644 index 0000000..6b76d72 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-decl-init.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5426 - the non-dependent obj would be fully processed and wrapped in a +// CXXConstructExpr at definition time, which would lead to a failure at +// instantiation time. +struct arg { + arg(); +}; + +struct oldstylemove { + oldstylemove(oldstylemove&); + oldstylemove(const arg&); +}; + +template <typename T> +void fn(T t, const arg& arg) { + oldstylemove obj(arg); +} + +void test() { + fn(1, arg()); +} + +struct X0 { }; + +struct X1 { + explicit X1(const X0 &x0 = X0()); +}; + +template<typename T> +void f0() { + X1 x1; +} + +template void f0<int>(); +template void f0<float>(); + +struct NonTrivial { + NonTrivial(); + ~NonTrivial(); +}; + +template<int N> void f1() { + NonTrivial array[N]; +} +template<> void f1<2>(); diff --git a/clang/test/SemaTemplate/instantiate-declref-ice.cpp b/clang/test/SemaTemplate/instantiate-declref-ice.cpp new file mode 100644 index 0000000..49b1b63 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-declref-ice.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<int i> struct x { + static const int j = i; + x<j>* y; +}; + +template<int i> +const int x<i>::j; + +int array0[x<2>::j]; + +template<typename T> +struct X0 { + static const unsigned value = sizeof(T); +}; + +template<typename T> +const unsigned X0<T>::value; + +int array1[X0<int>::value == sizeof(int)? 1 : -1]; + +const unsigned& testX0() { return X0<int>::value; } + +int array2[X0<int>::value == sizeof(int)? 1 : -1]; + +template<typename T> +struct X1 { + static const unsigned value; +}; + +template<typename T> +const unsigned X1<T>::value = sizeof(T); + +int array3[X1<int>::value == sizeof(int)? 1 : -1]; diff --git a/clang/test/SemaTemplate/instantiate-declref.cpp b/clang/test/SemaTemplate/instantiate-declref.cpp new file mode 100644 index 0000000..7d4a2ff --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-declref.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace N { + struct Outer { + struct Inner { + template<typename T> + struct InnerTemplate { + struct VeryInner { + typedef T type; + + static enum K1 { K1Val = sizeof(T) } Kind1; + static enum { K2Val = sizeof(T)*2 } Kind2; + enum { K3Val = sizeof(T)*2 } Kind3; + + void foo() { + K1 k1 = K1Val; + Kind1 = K1Val; + Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val; + Kind3 = K3Val; + } + + struct UeberInner { + void bar() { + K1 k1 = K1Val; + Kind1 = K1Val; + Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val; + + InnerTemplate t; + InnerTemplate<type> t2; + } + }; + }; + }; + }; + }; +} + +typedef int INT; +template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner; +template struct N::Outer::Inner::InnerTemplate<INT>::UeberInner; // expected-error{{no struct named 'UeberInner' in 'N::Outer::Inner::InnerTemplate<int>'}} + +namespace N2 { + struct Outer2 { + template<typename T, typename U = T> + struct Inner { + void foo() { + enum { K1Val = sizeof(T) } k1; + enum K2 { K2Val = sizeof(T)*2 } k2a; + + K2 k2b = K2Val; + + struct S { T x, y; } s1; + struct { U x, y; } s2; + s1.x = s2.x; // expected-error{{incompatible}} + + typedef T type; + type t2 = s1.x; + + typedef struct { T z; } type2; + type2 t3 = { s1.x }; + + Inner i1; + i1.foo(); + Inner<T> i2; + i2.foo(); + } + }; + }; +} + +template struct N2::Outer2::Inner<float>; +template struct N2::Outer2::Inner<int*, float*>; // expected-note{{instantiation}} + +// Test dependent pointer-to-member expressions. +template<typename T> +struct smart_ptr { + struct safe_bool { + int member; + }; + + operator int safe_bool::*() const { + return ptr? &safe_bool::member : 0; + } + + T* ptr; +}; + +void test_smart_ptr(smart_ptr<int> p) { + if (p) { } +} + +// PR5517 +namespace test0 { + template <int K> struct X { + X() { extern void x(); } + }; + void g() { X<2>(); } +} + +// <rdar://problem/8302161> +namespace test1 { + template <typename T> void f(T const &t) { + union { char c; T t_; }; + c = 'a'; // <- this shouldn't silently fail to instantiate + T::foo(); // expected-error {{has no members}} + } + template void f(int const &); // expected-note {{requested here}} +} + +namespace test2 { + template<typename T> void f() { + T::error; // expected-error {{no member}} + } + void g() { + // This counts as an odr-use, so should trigger the instantiation of f<int>. + (void)&f<int>; // expected-note {{here}} + } +} diff --git a/clang/test/SemaTemplate/instantiate-deeply.cpp b/clang/test/SemaTemplate/instantiate-deeply.cpp new file mode 100644 index 0000000..c5f6594 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-deeply.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -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; + +// PR5352 +template <typename T> +class Foo { +public: + Foo() {} + + struct Bar { + T value; + }; + + Bar u; +}; + +template class Foo<int>; diff --git a/clang/test/SemaTemplate/instantiate-default-assignment-operator.cpp b/clang/test/SemaTemplate/instantiate-default-assignment-operator.cpp new file mode 100644 index 0000000..31cdef5 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-default-assignment-operator.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct PassRefPtr { }; +template<typename T> struct RefPtr { + RefPtr& operator=(const RefPtr&) { int a[sizeof(T) ? -1 : -1];} // expected-error 2 {{array with a negative size}} + RefPtr& operator=(const PassRefPtr<T>&); +}; + +struct A { RefPtr<int> a; }; // expected-note {{instantiation of member function 'RefPtr<int>::operator=' requested here}} +struct B : RefPtr<float> { }; // expected-note {{in instantiation of member function 'RefPtr<float>::operator=' requested here}} + +void f() { + A a1, a2; + a1 = a2; + + B b1, b2; + b1 = b2; +} diff --git a/clang/test/SemaTemplate/instantiate-dependent-nested-name.cpp b/clang/test/SemaTemplate/instantiate-dependent-nested-name.cpp new file mode 100644 index 0000000..eb1d3fb --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-dependent-nested-name.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR4382 +template<typename T> struct X { static const T A = 1; }; +template<typename T, bool = X<T>::A> struct Y { typedef T A; }; +template<typename T> struct Z { typedef typename Y<T>::A A; }; +extern int x; +extern Z<int>::A x; diff --git a/clang/test/SemaTemplate/instantiate-elab-type-specifier.cpp b/clang/test/SemaTemplate/instantiate-elab-type-specifier.cpp new file mode 100644 index 0000000..e5e10a8 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-elab-type-specifier.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5681 +template <class T> struct Base { + struct foo {}; + int foo; +}; + +template <class T> struct Derived : Base<T> { + typedef struct Base<T>::foo type; +}; + +template struct Derived<int>; diff --git a/clang/test/SemaTemplate/instantiate-enum-2.cpp b/clang/test/SemaTemplate/instantiate-enum-2.cpp new file mode 100644 index 0000000..aa3b590 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-enum-2.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify + +template<int IntBits> struct X { + enum { + IntShift = (unsigned long long)IntBits, + ShiftedIntMask = (1 << IntShift) + }; +}; +X<1> x; diff --git a/clang/test/SemaTemplate/instantiate-enum.cpp b/clang/test/SemaTemplate/instantiate-enum.cpp new file mode 100644 index 0000000..5353a92 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-enum.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T, T I, int J> +struct adder { + enum { + value = I + J, + value2 + }; +}; + +int array1[adder<long, 3, 4>::value == 7? 1 : -1]; + +namespace PR6375 { + template<typename T> + void f() { + enum Enum + { + enumerator1 = 0xFFFFFFF, + enumerator2 = enumerator1 - 1 + }; + + int xb1 = enumerator1; + int xe1 = enumerator2; + } + + template void f<int>(); +} diff --git a/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp b/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp new file mode 100644 index 0000000..8a6f9ef --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -ftemplate-depth 16 -fcxx-exceptions -fexceptions %s + +// DR1330: an exception specification for a function template is only +// instantiated when it is needed. + +template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'Incomplete' is not allowed in exception specification}} +struct Incomplete; // expected-note{{forward}} + +void test_f1(Incomplete *incomplete_p, int *int_p) { + f1(int_p); + f1(incomplete_p); // expected-note{{instantiation of exception spec}} +} + +template<typename T> struct A { + template<typename U> struct B { + static void f() noexcept(A<U>().n); + }; + + constexpr A() : n(true) {} + bool n; +}; + +static_assert(noexcept(A<int>::B<char>::f()), ""); + +template<unsigned N> struct S { + static void recurse() noexcept(noexcept(S<N+1>::recurse())); // \ + // expected-error {{no member named 'recurse'}} \ + // expected-note 9{{instantiation of exception spec}} +}; +decltype(S<0>::recurse()) *pVoid1 = 0; // ok, exception spec not needed +decltype(&S<0>::recurse) pFn = 0; // ok, exception spec not needed + +template<> struct S<10> {}; +void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of exception spec}} expected-error {{not superset}} + + +template<typename T> T go(T a) noexcept(noexcept(go(a))); // \ +// expected-error 16{{call to function 'go' that is neither visible}} \ +// expected-note 16{{'go' should be declared prior to the call site}} \ +// expected-error {{recursive template instantiation exceeded maximum depth of 16}} \ +// expected-error {{use of undeclared identifier 'go'}} \ + +void f() { + int k = go(0); // \ + // expected-note {{in instantiation of exception specification for 'go<int>' requested here}} +} + + +namespace dr1330_example { + template <class T> struct A { + void f(...) throw (typename T::X); // expected-error {{'int'}} + void f(int); + }; + + int main() { + A<int>().f(42); + } + + int test2() { + struct S { + template<typename T> + static int f() noexcept(noexcept(A<T>().f("boo!"))) { return 0; } // \ + // expected-note {{instantiation of exception spec}} + typedef decltype(f<S>()) X; + }; + S().f<S>(); // ok + S().f<int>(); // expected-note {{instantiation of exception spec}} + } +} + +namespace core_19754_example { + template<typename T> T declval() noexcept; + + template<typename T, typename = decltype(T(declval<T&&>()))> + struct is_movable { static const bool value = true; }; + + template<typename T> + struct wrap { + T val; + void irrelevant(wrap &p) noexcept(is_movable<T>::value); + }; + + template<typename T> + struct base { + base() {} + base(const typename T::type1 &); + base(const typename T::type2 &); + }; + + template<typename T> + struct type1 { + wrap<typename T::base> base; + }; + + template<typename T> + struct type2 { + wrap<typename T::base> base; + }; + + struct types { + typedef base<types> base; + typedef type1<types> type1; + typedef type2<types> type2; + }; + + base<types> val = base<types>(); +} + +namespace pr9485 { + template <typename T> void f1(T) throw(typename T::exception); // expected-note {{candidate}} + template <typename T> void f1(T, int = 0) throw(typename T::noitpecxe); // expected-note {{candidate}} + + template <typename T> void f2(T) noexcept(T::throws); // expected-note {{candidate}} + template <typename T> void f2(T, int = 0) noexcept(T::sworht); // expected-note {{candidate}} + + void test() { + f1(0); // expected-error {{ambiguous}} + f2(0); // expected-error {{ambiguous}} + } +} + +struct Exc1 { char c[4]; }; +struct Exc2 { double x, y, z; }; +struct Base { + virtual void f() noexcept; // expected-note {{overridden}} +}; +template<typename T> struct Derived : Base { + void f() noexcept (sizeof(T) == 4); // expected-error {{is more lax}} + void g() noexcept (T::error); +}; + +Derived<Exc1> d1; // ok +Derived<Exc2> d2; // expected-note {{in instantiation of}} diff --git a/clang/test/SemaTemplate/instantiate-exception-spec.cpp b/clang/test/SemaTemplate/instantiate-exception-spec.cpp new file mode 100644 index 0000000..d4f12df --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-exception-spec.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: the "note" should be down at the call site! +template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'Incomplete' is not allowed in exception specification}} \ + // expected-note{{instantiation of}} +struct Incomplete; // expected-note{{forward}} + +void test_f1(Incomplete *incomplete_p, int *int_p) { + f1(int_p); + f1(incomplete_p); +} diff --git a/clang/test/SemaTemplate/instantiate-expr-1.cpp b/clang/test/SemaTemplate/instantiate-expr-1.cpp new file mode 100644 index 0000000..9395117 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-expr-1.cpp @@ -0,0 +1,192 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<int I, int J> +struct Bitfields { + int simple : I; // expected-error{{bit-field 'simple' has zero width}} + int parens : (J); +}; + +void test_Bitfields(Bitfields<0, 5> *b) { + (void)sizeof(Bitfields<10, 5>); + (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'Bitfields<0, 1>' requested here}} +} + +template<int I, int J> +struct BitfieldPlus { + int bitfield : I + J; // expected-error{{bit-field 'bitfield' has zero width}} +}; + +void test_BitfieldPlus() { + (void)sizeof(BitfieldPlus<0, 1>); + (void)sizeof(BitfieldPlus<-5, 5>); // expected-note{{in instantiation of template class 'BitfieldPlus<-5, 5>' requested here}} +} + +template<int I, int J> +struct BitfieldMinus { + int bitfield : I - J; // expected-error{{bit-field 'bitfield' has negative width (-1)}} \ + // expected-error{{bit-field 'bitfield' has zero width}} +}; + +void test_BitfieldMinus() { + (void)sizeof(BitfieldMinus<5, 1>); + (void)sizeof(BitfieldMinus<0, 1>); // expected-note{{in instantiation of template class 'BitfieldMinus<0, 1>' requested here}} + (void)sizeof(BitfieldMinus<5, 5>); // expected-note{{in instantiation of template class 'BitfieldMinus<5, 5>' requested here}} +} + +template<int I, int J> +struct BitfieldDivide { + int bitfield : I / J; // expected-error{{expression is not an integral constant expression}} \ + // expected-note{{division by zero}} +}; + +void test_BitfieldDivide() { + (void)sizeof(BitfieldDivide<5, 1>); + (void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'BitfieldDivide<5, 0>' requested here}} +} + +template<typename T, T I, int J> +struct BitfieldDep { + int bitfield : I + J; +}; + +void test_BitfieldDep() { + (void)sizeof(BitfieldDep<int, 1, 5>); +} + +template<int I> +struct BitfieldNeg { + int bitfield : (-I); // expected-error{{bit-field 'bitfield' has negative width (-5)}} +}; + +template<typename T, T I> +struct BitfieldNeg2 { + int bitfield : (-I); // expected-error{{bit-field 'bitfield' has negative width (-5)}} +}; + +void test_BitfieldNeg() { + (void)sizeof(BitfieldNeg<-5>); // okay + (void)sizeof(BitfieldNeg<5>); // expected-note{{in instantiation of template class 'BitfieldNeg<5>' requested here}} + (void)sizeof(BitfieldNeg2<int, -5>); // okay + (void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'BitfieldNeg2<int, 5>' requested here}} +} + +template<typename T> +void increment(T &x) { + (void)++x; +} + +struct Incrementable { + Incrementable &operator++(); +}; + +void test_increment(Incrementable inc) { + increment(inc); +} + +template<typename T> +void add(const T &x) { + (void)(x + x); +} + +namespace PR6237 { + template <typename T> + void f(T t) { + t++; + } + + struct B { }; + B operator++(B &, int); + + template void f(B); +} + +struct Addable { + Addable operator+(const Addable&) const; +}; + +void test_add(Addable &a) { + add(a); +} + +struct CallOperator { + int &operator()(int); + double &operator()(double); +}; + +template<typename Result, typename F, typename Arg1> +Result test_call_operator(F f, Arg1 arg1) { + // PR5266: non-dependent invocations of a function call operator. + CallOperator call_op; + int &ir = call_op(17); + return f(arg1); +} + +void test_call_operator(CallOperator call_op, int i, double d) { + int &ir = test_call_operator<int&>(call_op, i); + double &dr = test_call_operator<double&>(call_op, d); +} + +template<typename T> +void test_asm(T t) { + asm ("nop" : "=a"(*t) : "r"(*t)); // expected-error {{indirection requires pointer operand ('int' invalid)}} +} + +void test_asm() { + int* a; + test_asm(a); + + int b; + test_asm(b); // expected-note {{in instantiation of function template specialization 'test_asm<int>' requested here}} +} + +namespace PR6424 { + template<int I> struct X { + X() { + int *ip = I; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + } + }; + + template<int> struct Y { + typedef X<7> X7; + + void f() { X7(); } // expected-note{{instantiation}} + }; + + template void Y<3>::f(); + + template<int I> + struct X2 { + void *operator new(__SIZE_TYPE__) { + int *ip = I; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + return ip; + } + }; + + template<int> struct Y2 { + typedef X2<7> X; + void f() { + new X(); // expected-note{{instantiation of}} + } + }; + + template void Y2<3>::f(); + + template<typename T> + void rdar10283928(int count) { + (void)new char[count](); + } + + template void rdar10283928<int>(int); +} + +namespace PR10864 { + template<typename T> class Vals {}; + template<> class Vals<int> { public: static const int i = 1; }; + template<> class Vals<float> { public: static const double i; }; + template<typename T> void test_asm_tied(T o) { + __asm("addl $1, %0" : "=r" (o) : "0"(Vals<T>::i)); // expected-error {{input with type 'double' matching output with type 'float'}} + } + void test_asm_tied() { + test_asm_tied(1); + test_asm_tied(1.f); // expected-note {{instantiation of}} + } +} diff --git a/clang/test/SemaTemplate/instantiate-expr-2.cpp b/clang/test/SemaTemplate/instantiate-expr-2.cpp new file mode 100644 index 0000000..eaa68dd --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-expr-2.cpp @@ -0,0 +1,245 @@ +// RUN: %clang_cc1 -fsyntax-only %s +typedef char one_byte; +typedef char (&two_bytes)[2]; +typedef char (&four_bytes)[4]; +typedef char (&eight_bytes)[8]; + +template<int N> struct A { }; + +namespace N1 { + struct X { }; +} + +namespace N2 { + struct Y { }; + + two_bytes operator+(Y, Y); +} + +namespace N3 { + struct Z { }; + + eight_bytes operator+(Z, Z); +} + +namespace N4 { + one_byte operator+(N1::X, N2::Y); + + template<typename T, typename U> + struct BinOpOverload { + typedef A<sizeof(T() + U())> type; + }; +} + +namespace N1 { + four_bytes operator+(X, X); +} + +namespace N3 { + eight_bytes operator+(Z, Z); // redeclaration +} + +void test_bin_op_overload(A<1> *a1, A<2> *a2, A<4> *a4, A<8> *a8) { + typedef N4::BinOpOverload<N1::X, N2::Y>::type XY; + XY *xy = a1; + typedef N4::BinOpOverload<N1::X, N1::X>::type XX; + XX *xx = a4; + typedef N4::BinOpOverload<N2::Y, N2::Y>::type YY; + YY *yy = a2; + typedef N4::BinOpOverload<N3::Z, N3::Z>::type ZZ; + ZZ *zz = a8; +} + +namespace N3 { + eight_bytes operator-(::N3::Z); +} + +namespace N4 { + template<typename T> + struct UnaryOpOverload { + typedef A<sizeof(-T())> type; + }; +} + +void test_unary_op_overload(A<8> *a8) { + typedef N4::UnaryOpOverload<N3::Z>::type UZ; + UZ *uz = a8; +} + +/* +namespace N5 { + template<int I> + struct Lookup { + enum { val = I, more = val + 1 }; + }; + + template<bool B> + struct Cond { + enum Junk { is = B ? Lookup<B>::more : Lookup<Lookup<B+1>::more>::val }; + }; + + enum { resultT = Cond<true>::is, + resultF = Cond<false>::is }; +} +*/ + +namespace N6 { + // non-typedependent + template<int I> + struct Lookup {}; + + template<bool B, typename T, typename E> + struct Cond { + typedef Lookup<B ? sizeof(T) : sizeof(E)> True; + typedef Lookup<!B ? sizeof(T) : sizeof(E)> False; + }; + + typedef Cond<true, int, char>::True True; + typedef Cond<true, int, char>::False False; + + // check that we have the right types + Lookup<1> const &L1(False()); + Lookup<sizeof(int)> const &L2(True()); +} + + +namespace N7 { + // type dependent + template<int I> + struct Lookup {}; + + template<bool B, typename T, typename E> + struct Cond { + T foo() { return B ? T() : E(); } + typedef Lookup<sizeof(B ? T() : E())> Type; + }; + + //Cond<true, int*, double> C; // Errors + //int V(C.foo()); // Errors + //typedef Cond<true, int*, double>::Type Type; // Errors + typedef Cond<true, int, double>::Type Type; +} + +template<typename T, unsigned long N> struct IntegralConstant { }; + +template<typename T> +struct X0 { + void f(T x, IntegralConstant<T, sizeof(x)>); +}; + +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>; +} + +namespace N12 { + // PR5224 + template<typename T> + struct A { typedef int t0; }; + + struct C { + C(int); + + template<typename T> + static C *f0(T a0) {return new C((typename A<T>::t0) 1); } + }; + + void f0(int **a) { C::f0(a); } +} + +namespace PR7202 { + template<typename U, typename T> + struct meta { + typedef T type; + }; + + struct X { + struct dummy; + + template<typename T> + X(T, typename meta<T, dummy*>::type = 0); + + template<typename T, typename A> + X(T, A); + }; + + template<typename T> + struct Z { }; + + template<typename T> Z<T> g(T); + + struct Y { + template<typename T> + void f(T t) { + new X(g(*this)); + } + }; + + template void Y::f(int); +} + +namespace N13 { + class A{ + A(const A&); + + public: + ~A(); + A(int); + template<typename T> A &operator<<(const T&); + }; + + template<typename T> + void f(T t) { + A(17) << t; + } + + template void f(int); + +} diff --git a/clang/test/SemaTemplate/instantiate-expr-3.cpp b/clang/test/SemaTemplate/instantiate-expr-3.cpp new file mode 100644 index 0000000..ca88b00 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-expr-3.cpp @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// --------------------------------------------------------------------- +// Imaginary literals +// --------------------------------------------------------------------- +template<typename T> +struct ImaginaryLiteral0 { + void f(T &x) { + x = 3.0I; // expected-error{{incompatible type}} + } +}; + +template struct ImaginaryLiteral0<_Complex float>; +template struct ImaginaryLiteral0<int*>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Compound assignment operator +// --------------------------------------------------------------------- +namespace N1 { + struct X { }; + + int& operator+=(X&, int); // expected-note{{candidate}} +} + +namespace N2 { + long& operator+=(N1::X&, long); // expected-note{{candidate}} + + template<typename T, typename U, typename Result> + struct PlusEquals0 { + void f(T t, U u) { + Result r = t += u; // expected-error{{ambiguous}} + } + }; +} + +namespace N3 { + struct Y : public N1::X { + short& operator+=(long); // expected-note{{candidate}} + }; +} + +template struct N2::PlusEquals0<N1::X, int, int&>; +template struct N2::PlusEquals0<N1::X, long, long&>; +template struct N2::PlusEquals0<N3::Y, long, short&>; +template struct N2::PlusEquals0<int, int, int&>; +template struct N2::PlusEquals0<N3::Y, int, short&>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Conditional operator +// --------------------------------------------------------------------- +template<typename T, typename U, typename Result> +struct Conditional0 { + void f(T t, U u) { + Result result = t? : u; + } +}; + +template struct Conditional0<int, int, int>; + +// --------------------------------------------------------------------- +// Statement expressions +// --------------------------------------------------------------------- +template<typename T> +struct StatementExpr0 { + void f(T t) { + (void)({ + if (t) // expected-error{{contextually convertible}} + t = t + 17; + t + 12; // expected-error{{invalid operands}} + }); + } +}; + +template struct StatementExpr0<int>; +template struct StatementExpr0<N1::X>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// __builtin_choose_expr +// --------------------------------------------------------------------- +template<bool Cond, typename T, typename U, typename Result> +struct Choose0 { + void f(T t, U u) { + Result r = __builtin_choose_expr(Cond, t, u); // expected-error{{lvalue}} + } +}; + +template struct Choose0<true, int, float, int&>; +template struct Choose0<false, int, float, float&>; +template struct Choose0<true, int, float, float&>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// __builtin_va_arg +// --------------------------------------------------------------------- +template<typename ArgType> +struct VaArg0 { + void f(int n, ...) { + __builtin_va_list va; + __builtin_va_start(va, n); + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); + __builtin_va_end(va); + } +}; + +template struct VaArg0<int>; + +template<typename VaList, typename ArgType> +struct VaArg1 { + void f(int n, ...) { + VaList va; + __builtin_va_start(va, n); // expected-error{{int}} + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); // expected-error{{int}} + __builtin_va_end(va); // expected-error{{int}} + } +}; + +template struct VaArg1<__builtin_va_list, int>; +template struct VaArg1<int, int>; // expected-note{{instantiation}} diff --git a/clang/test/SemaTemplate/instantiate-expr-4.cpp b/clang/test/SemaTemplate/instantiate-expr-4.cpp new file mode 100644 index 0000000..d95ccfe --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-expr-4.cpp @@ -0,0 +1,354 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s + +// --------------------------------------------------------------------- +// C++ Functional Casts +// --------------------------------------------------------------------- +template<int N> +struct ValueInit0 { + int f() { + return int(); + } +}; + +template struct ValueInit0<5>; + +template<int N> +struct FunctionalCast0 { + int f() { + return int(N); + } +}; + +template struct FunctionalCast0<5>; + +struct X { // expected-note 3 {{candidate constructor (the implicit copy constructor)}} + X(int, int); // expected-note 3 {{candidate constructor}} +}; + +template<int N, int M> +struct BuildTemporary0 { + X f() { + return X(N, M); + } +}; + +template struct BuildTemporary0<5, 7>; + +template<int N, int M> +struct Temporaries0 { + void f() { + (void)X(N, M); + } +}; + +template struct Temporaries0<5, 7>; + +// Ensure that both the constructor and the destructor are instantiated by +// checking for parse errors from each. +template<int N> struct BadX { + BadX() { int a[-N]; } // expected-error {{array with a negative size}} + ~BadX() { int a[-N]; } // expected-error {{array with a negative size}} +}; + +template<int N> +struct PR6671 { + void f() { (void)BadX<1>(); } // expected-note 2 {{instantiation}} +}; +template struct PR6671<1>; + +// --------------------------------------------------------------------- +// new/delete expressions +// --------------------------------------------------------------------- +struct Y { }; + +template<typename T> +struct New0 { + T* f(bool x) { + if (x) + return new T; // expected-error{{no matching}} + else + return new T(); + } +}; + +template struct New0<int>; +template struct New0<Y>; +template struct New0<X>; // expected-note{{instantiation}} + +template<typename T, typename Arg1> +struct New1 { + T* f(bool x, Arg1 a1) { + return new T(a1); // expected-error{{no matching}} + } +}; + +template struct New1<int, float>; +template struct New1<Y, Y>; +template struct New1<X, Y>; // expected-note{{instantiation}} + +template<typename T, typename Arg1, typename Arg2> +struct New2 { + T* f(bool x, Arg1 a1, Arg2 a2) { + return new T(a1, a2); // expected-error{{no matching}} + } +}; + +template struct New2<X, int, float>; +template struct New2<X, int, int*>; // expected-note{{instantiation}} +// FIXME: template struct New2<int, int, float>; + +// PR5833 +struct New3 { + New3(); + + void *operator new[](__SIZE_TYPE__) __attribute__((unavailable)); // expected-note{{explicitly made unavailable}} +}; + +template<class C> +void* object_creator() { + return new C(); // expected-error{{call to unavailable function 'operator new[]'}} +} + +template void *object_creator<New3[4]>(); // expected-note{{instantiation}} + +template<typename T> +struct Delete0 { + void f(T t) { + delete t; // expected-error{{cannot delete}} + ::delete [] t; // expected-error{{cannot delete}} + } +}; + +template struct Delete0<int*>; +template struct Delete0<X*>; +template struct Delete0<int>; // expected-note{{instantiation}} + +namespace PR5755 { + template <class T> + void Foo() { + char* p = 0; + delete[] p; + } + + void Test() { + Foo<int>(); + } +} + +namespace PR10480 { + template<typename T> + struct X { + X(); + ~X() { + T *ptr = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + } + }; + + template<typename T> + void f() { + new X<int>[1]; // expected-note{{in instantiation of member function 'PR10480::X<int>::~X' requested here}} + } + + template void f<int>(); +} + +// --------------------------------------------------------------------- +// throw expressions +// --------------------------------------------------------------------- +template<typename T> +struct Throw1 { + void f(T t) { + throw; + throw t; // expected-error{{incomplete type}} + } +}; + +struct Incomplete; // expected-note 2{{forward}} + +template struct Throw1<int>; +template struct Throw1<int*>; +template struct Throw1<Incomplete*>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// typeid expressions +// --------------------------------------------------------------------- + +namespace std { + class type_info; +} + +template<typename T> +struct TypeId0 { + const std::type_info &f(T* ptr) { + if (ptr) + return typeid(ptr); + else + return typeid(T); // expected-error{{'typeid' of incomplete type 'Incomplete'}} + } +}; + +struct Abstract { + virtual void f() = 0; +}; + +template struct TypeId0<int>; +template struct TypeId0<Incomplete>; // expected-note{{instantiation of member function}} +template struct TypeId0<Abstract>; + +// --------------------------------------------------------------------- +// type traits +// --------------------------------------------------------------------- +template<typename T> +struct is_pod { + static const bool value = __is_pod(T); +}; + +static int is_pod0[is_pod<X>::value? -1 : 1]; +static int is_pod1[is_pod<Y>::value? 1 : -1]; + +// --------------------------------------------------------------------- +// initializer lists +// --------------------------------------------------------------------- +template<typename T, typename Val1> +struct InitList1 { + void f(Val1 val1) { + T x = { val1 }; + } +}; + +struct APair { + int *x; + const float *y; +}; + +template struct InitList1<int[1], float>; +template struct InitList1<APair, int*>; + +template<typename T, typename Val1, typename Val2> +struct InitList2 { + void f(Val1 val1, Val2 val2) { + T x = { val1, val2 }; // expected-error{{cannot initialize}} + } +}; + +template struct InitList2<APair, int*, float*>; +template struct InitList2<APair, int*, double*>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// member references +// --------------------------------------------------------------------- +template<typename T, typename Result> +struct DotMemRef0 { + void f(T t) { + Result result = t.m; // expected-error{{non-const lvalue reference to type}} + } +}; + +struct MemInt { + int m; +}; + +struct InheritsMemInt : MemInt { }; + +struct MemIntFunc { + static int m(int); +}; + +template struct DotMemRef0<MemInt, int&>; +template struct DotMemRef0<InheritsMemInt, int&>; +template struct DotMemRef0<MemIntFunc, int (*)(int)>; +template struct DotMemRef0<MemInt, float&>; // expected-note{{instantiation}} + +template<typename T, typename Result> +struct ArrowMemRef0 { + void f(T t) { + Result result = t->m; // expected-error 2{{non-const lvalue reference}} + } +}; + +template<typename T> +struct ArrowWrapper { + T operator->(); +}; + +template struct ArrowMemRef0<MemInt*, int&>; +template struct ArrowMemRef0<InheritsMemInt*, int&>; +template struct ArrowMemRef0<MemIntFunc*, int (*)(int)>; +template struct ArrowMemRef0<MemInt*, float&>; // expected-note{{instantiation}} + +template struct ArrowMemRef0<ArrowWrapper<MemInt*>, int&>; +template struct ArrowMemRef0<ArrowWrapper<InheritsMemInt*>, int&>; +template struct ArrowMemRef0<ArrowWrapper<MemIntFunc*>, int (*)(int)>; +template struct ArrowMemRef0<ArrowWrapper<MemInt*>, float&>; // expected-note{{instantiation}} +template struct ArrowMemRef0<ArrowWrapper<ArrowWrapper<MemInt*> >, int&>; + +struct UnresolvedMemRefArray { + int f(int); + int f(char); +}; +UnresolvedMemRefArray Arr[10]; +template<typename U> int UnresolvedMemRefArrayT(U u) { + return Arr->f(u); +} +template int UnresolvedMemRefArrayT<int>(int); + +// FIXME: we should be able to return a MemInt without the reference! +MemInt &createMemInt(int); + +template<int N> +struct NonDepMemberExpr0 { + void f() { + createMemInt(N).m = N; + } +}; + +template struct NonDepMemberExpr0<0>; + +template<typename T, typename Result> +struct MemberFuncCall0 { + void f(T t) { + Result result = t.f(); + } +}; + +template<typename T> +struct HasMemFunc0 { + T f(); +}; + + +template struct MemberFuncCall0<HasMemFunc0<int&>, const int&>; + +template<typename Result> +struct ThisMemberFuncCall0 { + Result g(); + + void f() { + Result r1 = g(); + Result r2 = this->g(); + } +}; + +template struct ThisMemberFuncCall0<int&>; + +template<typename T> +struct NonDepMemberCall0 { + void foo(HasMemFunc0<int&> x) { + T result = x.f(); // expected-error{{non-const lvalue reference}} + } +}; + +template struct NonDepMemberCall0<int&>; +template struct NonDepMemberCall0<const int&>; +template struct NonDepMemberCall0<float&>; // expected-note{{instantiation}} + + +template<typename T> +struct QualifiedDeclRef0 { + T f() { + return is_pod<X>::value; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'const bool'}} + } +}; + +template struct QualifiedDeclRef0<bool>; +template struct QualifiedDeclRef0<int&>; // expected-note{{instantiation}} diff --git a/clang/test/SemaTemplate/instantiate-expr-5.cpp b/clang/test/SemaTemplate/instantiate-expr-5.cpp new file mode 100644 index 0000000..13b7eae --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-expr-5.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class A> int x(A x) { return x++; } +int y() { return x<int>(1); } + +namespace PR5880 { + template<typename T> + struct A { + static const int a = __builtin_offsetof(T, a.array[5].m); // expected-error{{no member named 'a' in 'HasM'}} + }; + struct HasM { + float m; + }; + + struct ArrayOfHasM { + HasM array[10]; + }; + + struct B { ArrayOfHasM a; }; + A<B> x; + A<HasM> x2; // expected-note{{in instantiation of}} + + template<typename T> + struct AnonymousUnion { + union { + int i; + float f; + }; + }; + + template<typename T> + void test_anon_union() { + int array1[__builtin_offsetof(AnonymousUnion<T>, f) == 0? 1 : -1]; + int array2[__builtin_offsetof(AnonymousUnion<int>, f) == 0? 1 : -1]; + } + + template void test_anon_union<int>(); +} diff --git a/clang/test/SemaTemplate/instantiate-expr-basic.cpp b/clang/test/SemaTemplate/instantiate-expr-basic.cpp new file mode 100644 index 0000000..a266a65 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-expr-basic.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++11 %s + +template <typename T> +struct S { + void f() { + __func__; // PredefinedExpr + 10; // IntegerLiteral + 10.5; // FloatingLiteral + 'c'; // CharacterLiteral + "hello"; // StringLiteral + true; // CXXBooleanLiteralExpr + nullptr; // CXXNullPtrLiteralExpr + __null; // GNUNullExpr + } +}; + +template struct S<int>; diff --git a/clang/test/SemaTemplate/instantiate-field.cpp b/clang/test/SemaTemplate/instantiate-field.cpp new file mode 100644 index 0000000..a148ee4 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-field.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X { + int x; + T y; // expected-error{{data member instantiated with function type}} + T* z; + T bitfield : 12; // expected-error{{bit-field 'bitfield' has non-integral type 'float'}} \ + // expected-error{{data member instantiated with function type}} + + mutable T x2; // expected-error{{data member instantiated with function type}} +}; + +void test1(const X<int> *xi) { + int i1 = xi->x; + const int &i2 = xi->y; + int* ip1 = xi->z; + int i3 = xi->bitfield; + xi->x2 = 17; +} + +void test2(const X<float> *xf) { + (void)xf->x; // expected-note{{in instantiation of template class 'X<float>' requested here}} +} + +void test3(const X<int(int)> *xf) { + (void)xf->x; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}} +} + +namespace PR7123 { + template <class > struct requirement_; + + template <void(*)()> struct instantiate + { }; + + template <class > struct requirement ; + struct failed ; + + template <class Model> struct requirement<failed *Model::*> + { + static void failed() + { + ((Model*)0)->~Model(); // expected-note{{in instantiation of}} + } + }; + + template <class Model> struct requirement_<void(*)(Model)> : requirement<failed *Model::*> + { }; + + template <int> struct Requires_ + { typedef void type; }; + + template <class Model> struct usage_requirements + { + ~usage_requirements() + {((Model*)0)->~Model(); } // expected-note{{in instantiation of}} + }; + + template < typename TT > struct BidirectionalIterator + { + enum + { value = 0 }; + + instantiate< requirement_<void(*)(usage_requirements<BidirectionalIterator>)>::failed> int534; // expected-note{{in instantiation of}} + + ~BidirectionalIterator() + { i--; } // expected-error{{cannot decrement value of type 'PR7123::X'}} + + TT i; + }; + + struct X + { }; + + template<typename RanIter> + typename Requires_< BidirectionalIterator<RanIter>::value >::type sort(RanIter,RanIter){} + + void f() + { + X x; + sort(x,x); + } +} + +namespace PR7355 { + template<typename T1> class A { + class D; // expected-note{{declared here}} + D d; //expected-error{{implicit instantiation of undefined member 'PR7355::A<int>::D'}} + }; + + A<int> ai; // expected-note{{in instantiation of}} +} + +namespace PR8712 { + template <int dim> + class B { + public: + B(const unsigned char i); + unsigned char value : (dim > 0 ? dim : 1); + }; + + template <int dim> + inline B<dim>::B(const unsigned char i) : value(i) {} +} diff --git a/clang/test/SemaTemplate/instantiate-friend-class.cpp b/clang/test/SemaTemplate/instantiate-friend-class.cpp new file mode 100644 index 0000000..c87b8d0 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-friend-class.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR4794 + +template <class T> class X +{ + friend class Y; +}; +X<int> y; + diff --git a/clang/test/SemaTemplate/instantiate-function-1.cpp b/clang/test/SemaTemplate/instantiate-function-1.cpp new file mode 100644 index 0000000..ceef274 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-function-1.cpp @@ -0,0 +1,249 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s +template<typename T, typename U> +struct X0 { + void f(T x, U y) { + (void)(x + y); // expected-error{{invalid operands}} + } +}; + +struct X1 { }; + +template struct X0<int, float>; +template struct X0<int*, int>; +template struct X0<int X1::*, int>; // expected-note{{instantiation of}} + +template<typename T> +struct X2 { + void f(T); + + T g(T x, T y) { + /* DeclStmt */; + T *xp = &x, &yr = y; // expected-error{{pointer to a reference}} + /* NullStmt */; + } +}; + +template struct X2<int>; +template struct X2<int&>; // expected-note{{instantiation of}} + +template<typename T> +struct X3 { + void f(T) { + Label: + T x; + goto Label; + } +}; + +template struct X3<int>; + +template <typename T> struct X4 { + T f() const { + return; // expected-error{{non-void function 'f' should return a value}} + } + + T g() const { + return 1; // expected-error{{void function 'g' should not return a value}} + } +}; + +template struct X4<void>; // expected-note{{in instantiation of}} +template struct X4<int>; // expected-note{{in instantiation of}} + +struct Incomplete; // expected-note 2{{forward declaration}} + +template<typename T> struct X5 { + T f() { } // expected-error{{incomplete result type}} +}; +void test_X5(X5<Incomplete> x5); // okay! + +template struct X5<Incomplete>; // expected-note{{instantiation}} + +template<typename T, typename U, typename V> struct X6 { + U f(T t, U u, V v) { + // IfStmt + if (t > 0) + return u; + else { + if (t < 0) + return v; // expected-error{{cannot initialize return object of type}} + } + + if (T x = t) { + t = x; + } + return v; // expected-error{{cannot initialize return object of type}} + } +}; + +struct ConvertibleToInt { + operator int() const; +}; + +template struct X6<ConvertibleToInt, float, char>; +template struct X6<bool, int, int*>; // expected-note{{instantiation}} + +template <typename T> struct X7 { + void f() { + void *v = this; + } +}; + +template struct X7<int>; + +template<typename T> struct While0 { + void f(T t) { + while (t) { + } + + while (T t2 = T()) ; + } +}; + +template struct While0<float>; + +template<typename T> struct Do0 { + void f(T t) { + do { + } while (t); // expected-error{{not contextually}} + } +}; + +struct NotConvertibleToBool { }; +template struct Do0<ConvertibleToInt>; +template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}} + +template<typename T> struct For0 { + void f(T f, T l) { + for (; f != l; ++f) { + if (*f) + continue; + else if (*f == 17) + break; + } + } +}; + +template struct For0<int*>; + +template<typename T> struct Member0 { + void f(T t) { + t; + t.f; + t->f; + + T* tp; + tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}} + tp->f; + + this->f; + this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}} + } +}; + +template<typename T, typename U> struct Switch0 { + U f(T value, U v0, U v1, U v2) { + switch (value) { + case 0: return v0; + + case 1: return v1; + + case 2: // fall through + + default: + return v2; + } + } +}; + +template struct Switch0<int, float>; + +template<typename T, int I1, int I2> struct Switch1 { + T f(T x, T y, T z) { + switch (x) { + case I1: return y; // expected-note{{previous}} + case I2: return z; // expected-error{{duplicate}} + default: return x; + } + } +}; + +template struct Switch1<int, 1, 2>; +template struct Switch1<int, 2, 2>; // expected-note{{instantiation}} + +template<typename T> struct IndirectGoto0 { + void f(T x) { + // FIXME: crummy error message below + goto *x; // expected-error{{incompatible}} + + prior: + T prior_label; + prior_label = &&prior; // expected-error{{assigning to 'int'}} + + T later_label; + later_label = &&later; // expected-error{{assigning to 'int'}} + + later: + (void)(1+1); + } +}; + +template struct IndirectGoto0<void*>; +template struct IndirectGoto0<int>; // expected-note{{instantiation}} + +template<typename T> struct TryCatch0 { + void f() { + try { + } catch (T t) { // expected-error{{incomplete type}} \ + // expected-error{{abstract class}} + } catch (...) { + } + } +}; + +struct Abstract { + virtual void foo() = 0; // expected-note{{pure virtual}} +}; + +template struct TryCatch0<int>; // okay +template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}} +template struct TryCatch0<Abstract>; // expected-note{{instantiation}} + +// PR4383 +template<typename T> struct X; +template<typename T> struct Y : public X<T> { + Y& x() { return *this; } +}; + +// Make sure our assertions don't get too uppity. +namespace test0 { + template <class T> class A { void foo(T array[10]); }; + template class A<int>; +} + +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/clang/test/SemaTemplate/instantiate-function-1.mm b/clang/test/SemaTemplate/instantiate-function-1.mm new file mode 100644 index 0000000..c67b598 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-function-1.mm @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * + +template<typename T> struct Member0 { + void f(T t) { + t; + t.f; + t->f; + + T* tp; + tp.f; + tp->f; + + this->f; + this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}} + } +}; diff --git a/clang/test/SemaTemplate/instantiate-function-2.cpp b/clang/test/SemaTemplate/instantiate-function-2.cpp new file mode 100644 index 0000000..19a8b61 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-function-2.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template <typename T> struct S { + S() { } + S(T t); +}; + +template struct S<int>; + +void f() { + S<int> s1; + S<int> s2(10); +} + +namespace PR7184 { + template<typename T> + void f() { + typedef T type; + void g(int array[sizeof(type)]); + } + + template void f<int>(); +} + +namespace UsedAttr { + template<typename T> + void __attribute__((used)) foo() { + T *x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + } + + void bar() { + foo<int>(); // expected-note{{instantiation of}} + } +} + +namespace PR9654 { + typedef void ftype(int); + + template<typename T> + ftype f; + + void g() { + f<int>(0); + } +} + +namespace AliasTagDef { + template<typename T> + T f() { + using S = struct { // expected-warning {{C++11}} + T g() { + return T(); + } + }; + return S().g(); + } + + int n = f<int>(); +} + +namespace PR10273 { + template<typename T> void (f)(T t) {} + + void g() { + (f)(17); + } +} diff --git a/clang/test/SemaTemplate/instantiate-function-params.cpp b/clang/test/SemaTemplate/instantiate-function-params.cpp new file mode 100644 index 0000000..54847e4 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-function-params.cpp @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR6619 +template<bool C> struct if_c { }; +template<typename T1> struct if_ { + typedef if_c< static_cast<bool>(T1::value)> almost_type_; // expected-note 5{{in instantiation}} +}; +template <class Model, void (Model::*)()> struct wrap_constraints { }; +template <class Model> +inline char has_constraints_(Model* , // expected-note 2{{while substituting deduced template arguments into function template 'has_constraints_' [with }} \ + // expected-note 3{{candidate template ignored}} + wrap_constraints<Model,&Model::constraints>* = 0); // expected-note 2{{in instantiation}} + +template <class Model> struct not_satisfied { + static const bool value = sizeof( has_constraints_((Model*)0) == 1); // expected-error 3{{no matching function}} +}; +template <class ModelFn> struct requirement_; +template <void(*)()> struct instantiate { +}; +template <class Model> struct requirement_<void(*)(Model)> : if_< not_satisfied<Model> >::type { // expected-note 5{{in instantiation}} +}; +template <class Model> struct usage_requirements { +}; +template < typename TT > struct InputIterator { + typedef instantiate< & requirement_<void(*)(usage_requirements<InputIterator> x)>::failed> boost_concept_check1; // expected-note {{in instantiation}} +}; +template < typename TT > struct ForwardIterator : InputIterator<TT> { // expected-note {{in instantiation}} + typedef instantiate< & requirement_<void(*)(usage_requirements<ForwardIterator> x)>::failed> boost_concept_check2; // expected-note {{in instantiation}} + +}; +typedef instantiate< &requirement_<void(*)(ForwardIterator<char*> x)>::failed> boost_concept_checkX;// expected-note 3{{in instantiation}} + +template<typename T> struct X0 { }; +template<typename R, typename A1> struct X0<R(A1 param)> { }; + +template<typename T, typename A1, typename A2> +void instF0(X0<T(A1)> x0a, X0<T(A2)> x0b) { + X0<T(A1)> x0c; + X0<T(A2)> x0d; +} + +template void instF0<int, int, float>(X0<int(int)>, X0<int(float)>); + +template<typename R, typename A1, R (*ptr)(A1)> struct FuncPtr { }; +template<typename A1, int (*ptr)(A1)> struct FuncPtr<int, A1, ptr> { }; + +template<typename R, typename A1> R unary_func(A1); + +template<typename R, typename A1, typename A2> +void use_func_ptr() { + FuncPtr<R, A1, &unary_func<R, A1> > fp1; + FuncPtr<R, A2, &unary_func<R, A2> > fp2; +}; + +template void use_func_ptr<int, float, double>(); + +namespace PR6990 { + template < typename , typename = int, typename = int > struct X1; + template <typename > + struct X2; + + template <typename = int *, typename TokenT = int, + typename = int( X2<TokenT> &)> + struct X3 + { + }; + + template <typename , typename P> + struct X3_base : X3< X1<int, P> > + { + protected: typedef X1< P> type; + X3<type> e; + }; + + struct r : X3_base<int, int> + { + }; +} + +namespace InstantiateFunctionTypedef { + template<typename T> + struct X { + typedef int functype(int, int); + functype func; + }; + + void f(X<int> x) { + (void)x.func(1, 2); + } +} diff --git a/clang/test/SemaTemplate/instantiate-init.cpp b/clang/test/SemaTemplate/instantiate-init.cpp new file mode 100644 index 0000000..f0ca9a5 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-init.cpp @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -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}} +} + +namespace PR6457 { + template <typename T> struct X { explicit X(T* p = 0) { }; }; + template <typename T> struct Y { Y(int, const T& x); }; + struct A { }; + template <typename T> + struct B { + B() : y(0, X<A>()) { } + Y<X<A> > y; + }; + B<int> b; +} + +namespace PR6657 { + struct X + { + X (int, int) { } + }; + + template <typename> + void f0() + { + X x = X(0, 0); + } + + void f1() + { + 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/clang/test/SemaTemplate/instantiate-invalid.cpp b/clang/test/SemaTemplate/instantiate-invalid.cpp new file mode 100644 index 0000000..b8a5901 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-invalid.cpp @@ -0,0 +1,52 @@ +// RUN: not %clang_cc1 -fsyntax-only %s +namespace PR6375 { + template<class Conv> class rasterizer_sl_clip Conv::xi(x2), Conv::yi(y2)); +namespace agg +{ + template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa + { + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + while(num_cells) { } + } + } + class scanline_u8 {} + template<class PixelFormat> class renderer_base { } +} + template<class Rasterizer, class Scanline, class BaseRenderer, class ColorT> + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, const ColorT& color) + { + while(ras.sweep_scanline(sl)) + { + } + }; +namespace agg +{ + struct rgba8 + { + }; + template<class Rasterizer, class Scanline, class Renderer, class Ctrl> + void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + render_scanlines_aa_solid(ras, sl, r, c.color(i)); + } + template<class ColorT> class rbox_ctrl : public rbox_ctrl_impl + { + const ColorT& color(unsigned i) const { return *m_colors[i]; } + } +class the_application : public agg::platform_support +{ + agg::rbox_ctrl<agg::rgba8> m_polygons; + virtual void on_init() + { + typedef agg::renderer_base<pixfmt_type> base_ren_type; + base_ren_type ren_base(pf); + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + agg::render_ctrl(ras, sl, ren_base, m_polygons); + } +}; +} +} diff --git a/clang/test/SemaTemplate/instantiate-local-class.cpp b/clang/test/SemaTemplate/instantiate-local-class.cpp new file mode 100644 index 0000000..20b62c1 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-local-class.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -verify %s +template<typename T> +void f0() { + struct X; + typedef struct Y { + T (X::* f1())(int) { return 0; } + } Y2; + + Y2 y = Y(); +} + +template void f0<int>(); + +// PR5764 +namespace PR5764 { + struct X { + template <typename T> + void Bar() { + typedef T ValueType; + struct Y { + Y() { V = ValueType(); } + + ValueType V; + }; + + Y y; + } + }; + + void test(X x) { + x.Bar<int>(); + } +} + +// Instantiation of local classes with virtual functions. +namespace local_class_with_virtual_functions { + template <typename T> struct X { }; + template <typename T> struct Y { }; + + template <typename T> + void f() { + struct Z : public X<Y<T>*> { + virtual void g(Y<T>* y) { } + void g2(int x) {(void)x;} + }; + Z z; + (void)z; + } + + struct S { }; + void test() { f<S>(); } +} + +namespace PR8801 { + template<typename T> + void foo() { + class X; + typedef int (X::*pmf_type)(); + class X : public T { }; + + pmf_type pmf = &T::foo; + } + + struct Y { int foo(); }; + + template void foo<Y>(); +} diff --git a/clang/test/SemaTemplate/instantiate-member-class.cpp b/clang/test/SemaTemplate/instantiate-member-class.cpp new file mode 100644 index 0000000..bb64276 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-member-class.cpp @@ -0,0 +1,142 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8965 { + template<typename T> + struct X { + typedef int type; + + T field; // expected-note{{in instantiation of member class}} + }; + + template<typename T> + struct Y { + struct Inner; + + typedef typename X<Inner>::type // expected-note{{in instantiation of template class}} + type; // expected-note{{not-yet-instantiated member is declared here}} + + struct Inner { + typedef type field; // expected-error{{no member 'type' in 'PR8965::Y<int>'; it has not yet been instantiated}} + }; + }; + + Y<int> y; // expected-note{{in instantiation of template class}} +} + +template<typename T> +class X { +public: + struct C { T &foo(); }; + + struct D { + struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}} + struct F; // expected-note{{member is declared here}} + }; +}; + +X<int>::C *c1; +X<float>::C *c2; + +X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}} +X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}} + +void test_naming() { + c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}} + xi = xf; // expected-error{{assigning to 'X<int>::X<int> *' from incompatible type 'X<float>::X<float> *'}} + // FIXME: error above doesn't print the type X<int>::X cleanly! +} + +void test_instantiation(X<double>::C *x, + X<float>::D::E *e, + X<float>::D::F *f) { + double &dr = x->foo(); + float &fr = e->bar(); + f->foo(); // expected-error{{implicit instantiation of undefined member 'X<float>::D::F'}} + +} + + +X<void>::C *c3; // okay +X<void>::D::E *e1; // okay +X<void>::D::E e2; // expected-note{{in instantiation of member class 'X<void>::D::E' requested here}} + +// Redeclarations. +namespace test1 { + template <typename T> struct Registry { + struct node; + static node *Head; + struct node { + node(int v) { Head = this; } + }; + }; + void test() { + Registry<int>::node node(0); + } +} + +// Redeclarations during explicit instantiations. +namespace test2 { + template <typename T> class A { + class Foo; + class Foo { + int foo(); + }; + }; + template class A<int>; + + template <typename T> class B { + class Foo; + class Foo { + public: + typedef int X; + }; + typename Foo::X x; + class Foo; + }; + template class B<int>; + + template <typename T> class C { + class Foo; + class Foo; + }; + template <typename T> class C<T>::Foo { + int x; + }; + template class C<int>; +} + +namespace AliasTagDef { + template<typename T> + struct F { + using S = struct U { // expected-warning {{C++11}} + T g() { + return T(); + } + }; + }; + + int m = F<int>::S().g(); + int n = F<int>::U().g(); +} + +namespace rdar10397846 { + template<int I> struct A + { + struct B + { + struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + }; + }; + + template<int N> void foo() + { + class A<N>::B::C X; // expected-note{{in instantiation of member function}} + int A<N+1>::B::C::*member = 0; + } + + void bar() + { + foo<0>(); + foo<1>(); // expected-note{{in instantiation of function template}} + } +} diff --git a/clang/test/SemaTemplate/instantiate-member-expr.cpp b/clang/test/SemaTemplate/instantiate-member-expr.cpp new file mode 100644 index 0000000..a31569a --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-member-expr.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +struct S { + S() { } +}; + +template<typename T> +struct vector { + void push_back(const T&) { int a[sizeof(T) ? -1: -1]; } // expected-error {{array with a negative size}} +}; + +class ExprEngine { +public: + typedef vector<S<void *> >CheckersOrdered; + CheckersOrdered Checkers; + + template <typename CHECKER> + void registerCheck(CHECKER *check) { + Checkers.push_back(S<void *>()); // expected-note {{in instantiation of member function 'vector<S<void *> >::push_back' requested here}} + } +}; + +class RetainReleaseChecker { }; + +void f(ExprEngine& Eng) { + Eng.registerCheck(new RetainReleaseChecker); // expected-note {{in instantiation of function template specialization 'ExprEngine::registerCheck<RetainReleaseChecker>' requested here}} +} + +// PR 5838 +namespace test1 { + template<typename T> struct A { + int a; + }; + + template<typename T> struct B : A<float>, A<T> { + void f() { + a = 0; // should not be ambiguous + } + }; + template struct B<int>; + + struct O { + int a; + template<typename T> struct B : A<T> { + void f() { + a = 0; // expected-error {{'test1::O::a' is not a member of class 'test1::O::B<int>'}} + } + }; + }; + template struct O::B<int>; // expected-note {{in instantiation}} +} + +// PR7248 +namespace test2 { + template <class T> struct A { + void foo() { + T::bar(); // expected-error {{type 'int' cannot}} + } + }; + + template <class T> class B { + void foo(A<T> a) { + a.test2::template A<T>::foo(); // expected-note {{in instantiation}} + } + }; + + template class B<int>; +} diff --git a/clang/test/SemaTemplate/instantiate-member-initializers.cpp b/clang/test/SemaTemplate/instantiate-member-initializers.cpp new file mode 100644 index 0000000..45503b3 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-member-initializers.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -Wall -verify %s + +template<typename T> struct A { + A() : a(1) { } // expected-error{{cannot initialize a member subobject of type 'void *' with an rvalue of type 'int'}} + + 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 { + B() : b(1), // expected-warning {{field 'b' will be initialized after field 'a'}} + a(2) { } + + int a; + int b; +}; + +B<int> b0; // expected-note {{in instantiation of member function 'B<int>::B' requested here}} + +template <class T> struct AA { AA(int); }; +template <class T> class BB : public AA<T> { +public: + BB() : AA<T>(1) {} +}; +BB<int> x; diff --git a/clang/test/SemaTemplate/instantiate-member-pointers.cpp b/clang/test/SemaTemplate/instantiate-member-pointers.cpp new file mode 100644 index 0000000..0db90e3 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-member-pointers.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct Y { + int x; +}; + +template<typename T> +struct X1 { + int f(T* ptr, int T::*pm) { // expected-error{{member pointer}} + return ptr->*pm; + } +}; + +template struct X1<Y>; +template struct X1<int>; // expected-note{{instantiation}} + +template<typename T, typename Class> +struct X2 { + T f(Class &obj, T Class::*pm) { // expected-error{{to a reference}} \ + // expected-error{{member pointer to void}} + return obj.*pm; + } +}; + +template struct X2<int, Y>; +template struct X2<int&, Y>; // expected-note{{instantiation}} +template struct X2<const void, Y>; // expected-note{{instantiation}} + +template<typename T, typename Class, T Class::*Ptr> +struct X3 { + X3<T, Class, Ptr> &operator=(const T& value) { + return *this; + } +}; + +X3<int, Y, &Y::x> x3; + +typedef int Y::*IntMember; + +template<IntMember Member> +struct X4 { + X3<int, Y, Member> member; + + int &getMember(Y& y) { return y.*Member; } +}; + +int &get_X4(X4<&Y::x> x4, Y& y) { + return x4.getMember(y); +} + +template<IntMember Member> +void accept_X4(X4<Member>); + +void test_accept_X4(X4<&Y::x> x4) { + accept_X4(x4); +} + +namespace ValueDepMemberPointer { + template <void (*)()> struct instantiate_function {}; + template <typename T> struct S { + static void instantiate(); + typedef instantiate_function<&S::instantiate> x; // expected-note{{instantiation}} + }; + template <typename T> void S<T>::instantiate() { + int a[(int)sizeof(T)-42]; // expected-error{{array with a negative size}} + } + S<int> s; +} diff --git a/clang/test/SemaTemplate/instantiate-member-template.cpp b/clang/test/SemaTemplate/instantiate-member-template.cpp new file mode 100644 index 0000000..4c74f5f --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-member-template.cpp @@ -0,0 +1,261 @@ +// RUN: %clang_cc1 -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) { // expected-note{{passing argument to parameter 't' here}} + (void)(t + u); // expected-error{{invalid operands}} + } + + template<typename V> + V f1(T t, U u, V) { + return t + u; // expected-error{{cannot initialize return object}} + } + }; + + 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{{cannot initialize return object}} +} + +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{{cannot initialize a parameter of type 'int *' with an lvalue of type 'double *'}} + 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}} +} + + +template<typename T> +struct X2 { + template<T *Ptr> // expected-error{{pointer to a reference}} + struct Inner; + + template<T Value> // expected-error{{cannot have type 'float'}} + struct Inner2; +}; + +X2<int&> x2a; // expected-note{{instantiation}} +X2<float> x2b; // expected-note{{instantiation}} + +namespace N0 { + template<typename T> + struct X0 { }; + + struct X1 { + template<typename T> void f(X0<T>& vals) { g(vals); } + template<typename T> void g(X0<T>& vals) { } + }; + + void test(X1 x1, X0<int> x0i, X0<long> x0l) { + x1.f(x0i); + x1.f(x0l); + } +} + +namespace PR6239 { + template <typename T> + struct X0 { + class type { + typedef T E; + template <E e> // subsitute T for E and bug goes away + struct sfinae { }; + + template <class U> + typename sfinae<&U::operator=>::type test(int); + }; + }; + + template <typename T> + struct X1 { + typedef T E; + template <E e> // subsitute T for E and bug goes away + struct sfinae { }; + + template <class U> + typename sfinae<&U::operator=>::type test(int); + }; + +} + +namespace PR7587 { + template<typename> class X0; + template<typename> struct X1; + template<typename> class X2; + + template<typename T> class X3 + { + template< + template<typename> class TT, + typename U = typename X1<T>::type + > + struct Inner { + typedef X2<TT<typename X1<T>::type> > Type; + }; + + const typename Inner<X0>::Type minCoeff() const; + }; + + template<typename T> class X3<T*> + { + template< + template<typename> class TT, + typename U = typename X1<T>::type + > + struct Inner { + typedef X2<TT<typename X1<T>::type> > Type; + }; + + const typename Inner<X0>::Type minCoeff() const; + }; + +} + +namespace PR7669 { + template<class> struct X { + template<class> struct Y { + template<int,class> struct Z; + template<int Dummy> struct Z<Dummy,int> {}; + }; + }; + + void a() + { + X<int>::Y<int>::Z<0,int>(); + } +} + +namespace PR8489 { + template <typename CT> + class C { + template<typename FT> + void F() {} // expected-note{{FT}} + }; + void f() { + C<int> c; + c.F(); // expected-error{{no matching member function}} + } +} + +namespace rdar8986308 { + template <bool> struct __static_assert_test; + template <> struct __static_assert_test<true> {}; + template <unsigned> struct __static_assert_check {}; + + namespace std { + + template <class _Tp, class _Up> + struct __has_rebind + { + private: + struct __two {char _; char __;}; + template <class _Xp> static __two __test(...); + template <class _Xp> static char __test(typename _Xp::template rebind<_Up>* = 0); + public: + static const bool value = sizeof(__test<_Tp>(0)) == 1; + }; + + } + + template <class T> struct B1 {}; + + template <class T> + struct B + { + template <class U> struct rebind {typedef B1<U> other;}; + }; + + template <class T, class U> struct D1 {}; + + template <class T, class U> + struct D + { + template <class V> struct rebind {typedef D1<V, U> other;}; + }; + + int main() + { + typedef __static_assert_check<sizeof(__static_assert_test<((std::__has_rebind<B<int>, double>::value))>)> __t64; + typedef __static_assert_check<sizeof(__static_assert_test<((std::__has_rebind<D<char, int>, double>::value))>)> __t64; + } + +} diff --git a/clang/test/SemaTemplate/instantiate-method.cpp b/clang/test/SemaTemplate/instantiate-method.cpp new file mode 100644 index 0000000..363115d --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-method.cpp @@ -0,0 +1,177 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +class X { +public: + void f(T x); // expected-error{{argument may not have 'void' type}} + void g(T*); + + static int h(T, T); // expected-error {{argument may not have 'void' type}} +}; + +int identity(int x) { return x; } + +void test(X<int> *xi, int *ip, X<int(int)> *xf) { + xi->f(17); + xi->g(ip); + xf->f(&identity); + xf->g(identity); + X<int>::h(17, 25); + X<int(int)>::h(identity, &identity); +} + +void test_bad() { + X<void> xv; // expected-note{{in instantiation of template class 'X<void>' requested here}} +} + +template<typename T, typename U> +class Overloading { +public: + int& f(T, T); // expected-note{{previous declaration is here}} + float& f(T, U); // expected-error{{functions that differ only in their return type cannot be overloaded}} +}; + +void test_ovl(Overloading<int, long> *oil, int i, long l) { + int &ir = oil->f(i, i); + float &fr = oil->f(i, l); +} + +void test_ovl_bad() { + Overloading<float, float> off; // expected-note{{in instantiation of template class 'Overloading<float, float>' requested here}} +} + +template<typename T> +class HasDestructor { +public: + virtual ~HasDestructor() = 0; +}; + +int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but + // the code below should probably instantiate by itself. +int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1]; + + +template<typename T> +class Constructors { +public: + Constructors(const T&); + Constructors(const Constructors &other); +}; + +void test_constructors() { + Constructors<int> ci1(17); + Constructors<int> ci2 = ci1; +} + + +template<typename T> +struct ConvertsTo { + operator T(); +}; + +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{{no viable conversion}} +} + +struct X0Base { + int &f(); + int& g(int); + static double &g(double); +}; + +template<typename T> +struct X0 : X0Base { +}; + +template<typename U> +struct X1 : X0<U> { + int &f2() { + return X0Base::f(); + } +}; + +void test_X1(X1<int> x1i) { + int &ir = x1i.f2(); +} + +template<typename U> +struct X2 : X0Base, U { + int &f2() { return X0Base::f(); } +}; + +template<typename T> +struct X3 { + void test(T x) { + double& d1 = X0Base::g(x); + } +}; + + +template struct X3<double>; + +// Don't try to instantiate this, it's invalid. +namespace test1 { + template <class T> class A {}; + template <class T> class B { + void foo(A<test1::Undeclared> &a) // expected-error {{no member named 'Undeclared' in namespace 'test1'}} + {} + }; + template class B<int>; +} + +namespace PR6947 { + template< class T > + struct X { + int f0( ) + { + typedef void ( X::*impl_fun_ptr )( ); + impl_fun_ptr pImpl = &X::template + f0_impl1<int>; + } + private: + int f1() { + } + template< class Processor> + void f0_impl1( ) + { + } + }; + + char g0() { + X<int> pc; + pc.f0(); + } + +} + +namespace PR7022 { + template <typename > + struct X1 + { + typedef int state_t( ); + state_t g ; + }; + + template < typename U = X1<int> > struct X2 + { + X2( U = U()) + { + } + }; + + void m(void) + { + typedef X2<> X2_type; + X2_type c; + } + +} diff --git a/clang/test/SemaTemplate/instantiate-non-dependent-types.cpp b/clang/test/SemaTemplate/instantiate-non-dependent-types.cpp new file mode 100644 index 0000000..a0005c5 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-non-dependent-types.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +struct X1 { + static void member() { T* x = 1; } // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} +}; + +template<void(*)()> struct instantiate { }; + +template<typename T> +struct X2 { + typedef instantiate<&X1<int>::member> i; // expected-note{{in instantiation of}} +}; + +X2<int> x; diff --git a/clang/test/SemaTemplate/instantiate-non-type-template-parameter.cpp b/clang/test/SemaTemplate/instantiate-non-type-template-parameter.cpp new file mode 100644 index 0000000..027c1e8 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-non-type-template-parameter.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5311 +template<typename T> +class StringSwitch { +public: + template<unsigned N> + void Case(const char (&S)[N], const int & Value) { + } +}; + +void test_stringswitch(int argc, char *argv[]) { + (void)StringSwitch<int>(); +} + +namespace PR6986 { + template<class Class,typename Type,Type Class::*> + struct non_const_member_base + { + }; + + template<class Class,typename Type,Type Class::*PtrToMember> + struct member: non_const_member_base<Class,Type,PtrToMember> + { + }; + + struct test_class + { + int int_member; + }; + typedef member< test_class,const int,&test_class::int_member > ckey_m; + void test() + { + ckey_m m; + } +} + +namespace rdar8980215 { + enum E { E1, E2, E3 }; + + template<typename T, E e = E2> + struct X0 { + X0() {} + template<typename U> X0(const X0<U, e> &); + }; + + template<typename T> + struct X1 : X0<T> { + X1() {} + template<typename U> X1(const X1<U> &x) : X0<T>(x) { } + }; + + X1<int> x1i; + X1<float> x1f(x1i); +} diff --git a/clang/test/SemaTemplate/instantiate-objc-1.mm b/clang/test/SemaTemplate/instantiate-objc-1.mm new file mode 100644 index 0000000..2780f8e --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-objc-1.mm @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Obj-C string literal expressions +template <typename T> struct StringTest { + void f() { + (void)@"Hello"; + } +}; + +template struct StringTest<int>; +template struct StringTest<double>; + +// @selector expressions +template <typename T> struct SelectorTest { + SEL f() { + return @selector(multiple:arguments:); + } + SEL f2() { + return @selector(multiple:arguments:); + } +}; + +template struct SelectorTest<int>; +template struct SelectorTest<double>; + +// @protocol expressions +@protocol P +@end + +template <typename T> struct ProtocolTest { + void f() { + (void)@protocol(P); + } +}; + +template struct ProtocolTest<int>; +template struct ProtocolTest<double>; + +// @encode expressions +template <typename T> struct EncodeTest { + static const char *encode(T t) { + return @encode(T); + } +}; + +template struct EncodeTest<int>; +template struct EncodeTest<double>; +template struct EncodeTest<wchar_t>; diff --git a/clang/test/SemaTemplate/instantiate-overload-candidates.cpp b/clang/test/SemaTemplate/instantiate-overload-candidates.cpp new file mode 100644 index 0000000..5b7e60d --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-overload-candidates.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This is the function actually selected during overload resolution, and the +// only one defined. +template <typename T> void f(T*, int) {} + +template <typename T> struct S; +template <typename T> struct S_ : S<T> { typedef int type; }; // expected-note{{in instantiation}} +template <typename T> struct S { + // Force T to have a complete type here so we can observe instantiations with + // incomplete types. + T t; // expected-error{{field has incomplete type}} +}; + +// Provide a bad class and an overload that instantiates templates with it. +class NoDefinition; // expected-note{{forward declaration}} +template <typename T> S_<NoDefinition>::type f(T*, NoDefinition*); // expected-note{{in instantiation}} + +void test(int x) { + f(&x, 0); +} diff --git a/clang/test/SemaTemplate/instantiate-overloaded-arrow.cpp b/clang/test/SemaTemplate/instantiate-overloaded-arrow.cpp new file mode 100644 index 0000000..ee36427 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-overloaded-arrow.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR5488 + +struct X { + int x; +}; + +struct Iter { + X* operator->(); +}; + +template <typename T> +void Foo() { + (void)Iter()->x; +} + +void Func() { + Foo<int>(); +} + diff --git a/clang/test/SemaTemplate/instantiate-self.cpp b/clang/test/SemaTemplate/instantiate-self.cpp new file mode 100644 index 0000000..cfe9025 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-self.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// Check that we deal with cases where the instantiation of a class template +// recursively requires the instantiation of the same template. +namespace test1 { + template<typename T> struct A { + struct B { // expected-note {{not complete until the closing '}'}} + B b; // expected-error {{has incomplete type 'test1::A<int>::B'}} + }; + B b; // expected-note {{in instantiation of}} + }; + A<int> a; // expected-note {{in instantiation of}} +} + +namespace test2 { + template<typename T> struct A { + struct B { + struct C {}; + char c[1 + C()]; // expected-error {{invalid operands to binary expression}} + friend constexpr int operator+(int, C) { return 4; } + }; + B b; // expected-note {{in instantiation of}} + }; + A<int> a; // expected-note {{in instantiation of}} +} + +namespace test3 { + // PR12317 + template<typename T> struct A { + struct B { + enum { Val = 1 }; + char c[1 + Val]; // ok + }; + B b; + }; + A<int> a; +} + +namespace test4 { + template<typename T> struct M { typedef int type; }; + template<typename T> struct A { + struct B { // expected-note {{not complete until the closing '}'}} + int k[typename A<typename M<T>::type>::B().k[0] + 1]; // expected-error {{incomplete type}} + }; + B b; // expected-note {{in instantiation of}} + }; + A<int> a; // expected-note {{in instantiation of}} +} + +// FIXME: PR12298: Recursive constexpr function template instantiation leads to +// stack overflow. +#if 0 +namespace test5 { + template<typename T> struct A { + constexpr T f(T k) { return g(k); } + constexpr T g(T k) { + return k ? f(k-1)+1 : 0; + } + }; + // This should be accepted. + constexpr int x = A<int>().f(5); +} + +namespace test6 { + template<typename T> constexpr T f(T); + template<typename T> constexpr T g(T t) { + typedef int arr[f(T())]; + return t; + } + template<typename T> constexpr T f(T t) { + typedef int arr[g(T())]; + return t; + } + // This should be ill-formed. + int n = f(0); +} + +namespace test7 { + template<typename T> constexpr T g(T t) { + return t; + } + template<typename T> constexpr T f(T t) { + typedef int arr[g(T())]; + return t; + } + // This should be accepted. + int n = f(0); +} +#endif diff --git a/clang/test/SemaTemplate/instantiate-sizeof.cpp b/clang/test/SemaTemplate/instantiate-sizeof.cpp new file mode 100644 index 0000000..00d63d0 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-sizeof.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Make sure we handle contexts correctly with sizeof +template<typename T> void f(T n) { + int buffer[n]; + [] { int x = sizeof(sizeof(buffer)); }(); +} +int main() { + f<int>(1); +} diff --git a/clang/test/SemaTemplate/instantiate-static-var.cpp b/clang/test/SemaTemplate/instantiate-static-var.cpp new file mode 100644 index 0000000..f309f29 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-static-var.cpp @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, T Divisor> +class X { +public: + static const T value = 10 / Divisor; // expected-error{{in-class initializer for static data member is not a constant expression}} +}; + +int array1[X<int, 2>::value == 5? 1 : -1]; +X<int, 0> xi0; // expected-note{{in instantiation of template class 'X<int, 0>' requested here}} + + +template<typename T> +class Y { + static const T value = 0; // expected-warning{{in-class initializer for static data member of type 'const float' is a GNU extension}} +}; + +Y<float> fy; // expected-note{{in instantiation of template 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&); // expected-note{{candidate constructor}} +}; + +void test() { + DefCon &DC = Z<DefCon>::value; + NoDefCon &NDC = Z<NoDefCon>::value; // expected-note{{instantiation}} +} + +// PR5609 +struct X1 { + ~X1(); // The errors won't be triggered without this dtor. +}; + +template <typename T> +struct Y1 { + static char Helper(T); + static const int value = sizeof(Helper(T())); +}; + +struct X2 { + virtual ~X2(); +}; + +namespace std { + class type_info { }; +} + +template <typename T> +struct Y2 { + static T &Helper(); + static const int value = sizeof(typeid(Helper())); +}; + +template <int> +struct Z1 {}; + +void Test() { + Z1<Y1<X1>::value> x; + int y[Y1<X1>::value]; + Z1<Y2<X2>::value> x2; + int y2[Y2<X2>::value]; +} + +// PR5672 +template <int n> +struct X3 {}; + +class Y3 { + public: + ~Y3(); // The error isn't triggered without this dtor. + + void Foo(X3<1>); +}; + +template <typename T> +struct SizeOf { + static const int value = sizeof(T); +}; + +void MyTest3() { + Y3().Foo(X3<SizeOf<char>::value>()); +} + +namespace PR6449 { + template<typename T> + struct X0 { + static const bool var = false; + }; + + template<typename T> + const bool X0<T>::var; + + template<typename T> + struct X1 : public X0<T> { + static const bool var = false; + }; + + template<typename T> + const bool X1<T>::var; + + template class X0<char>; + template class X1<char>; + +} diff --git a/clang/test/SemaTemplate/instantiate-subscript.cpp b/clang/test/SemaTemplate/instantiate-subscript.cpp new file mode 100644 index 0000000..8c119ec --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-subscript.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + + +struct Sub0 { + int &operator[](int); +}; + +struct Sub1 { + long &operator[](long); // expected-note{{candidate function}} +}; + +struct ConvertibleToInt { + operator int(); +}; + +template<typename T, typename U, typename Result> +struct Subscript0 { + void test(T t, U u) { + Result &result = t[u]; // expected-error{{no viable overloaded operator[] for type}} + } +}; + +template struct Subscript0<int*, int, int&>; +template struct Subscript0<Sub0, int, int&>; +template struct Subscript0<Sub1, ConvertibleToInt, long&>; +template struct Subscript0<Sub1, Sub0, long&>; // expected-note{{instantiation}} + +// PR5345 +template <typename T> +struct S { + bool operator[](int n) const { return true; } +}; + +template <typename T> +void Foo(const S<int>& s, T x) { + if (s[0]) {} +} + +void Bar() { + Foo(S<int>(), 0); +} diff --git a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp new file mode 100644 index 0000000..a70c7e8 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<template<typename T> class MetaFun, typename Value> +struct apply { + typedef typename MetaFun<Value>::type type; +}; + +template<class T> +struct add_pointer { + typedef T* type; +}; + +template<class T> +struct add_reference { + typedef T& type; +}; + +int i; +apply<add_pointer, int>::type ip = &i; +apply<add_reference, int>::type ir = i; +apply<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'int'}} + +// Template template parameters +template<int> struct B; // expected-note{{has a different type 'int'}} + +template<typename T, + template<T Value> class X> // expected-error{{cannot have type 'float'}} \ + // expected-note{{with type 'long'}} +struct X0 { }; + +X0<int, B> x0b1; +X0<float, B> x0b2; // expected-note{{while substituting}} +X0<long, B> x0b3; // expected-error{{template template argument has different template parameters}} + +template<template<int V> class TT> // expected-note{{parameter with type 'int'}} +struct X1 { }; + +template<typename T, template<T V> class TT> +struct X2 { + X1<TT> x1; // expected-error{{has different template parameters}} +}; + +template<int V> struct X3i { }; +template<long V> struct X3l { }; // expected-note{{different type 'long'}} + +X2<int, X3i> x2okay; +X2<long, X3l> x2bad; // expected-note{{instantiation}} + +template <typename T, template <T, T> class TT, class R = TT<1, 2> > +struct Comp { + typedef R r1; + template <T x, T y> struct gt { + static const bool result = x > y; + }; + typedef gt<2, 1> r2; +}; + +template <int x, int y> struct lt { + static const bool result = x < y; +}; + +Comp<int, lt> c0; + +namespace PR8629 { + template<template<int> class TT> struct X0 + { + static void apply(); + }; + template<int> struct Type { }; + + template<class T> struct X1 + { + template<class U> struct Inner; + + template<class U> void g() + { + typedef Inner<U> Init; + X0<Init::template VeryInner>::apply(); + } + template<int N> void f () + { + g<Type<N> >(); + } + }; + template<class T> template<class U> struct X1<T>::Inner + { + template<int> struct VeryInner { + }; + }; + struct X1Container + { + X1Container() + { + simplex_.f<0>(); + } + X1<double> simplex_; + }; +} diff --git a/clang/test/SemaTemplate/instantiate-try-catch.cpp b/clang/test/SemaTemplate/instantiate-try-catch.cpp new file mode 100644 index 0000000..89cae03 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-try-catch.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -std=c++11 -verify %s + +template<typename T> struct TryCatch0 { + void f() { + try { + } catch (T&&) { // expected-error 2{{cannot catch exceptions by rvalue reference}} + } + } +}; + +template struct TryCatch0<int&>; // okay +template struct TryCatch0<int&&>; // expected-note{{instantiation}} +template struct TryCatch0<int>; // expected-note{{instantiation}} + + +namespace PR10232 { + template <typename T> + class Templated { + struct Exception { + private: + Exception(const Exception&); // expected-note{{declared private here}} + }; + void exception() { + try { + } catch(Exception e) { // expected-error{{calling a private constructor of class 'PR10232::Templated<int>::Exception'}} + } + } + }; + + template class Templated<int>; // expected-note{{in instantiation of member function 'PR10232::Templated<int>::exception' requested here}} +} diff --git a/clang/test/SemaTemplate/instantiate-type.cpp b/clang/test/SemaTemplate/instantiate-type.cpp new file mode 100644 index 0000000..f5d0270 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-type.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +int* f(int); +float *f(...); + +template<typename T> +struct X { + typedef typeof(T*) typeof_type; + typedef typeof(f(T())) typeof_expr; +}; + +int *iptr0; +float *fptr0; +X<int>::typeof_type &iptr1 = iptr0; + +X<int>::typeof_expr &iptr2 = iptr0; +X<float*>::typeof_expr &fptr1 = fptr0; diff --git a/clang/test/SemaTemplate/instantiate-typedef.cpp b/clang/test/SemaTemplate/instantiate-typedef.cpp new file mode 100644 index 0000000..4e6cd24 --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-typedef.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct add_pointer { + typedef T* type; // expected-error{{'type' declared as a pointer to a reference}} +}; + +add_pointer<int>::type test1(int * ptr) { return ptr; } + +add_pointer<float>::type test2(int * ptr) { + return ptr; // expected-error{{cannot initialize return object of type 'add_pointer<float>::type' (aka 'float *') with an lvalue of type 'int *'}} +} + +add_pointer<int&>::type // expected-note{{in instantiation of template class 'add_pointer<int &>' requested here}} +test3(); diff --git a/clang/test/SemaTemplate/instantiate-typeof.cpp b/clang/test/SemaTemplate/instantiate-typeof.cpp new file mode 100644 index 0000000..92873cb --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-typeof.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Make sure we correctly treat __typeof as potentially-evaluated when appropriate +template<typename T> void f(T n) { + int buffer[n]; // expected-note {{declared here}} + [] { __typeof(buffer) x; }(); // expected-error {{variable 'buffer' with variably modified type cannot be captured in a lambda expression}} +} +int main() { + f<int>(1); // expected-note {{in instantiation}} +} diff --git a/clang/test/SemaTemplate/instantiate-using-decl.cpp b/clang/test/SemaTemplate/instantiate-using-decl.cpp new file mode 100644 index 0000000..1bfcb7a --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-using-decl.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + namespace N { } + + template<typename T> + struct A { + void f(); + }; + + template<typename T> + struct B : A<T> { + using A<T>::f; + + void g() { + using namespace N; + f(); + } + }; + + template struct B<int>; +} + +namespace test1 { + template <class Derived> struct Visitor1 { + void Visit(struct Object1*); + }; + template <class Derived> struct Visitor2 { + void Visit(struct Object2*); // expected-note {{candidate function}} + }; + + template <class Derived> struct JoinVisitor + : Visitor1<Derived>, Visitor2<Derived> { + typedef Visitor1<Derived> Base1; + typedef Visitor2<Derived> Base2; + + void Visit(struct Object1*); // expected-note {{candidate function}} + using Base2::Visit; + }; + + class Knot : public JoinVisitor<Knot> { + }; + + void test() { + Knot().Visit((struct Object1*) 0); + Knot().Visit((struct Object2*) 0); + Knot().Visit((struct Object3*) 0); // expected-error {{no matching member function for call}} + } +} + +// PR5847 +namespace test2 { + namespace ns { + void foo(); + } + + template <class T> void bar(T* ptr) { + using ns::foo; + foo(); + } + + template void bar(char *); +} + +namespace test3 { + template <typename T> struct t { + struct s1 { + T f1() const; + }; + struct s2 : s1 { + using s1::f1; + T f1() const; + }; + }; + + void f2() + { + t<int>::s2 a; + t<int>::s2 const & b = a; + b.f1(); + } +} diff --git a/clang/test/SemaTemplate/instantiation-backtrace.cpp b/clang/test/SemaTemplate/instantiation-backtrace.cpp new file mode 100644 index 0000000..21456e9 --- /dev/null +++ b/clang/test/SemaTemplate/instantiation-backtrace.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> struct A; // expected-note 4{{template is declared here}} + +template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \ +// expected-error{{implicit instantiation of undefined template 'A<X *>'}} + +template<typename T> struct C : B<T> { } ; // expected-note{{instantiation of template class}} + +template<typename T> struct D : C<T> { }; // expected-note{{instantiation of template class}} + +template<typename T> struct E : D<T> { }; // expected-note{{instantiation of template class}} + +template<typename T> struct F : E<T(T)> { }; // expected-note{{instantiation of template class}} + +void f() { + (void)sizeof(F<int>); // expected-note{{instantiation of template class}} +} + +typedef struct { } X; + +void g() { + (void)sizeof(B<X>); // expected-note{{in instantiation of template class 'B<X>' requested here}} +} + +template<typename T> +struct G : A<T>, // expected-error{{implicit instantiation of undefined template 'A<int>'}} + A<T*> // expected-error{{implicit instantiation of undefined template 'A<int *>'}} + { }; + +void h() { + (void)sizeof(G<int>); // expected-note{{in instantiation of template class 'G<int>' requested here}} +} diff --git a/clang/test/SemaTemplate/instantiation-default-1.cpp b/clang/test/SemaTemplate/instantiation-default-1.cpp new file mode 100644 index 0000000..99154a5 --- /dev/null +++ b/clang/test/SemaTemplate/instantiation-default-1.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U = const T> struct Def1; + +template<> struct Def1<int> { + void foo(); +}; + +template<> struct Def1<const int> { // expected-note{{previous definition is here}} + void bar(); +}; + +template<> struct Def1<int&> { + void wibble(); +}; + +void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2, + Def1<int&, int&> *d3) { + d1->foo(); + d2->bar(); + d3->wibble(); +} + +template<typename T, // FIXME: bad error message below, needs better location info + typename T2 = const T*> // expected-error{{'T2' declared as a pointer to a reference}} + struct Def2; + +template<> struct Def2<int> { + void foo(); +}; + +void test_Def2(Def2<int, int const*> *d2) { + d2->foo(); +} + +typedef int& int_ref_t; +Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}} + + +template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<const int>'}} + +template<typename T, typename T2 = T&> struct Def3; + +template<> struct Def3<int> { + void foo(); +}; + +template<> struct Def3<int&> { + void bar(); +}; + +void test_Def3(Def3<int, int&> *d3a, Def3<int&, int&> *d3b) { + d3a->foo(); + d3b->bar(); +} + + +template<typename T, typename T2 = T[]> struct Def4; + +template<> struct Def4<int> { + void foo(); +}; + +void test_Def4(Def4<int, int[]> *d4a) { + d4a->foo(); +} + +template<typename T, typename T2 = T const[12]> struct Def5; + +template<> struct Def5<int> { + void foo(); +}; + +template<> struct Def5<int, int const[13]> { + void bar(); +}; + +void test_Def5(Def5<int, const int[12]> *d5a, Def5<int, const int[13]> *d5b) { + d5a->foo(); + d5b->bar(); +} + +template<typename R, typename Arg1, typename Arg2 = Arg1, + typename FuncType = R (*)(Arg1, Arg2)> + struct Def6; + +template<> struct Def6<int, float> { + void foo(); +}; + +template<> struct Def6<bool, int[5], float(double, double)> { + void bar(); +}; + +bool test_Def6(Def6<int, float, float> *d6a, + Def6<int, float, float, int (*)(float, float)> *d6b, + Def6<bool, int[5], float(double, double), + bool(*)(int*, float(*)(double, double))> *d6c) { + d6a->foo(); + d6b->foo(); + d6c->bar(); + return d6a == d6b; +} diff --git a/clang/test/SemaTemplate/instantiation-default-2.cpp b/clang/test/SemaTemplate/instantiation-default-2.cpp new file mode 100644 index 0000000..5a744a0 --- /dev/null +++ b/clang/test/SemaTemplate/instantiation-default-2.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, T Value> struct Constant; // expected-note{{template parameter is declared here}} \ +// FIXME: bad location expected-error{{a non-type template parameter cannot have type 'float'}} + +Constant<int, 5> *c1; + +int x; +float f(int, double); + +Constant<int&, x> *c2; +Constant<int*, &x> *c3; +Constant<float (*)(int, double), f> *c4; +Constant<float (*)(int, double), &f> *c5; + +Constant<float (*)(int, int), f> *c6; // expected-error{{non-type template argument of type 'float (int, double)' cannot be converted to a value of type 'float (*)(int, int)'}} + +Constant<float, 0> *c7; // expected-note{{while substituting}} diff --git a/clang/test/SemaTemplate/instantiation-default-3.cpp b/clang/test/SemaTemplate/instantiation-default-3.cpp new file mode 100644 index 0000000..dae6b18 --- /dev/null +++ b/clang/test/SemaTemplate/instantiation-default-3.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +template<typename T, typename U = A<T*> > + struct B : U { }; + +template<> +struct A<int*> { + void foo(); +}; + +template<> +struct A<float*> { + void bar(); +}; + +void test(B<int> *b1, B<float> *b2) { + b1->foo(); + b2->bar(); +} diff --git a/clang/test/SemaTemplate/instantiation-depth.cpp b/clang/test/SemaTemplate/instantiation-depth.cpp new file mode 100644 index 0000000..8e1b803 --- /dev/null +++ b/clang/test/SemaTemplate/instantiation-depth.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-depth 5 -ftemplate-backtrace-limit 4 %s +// RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth-5 -ftemplate-backtrace-limit=4 %s +// RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth=5 -ftemplate-backtrace-limit=4 %s + +template<typename T> struct X : X<T*> { }; \ +// expected-error{{recursive template instantiation exceeded maximum depth of 5}} \ +// expected-note 3 {{instantiation of template class}} \ +// expected-note {{skipping 2 contexts in backtrace}} \ +// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}} + +void test() { + (void)sizeof(X<int>); // expected-note {{instantiation of template class}} +} diff --git a/clang/test/SemaTemplate/instantiation-order.cpp b/clang/test/SemaTemplate/instantiation-order.cpp new file mode 100644 index 0000000..e058a5b --- /dev/null +++ b/clang/test/SemaTemplate/instantiation-order.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// From core issue 1227. + +template <class T> struct A { using X = typename T::X; }; // expected-error {{no members}} +template <class T> typename T::X f(typename A<T>::X); +template <class T> void f(...) {} +template <class T> auto g(typename A<T>::X) -> typename T::X; // expected-note {{here}} expected-note {{substituting}} +template <class T> void g(...) {} + +void h() +{ + f<int>(0); // ok, SFINAE in return type + g<int>(0); // not ok, substitution inside A<int> is a hard error +} diff --git a/clang/test/SemaTemplate/issue150.cpp b/clang/test/SemaTemplate/issue150.cpp new file mode 100644 index 0000000..af3b93c --- /dev/null +++ b/clang/test/SemaTemplate/issue150.cpp @@ -0,0 +1,107 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Core issue 150: Template template parameters and default arguments + +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; +}; + +namespace PR9353 { + template<class _T, class Traits> class IM; + + template <class T, class Trt, + template<class _T, class Traits = int> class IntervalMap> + void foo(IntervalMap<T,Trt>* m) { typedef IntervalMap<int> type; } + + void f(IM<int, int>* m) { foo(m); } +} + +namespace PR9400 { + template<template <typename T, typename = T > class U> struct A + { + template<int> U<int> foo(); + }; + + template <typename T, typename = T> + struct s { + }; + + void f() { + A<s> x; + x.foo<2>(); + } +} + +namespace MultiReplace { + template<typename Z, + template<typename T, typename U = T *, typename V = U const> class TT> + struct X { + typedef TT<Z> type; + }; + + template<typename T, typename = int, typename = float> + struct Y { }; + + int check0[is_same<X<int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1]; +} + +namespace MultiReplacePartial { + template<typename First, typename Z, + template<typename T, typename U = T *, typename V = U const> class TT> + struct X { + typedef TT<Z> type; + }; + + template<typename Z, + template<typename T, typename U = T *, typename V = U const> class TT> + struct X<int, Z, TT> { + typedef TT<Z> type; + }; + + template<typename T, typename = int, typename = float> + struct Y { }; + + int check0[is_same<X<int, int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1]; +} + +namespace PR9016 { + template<typename > struct allocator ; + template<typename > struct less ; + + template<class T, template<class> class Compare, class Default, + template<class> class Alloc> + struct interval_set { }; + + template <class X, template<class> class = less> struct interval_type_default { + typedef X type; + }; + + template <class T, + template<class _T, template<class> class Compare = PR9016::less, + class = typename interval_type_default<_T,Compare>::type, + template<class> class = allocator> class IntervalSet> + struct ZZZ + { + IntervalSet<T> IntervalSetT; + }; + + template <class T, + template<class _T, template<class> class Compare = PR9016::less, + class = typename interval_type_default<_T,Compare>::type, + template<class> class = allocator> class IntervalSet> + void int40() + { + IntervalSet<T> IntervalSetT; + } + + void test() { + ZZZ<int, interval_set> zzz; + int40<int, interval_set>(); + } +} diff --git a/clang/test/SemaTemplate/lookup-dependent-bases.cpp b/clang/test/SemaTemplate/lookup-dependent-bases.cpp new file mode 100644 index 0000000..2710caf --- /dev/null +++ b/clang/test/SemaTemplate/lookup-dependent-bases.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s + +class C { +public: + static void foo2() { } +}; +template <class T> +class A { +public: + typedef C D; +}; + +template <class T> +class B : public A<T> { +public: + void foo() { + D::foo2(); + } +}; diff --git a/clang/test/SemaTemplate/member-access-ambig.cpp b/clang/test/SemaTemplate/member-access-ambig.cpp new file mode 100644 index 0000000..f8a01d5 --- /dev/null +++ b/clang/test/SemaTemplate/member-access-ambig.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR8439 +class A +{ +}; + +class B +{ +public: + A & m; +}; + +class Base +{ +public: + B &f(); +}; + +class Derived1 : public Base { }; + +class Derived2 : public Base { }; + +class X : public B, public Derived2, public Derived1 +{ +public: + virtual void g(); +}; + +void X::g() +{ + m.f<int>(); // expected-error{{no member named 'f' in 'A'}} \ + // expected-error{{expected '(' for function-style cast}} \ + // expected-error{{expected expression}} +} + +namespace PR11134 { + template<typename Derived> class A; + template<typename Derived> class B : A<Derived> { + typedef A<Derived> Base; + using Base::member; + int member; + }; +} + diff --git a/clang/test/SemaTemplate/member-access-expr.cpp b/clang/test/SemaTemplate/member-access-expr.cpp new file mode 100644 index 0000000..f1aa30e --- /dev/null +++ b/clang/test/SemaTemplate/member-access-expr.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -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(); + ptr->T::~T(); +} + +template<typename T> +void destruct_intptr(int *ip) { + ip->~T(); + ip->T::~T(); +} + +void test_destruct(X2 *x2p, int *ip) { + destruct(x2p); + destruct(ip); + destruct_intptr<int>(ip); +} + +// PR5220 +class X3 { +protected: + template <int> float* &f0(); + template <int> const float* &f0() const; + void f1() { + (void)static_cast<float*>(f0<0>()); + } + void f1() const{ + (void)f0<0>(); + } +}; + +// Fun with template instantiation and conversions +struct X4 { + int& member(); + float& member() const; +}; + +template<typename T> +struct X5 { + void f(T* ptr) { int& ir = ptr->member(); } + void g(T* ptr) { float& fr = ptr->member(); } +}; + +void test_X5(X5<X4> x5, X5<const X4> x5c, X4 *xp, const X4 *cxp) { + x5.f(xp); + x5c.g(cxp); +} + +// In theory we can do overload resolution at template-definition time on this. +// We should at least not assert. +namespace test4 { + struct Base { + template <class T> void foo() {} + }; + + template <class T> struct Foo : Base { + void test() { + foo<int>(); + } + }; +} + +namespace test5 { + template<typename T> + struct X { + using T::value; + + T &getValue() { + return &value; + } + }; +} + +// PR8739 +namespace test6 { + struct A {}; + struct B {}; + template <class T> class Base; + template <class T> class Derived : public Base<T> { + A *field; + void get(B **ptr) { + // It's okay if at some point we figure out how to diagnose this + // at instantiation time. + *ptr = field; + } + }; +} diff --git a/clang/test/SemaTemplate/member-function-template.cpp b/clang/test/SemaTemplate/member-function-template.cpp new file mode 100644 index 0000000..44954ed --- /dev/null +++ b/clang/test/SemaTemplate/member-function-template.cpp @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -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; }; + +// PR5419 +struct Functor { + template <typename T> + bool operator()(const T& v) const { + return true; + } +}; + +void test_Functor(Functor f) { + f(1); +} + +// Instantiation on -> +template<typename T> +struct X1 { + template<typename U> U& get(); +}; + +template<typename T> struct X2; // expected-note{{here}} + +void test_incomplete_access(X1<int> *x1, X2<int> *x2) { + float &fr = x1->get<float>(); + (void)x2->get<float>(); // expected-error{{implicit instantiation of undefined template}} +} + +// Instantiation of template template parameters in a member function +// template. +namespace TTP { + template<int Dim> struct X { + template<template<class> class M, class T> void f(const M<T>&); + }; + + template<typename T> struct Y { }; + + void test_f(X<3> x, Y<int> y) { x.f(y); } +} + +namespace PR7387 { + template <typename T> struct X {}; + + template <typename T1> struct S { + template <template <typename> class TC> void foo(const TC<T1>& arg); + }; + + template <typename T1> template <template <typename> class TC> + void S<T1>::foo(const TC<T1>& arg) {} + + void test(const X<int>& x) { + S<int> s; + s.foo(x); + } +} diff --git a/clang/test/SemaTemplate/member-inclass-init-value-dependent.cpp b/clang/test/SemaTemplate/member-inclass-init-value-dependent.cpp new file mode 100644 index 0000000..5bff7f2 --- /dev/null +++ b/clang/test/SemaTemplate/member-inclass-init-value-dependent.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -emit-llvm-only %s +// PR10290 + +template<int Flags> struct foo { + int value = Flags && 0; +}; + +void test() { + foo<4> bar; +} + +struct S { + S(int n); +}; +template<typename> struct T { + S s = 0; +}; +T<int> t; diff --git a/clang/test/SemaTemplate/member-initializers.cpp b/clang/test/SemaTemplate/member-initializers.cpp new file mode 100644 index 0000000..40f56b3 --- /dev/null +++ b/clang/test/SemaTemplate/member-initializers.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -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/clang/test/SemaTemplate/member-template-access-expr.cpp b/clang/test/SemaTemplate/member-template-access-expr.cpp new file mode 100644 index 0000000..c95b57d --- /dev/null +++ b/clang/test/SemaTemplate/member-template-access-expr.cpp @@ -0,0 +1,144 @@ +// RUN: %clang_cc1 -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) { + int &ir = f1<X>(xd); +} + +// PR5213 +template <class T> +struct A {}; + +template<class T> +class B +{ + A<T> a_; + +public: + void destroy(); +}; + +template<class T> +void +B<T>::destroy() +{ + a_.~A<T>(); +} + +void do_destroy_B(B<int> b) { + b.destroy(); +} + +struct X1 { + int* f1(int); + template<typename T> float* f1(T); + + static int* f2(int); + template<typename T> static float* f2(T); +}; + +void test_X1(X1 x1) { + float *fp1 = x1.f1<>(17); + float *fp2 = x1.f1<int>(3.14); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int *ip1 = x1.f1(17); + float *ip2 = x1.f1(3.14); + + float* (X1::*mf1)(int) = &X1::f1; + float* (X1::*mf2)(int) = &X1::f1<>; + float* (X1::*mf3)(float) = &X1::f1<float>; + + float* (*fp3)(int) = &X1::f2; + float* (*fp4)(int) = &X1::f2<>; + float* (*fp5)(float) = &X1::f2<float>; + float* (*fp6)(int) = X1::f2; + float* (*fp7)(int) = X1::f2<>; + float* (*fp8)(float) = X1::f2<float>; +} + +template<int A> struct X2 { + int m; +}; + +template<typename T> +struct X3 : T { }; + +template<typename T> +struct X4 { + template<typename U> + void f(X2<sizeof(X3<U>().U::m)>); +}; + +void f(X4<X3<int> > x4i) { + X2<sizeof(int)> x2; + x4i.f<X2<sizeof(int)> >(x2); +} + +template<typename T> +struct X5 { + template<typename U> + void f(); + + void g() { + this->f<T*>(); + } +}; + +namespace PR6021 { + template< class T1, class T2 > + class Outer + { + public: // Range operations + template< class X > X tmpl( const X* = 0 ) const; + + struct Inner + { + const Outer& o; + + template< class X > + operator X() const + { + return o.tmpl<X>(); + } + }; + }; +} + +namespace rdar8198511 { + template<int, typename U> + struct Base { + void f(); + }; + + template<typename T> + struct X0 : Base<1, T> { }; + + template<typename T> + struct X1 { + X0<int> x0; + + void f() { + this->x0.Base<1, int>::f(); + } + }; +} diff --git a/clang/test/SemaTemplate/metafun-apply.cpp b/clang/test/SemaTemplate/metafun-apply.cpp new file mode 100644 index 0000000..3a7408e --- /dev/null +++ b/clang/test/SemaTemplate/metafun-apply.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct add_pointer { + template<typename T> + struct apply { + typedef T* type; + }; +}; + +struct add_reference { + template<typename T> + struct apply { + typedef T& type; // expected-error{{cannot form a reference to 'void'}} + }; +}; + +struct bogus { + struct apply { + typedef int type; + }; +}; + +template<typename MetaFun, typename T> +struct apply1 { + typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'add_reference::apply<void>' requested here}} \ + // expected-error{{'apply' following the 'template' keyword does not refer to a template}} +}; + +int i; +apply1<add_pointer, int>::type ip = &i; +apply1<add_reference, int>::type ir = i; +apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'int'}} + +void test() { + apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'apply1<add_reference, void>' requested here}} + + apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'apply1<bogus, int>' requested here}} +} + + diff --git a/clang/test/SemaTemplate/missing-class-keyword-crash.cpp b/clang/test/SemaTemplate/missing-class-keyword-crash.cpp new file mode 100644 index 0000000..f0eee2b --- /dev/null +++ b/clang/test/SemaTemplate/missing-class-keyword-crash.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class G {}; +template <Foo> // expected-error{{unknown type name 'Foo'}} \ + // expected-note{{template parameter is declared here}} +class Bar {}; + +class Bar<G> blah_test; // expected-error{{template argument for non-type template parameter must be an expression}} diff --git a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp new file mode 100644 index 0000000..bda87f9 --- /dev/null +++ b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s + + +class A { +public: + template <class U> + A(U p) { + } + template <> + A(int p) { // expected-warning{{explicit specialization of 'A' within class scope is a Microsoft extension}} + } + + template <class U> + void f(U p) { + } + + template <> + void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope is a Microsoft extension}} + } + + void f(int p) { + } +}; + +void test1() +{ + A a(3); + char* b ; + a.f(b); + a.f<int>(99); + a.f(100); +} + + + + +template <class T> +class B { +public: + template <class U> + B(U p) { + } + template <> + B(int p) { // expected-warning{{explicit specialization of 'B<T>' within class scope is a Microsoft extension}} + } + + template <class U> + void f(U p) { + T y = 9; + } + + + template <> + void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope is a Microsoft extension}} + T a = 3; + } + + void f(int p) { + T a = 3; + } +}; + +void test2() +{ + B<char> b(3); + char* ptr; + b.f(ptr); + b.f<int>(99); + b.f(100); +} + diff --git a/clang/test/SemaTemplate/ms-if-exists.cpp b/clang/test/SemaTemplate/ms-if-exists.cpp new file mode 100644 index 0000000..04f4a63 --- /dev/null +++ b/clang/test/SemaTemplate/ms-if-exists.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fms-extensions -std=c++11 %s -verify + +struct Nontemplate { + typedef int type; +}; + +template<typename T> +struct X { + __if_exists(Nontemplate::type) { + typedef Nontemplate::type type; + } + + __if_exists(Nontemplate::value) { + typedef Nontemplate::value type2; + } + + __if_not_exists(Nontemplate::value) { + typedef int type3; + } + + __if_exists(T::X) { // expected-warning{{dependent __if_exists declarations are ignored}} + typedef T::X type4; + } +}; + +X<int>::type i1; +X<int>::type2 i2; // expected-error{{no type named 'type2' in 'X<int>'}} +X<int>::type3 i3; +X<int>::type4 i4; // expected-error{{no type named 'type4' in 'X<int>'}} + +struct HasFoo { + void foo(); +}; +struct HasBar { + void bar(int); + void bar(float); +}; + +template<typename T> +void f(T t) { + __if_exists(T::foo) { + { } + t.foo(); + } + + __if_not_exists(T::bar) { + int *i = t; // expected-error{{no viable conversion from 'HasFoo' to 'int *'}} + { } + } + + int array2[] = {
+ 0,
+ __if_exists(T::bar) {2, }// expected-warning{{dependent __if_exists declarations are ignored}}
+ 3
+ };
+} + +template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' requested here}} +template void f(HasBar); + +template<typename T, typename ...Ts> +void g(T, Ts...) { + __if_exists(T::operator Ts) { // expected-error{{__if_exists name contains unexpanded parameter pack 'Ts'}} + } + + __if_not_exists(Ts::operator T) { // expected-error{{__if_not_exists name contains unexpanded parameter pack 'Ts'}} + } +} diff --git a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp new file mode 100644 index 0000000..2c422dc --- /dev/null +++ b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -0,0 +1,145 @@ +// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s + + +template <class T> +class A { +public: + void f(T a) { }// expected-note {{must qualify identifier to find this declaration in dependent base class}} + void g();// expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + + +template <class T> +class B : public A<T> { +public: + void z(T a) + { + f(a); // expected-warning {{use of identifier 'f' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + g(); // expected-warning {{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + } +}; + +template class B<int>; // expected-note {{requested here}} +template class B<char>; + +void test() +{ + B<int> b; + b.z(3); +} + +namespace lookup_dependent_bases_id_expr { + +template<class T> class A { +public: + int var; +}; + + +template<class T> +class B : public A<T> { +public: + void f() { + var = 3; + } +}; + +template class B<int>; + +} + + + +namespace lookup_dependent_base_class_static_function { + +template <class T> +class A { +public: + static void static_func();// expected-note {{must qualify identifier to find this declaration in dependent base class}} + void func();// expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + + +template <class T> +class B : public A<T> { +public: + static void z2(){ + static_func(); // expected-warning {{use of identifier 'static_func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + func(); // expected-warning {{use of identifier 'func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}} + } +}; +template class B<int>; // expected-note {{requested here}} + +} + + + +namespace lookup_dependent_base_class_default_argument { + +template<class T> +class A { +public: + static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + +template<class T> +class B : public A<T> { +public: + void g1(int p = f1());// expected-warning {{use of identifier 'f1' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + void g2(int p = f2());// expected-warning {{use of identifier 'f2' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}} +}; + +void foo() +{ + B<int> b; + b.g1(); // expected-note {{required here}} + b.g2(); // expected-note {{required here}} +} + +} + + +namespace lookup_dependent_base_class_friend { + +template <class T> +class B { +public: + static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + +template <class T> +class A : public B<T> { +public: + friend void foo(A<T> p){ + g(); // expected-warning {{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + } +}; + +int main2() +{ + A<int> a; + foo(a); // expected-note {{requested here}} +} + +} + + +namespace lookup_dependent_base_no_typo_correction { + +class C { +public: + int m_hWnd; +}; + +template <class T> +class A : public T { +public: + void f(int hWnd) { + m_hWnd = 1; + } +}; + +template class A<C>; + +} diff --git a/clang/test/SemaTemplate/nested-incomplete-class.cpp b/clang/test/SemaTemplate/nested-incomplete-class.cpp new file mode 100644 index 0000000..a4bfccb --- /dev/null +++ b/clang/test/SemaTemplate/nested-incomplete-class.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template <typename T> +struct foo { + struct bar; + + bar fn() { + // Should not get errors about bar being incomplete here. + bar b = bar(1, 2); + return b; + } +}; + +template <typename T> +struct foo<T>::bar { + bar(int, int); +}; + +void fn() { + foo<int>().fn(); +} diff --git a/clang/test/SemaTemplate/nested-linkage.cpp b/clang/test/SemaTemplate/nested-linkage.cpp new file mode 100644 index 0000000..6c0791c --- /dev/null +++ b/clang/test/SemaTemplate/nested-linkage.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern "C" { extern "C++" { template<class C> C x(); } } diff --git a/clang/test/SemaTemplate/nested-name-spec-template.cpp b/clang/test/SemaTemplate/nested-name-spec-template.cpp new file mode 100644 index 0000000..635687d --- /dev/null +++ b/clang/test/SemaTemplate/nested-name-spec-template.cpp @@ -0,0 +1,142 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + namespace M { + template<typename T> struct Promote; + + template<> struct Promote<short> { + typedef int type; + }; + + template<> struct Promote<int> { + typedef int type; + }; + + template<> struct Promote<float> { + typedef double type; + }; + + Promote<short>::type *ret_intptr(int* ip) { return ip; } + Promote<int>::type *ret_intptr2(int* ip) { return ip; } + } + + M::Promote<int>::type *ret_intptr3(int* ip) { return ip; } + M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' keyword outside of a template}} + M::template Promote<int> pi; // expected-warning{{'template' keyword outside of a template}} +} + +N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; } +::N::M::Promote<int>::type *ret_intptr6(int* ip) { return ip; } + + +N::M::template; // expected-error{{expected unqualified-id}} +N::M::template Promote; // expected-error{{expected unqualified-id}} + +namespace N { + template<typename T> struct A; + + template<> + struct A<int> { + struct X; + }; + + struct B; +} + +struct ::N::A<int>::X { + int foo; +}; + +template<typename T> +struct TestA { + typedef typename N::template B<T>::type type; // expected-error{{'B' following the 'template' keyword does not refer to a template}} \ + // expected-error{{expected member name}} +}; + +// Reduced from a Boost failure. +namespace test1 { + template <class T> struct pair { + T x; + T y; + + static T pair<T>::* const mem_array[2]; + }; + + template <class T> + T pair<T>::* const pair<T>::mem_array[2] = { &pair<T>::x, &pair<T>::y }; +} + +typedef int T; +namespace N1 { + template<typename T> T f0(); +} + +template<typename T> T N1::f0() { } + +namespace PR7385 { + template< typename > struct has_xxx0 + { + template< typename > struct has_xxx0_introspect + { + template< typename > struct has_xxx0_substitute ; + template< typename V > + int int00( has_xxx0_substitute < typename V::template xxx< > > = 0 ); + }; + static const int value = has_xxx0_introspect<int>::value; // expected-error{{no member named 'value'}} + typedef int type; + }; + + has_xxx0<int>::type t; // expected-note{{instantiation of}} +} + +namespace PR7725 { + template<class ignored> struct TypedefProvider; + template<typename T> + struct TemplateClass : public TypedefProvider<T> + { + void PrintSelf() { + TemplateClass::Test::PrintSelf(); + } + }; +} + +namespace PR9226 { + template<typename a> + void nt() // expected-note{{function template 'nt' declared here}} + { nt<>:: } // expected-error{{qualified name refers into a specialization of function template 'nt'}} \ + // expected-error{{expected unqualified-id}} + + template<typename T> + void f(T*); // expected-note{{function template 'f' declared here}} + + template<typename T> + void f(T*, T*); // expected-note{{function template 'f' declared here}} + + void g() { + f<int>:: // expected-error{{qualified name refers into a specialization of function template 'f'}} + } // expected-error{{expected unqualified-id}} + + struct X { + template<typename T> void f(); // expected-note{{function template 'f' declared here}} + }; + + template<typename T, typename U> + struct Y { + typedef typename T::template f<U> type; // expected-error{{template name refers to non-type template 'X::f'}} + }; + + Y<X, int> yxi; // expected-note{{in instantiation of template class 'PR9226::Y<PR9226::X, int>' requested here}} +} + +namespace PR9449 { + template <typename T> + struct s; // expected-note{{template is declared here}} + + template <typename T> + void f() { + int s<T>::template n<T>::* f; // expected-error{{implicit instantiation of undefined template 'PR9449::s<int>'}} \ + // expected-error{{following the 'template' keyword}} + } + + template void f<int>(); // expected-note{{in instantiation of}} +} diff --git a/clang/test/SemaTemplate/nested-template.cpp b/clang/test/SemaTemplate/nested-template.cpp new file mode 100644 index 0000000..7849bae --- /dev/null +++ b/clang/test/SemaTemplate/nested-template.cpp @@ -0,0 +1,157 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class A; + +class S { +public: + template<typename T> struct A { + struct Nested { + typedef T type; + }; + }; +}; + +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()) { } +}; + +// PR5103 +template<typename> +struct X1 { + template<typename, bool = false> struct B { }; +}; +template struct X1<int>::B<bool>; + +// Template template parameters +template<typename T> +struct X2 { + template<template<class U, T Value> class> // expected-error{{cannot have type 'float'}} \ + // expected-note{{previous non-type template}} + struct Inner { }; +}; + +template<typename T, + int Value> // expected-note{{template non-type parameter}} + struct X2_arg; + +X2<int>::Inner<X2_arg> x2i1; +X2<float> x2a; // expected-note{{instantiation}} +X2<long>::Inner<X2_arg> x2i3; // expected-error{{template template argument has different}} + +namespace PR10896 { + template<typename TN> + class Foo { + + public: + void foo() {} + private: + + template<typename T> + T SomeField; // expected-error {{member 'SomeField' declared as a template}} + }; + + void g() { + Foo<int> f; + f.foo(); + } +} + +namespace PR10924 { + template< class Topology, class ctype > + struct ReferenceElement + { + }; + + template< class Topology, class ctype > + template< int codim > + class ReferenceElement< Topology, ctype > :: BaryCenterArray // expected-error{{out-of-line definition of 'BaryCenterArray' does not match any declaration in 'ReferenceElement<Topology, ctype>'}} + { + }; +} diff --git a/clang/test/SemaTemplate/operator-function-id-template.cpp b/clang/test/SemaTemplate/operator-function-id-template.cpp new file mode 100644 index 0000000..9a0884e --- /dev/null +++ b/clang/test/SemaTemplate/operator-function-id-template.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct A { + template<typename U> A<T> operator+(U); +}; + +template<int Value, typename T> bool operator==(A<T>, A<T>); + +template<> bool operator==<0>(A<int>, A<int>); + +bool test_qualified_id(A<int> ai) { + return ::operator==<0, int>(ai, ai); +} + +void test_op(A<int> a, int i) { + const A<int> &air = a.operator+<int>(i); +} + +template<typename T> +void test_op_template(A<T> at, T x) { + const A<T> &atr = at.template operator+<T>(x); + const A<T> &atr2 = at.A::template operator+<T>(x); + // FIXME: unrelated template-name instantiation issue + // const A<T> &atr3 = at.template A<T>::template operator+<T>(x); +} + +template void test_op_template<float>(A<float>, float); diff --git a/clang/test/SemaTemplate/operator-template.cpp b/clang/test/SemaTemplate/operator-template.cpp new file mode 100644 index 0000000..777b0f5 --- /dev/null +++ b/clang/test/SemaTemplate/operator-template.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Make sure we accept this +template<class X>struct A{typedef X Y;}; +template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: failed template argument deduction}} + +int a(A<int> x) { return operator==(x,1); } + +int a0(A<int> x) { return x == 1; } + +// FIXME: the location information for the note isn't very good +template<class X>struct B{typedef X Y;}; +template<class X>bool operator==(B<X>*,typename B<X>::Y); // \ +// expected-error{{overloaded 'operator==' must have at least one parameter of class or enumeration type}} \ +// expected-note{{in instantiation of function template specialization}} \ +// expected-note{{candidate template ignored: substitution failure [with X = int]}} +int a(B<int> x) { return operator==(&x,1); } // expected-error{{no matching function for call to 'operator=='}} + diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp new file mode 100644 index 0000000..8762cc8 --- /dev/null +++ b/clang/test/SemaTemplate/overload-candidates.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +const T& min(const T&, const T&); // expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'long')}} + +void test_min() { + (void)min(1, 2l); // expected-error{{no matching function for call to 'min'}} +} + +template<typename R, typename T> +R *dyn_cast(const T&); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + +void test_dyn_cast(int* ptr) { + (void)dyn_cast(ptr); // expected-error{{no matching function for call to 'dyn_cast'}} +} + +template<int I, typename T> + void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I'}} +template<template<class T> class, typename T> + void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} + +void test_get(void *ptr) { + get<int>(ptr); // expected-error{{no matching function for call to 'get'}} +} + +template<typename T> + typename T::type get_type(const T&); // expected-note{{candidate template ignored: substitution failure [with T = int *]}} + +void test_get_type(int *ptr) { + (void)get_type(ptr); // expected-error{{no matching function for call to 'get_type'}} +} + +struct X { + template<typename T> + const T& min(const T&, const T&); // expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'long')}} +}; + +void test_X_min(X x) { + (void)x.min(1, 2l); // expected-error{{no matching member function for call to 'min'}} +} diff --git a/clang/test/SemaTemplate/overload-uneval.cpp b/clang/test/SemaTemplate/overload-uneval.cpp new file mode 100644 index 0000000..8d8a2f4 --- /dev/null +++ b/clang/test/SemaTemplate/overload-uneval.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused %s + +// Tests that overload resolution is treated as an unevaluated context. +// PR5541 +struct Foo +{ + Foo *next; +}; + +template <typename> +struct Bar +{ +}; + + +template <typename T> +class Wibble +{ + typedef Bar<T> B; + + static inline B *concrete(Foo *node) { + int a[sizeof(T) ? -1 : -1]; + return reinterpret_cast<B *>(node); + } + +public: + class It + { + Foo *i; + + public: + inline operator B *() const { return concrete(i); } + inline bool operator!=(const It &o) const { return i != +o.i; } + }; +}; + +void f() { + Wibble<void*>::It a, b; + + a != b; +} diff --git a/clang/test/SemaTemplate/partial-spec-instantiate.cpp b/clang/test/SemaTemplate/partial-spec-instantiate.cpp new file mode 100644 index 0000000..a93af50 --- /dev/null +++ b/clang/test/SemaTemplate/partial-spec-instantiate.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -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();} + +namespace WonkyAccess { + template<typename T> + struct X { + int m; + }; + + template<typename U> + class Y; + + template<typename U> + struct Y<U*> : X<U> { }; + + template<> + struct Y<float*> : X<float> { }; + + int f(Y<int*> y, Y<float*> y2) { + 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/clang/test/SemaTemplate/pragma-ms_struct.cpp b/clang/test/SemaTemplate/pragma-ms_struct.cpp new file mode 100644 index 0000000..f04dc5c --- /dev/null +++ b/clang/test/SemaTemplate/pragma-ms_struct.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-osx10.7.0 %s + +#pragma ms_struct on + +// <rdar://problem/10791194> +template<int x> struct foo { + long long a; + int b; +}; +extern int arr[sizeof(foo<0>) == 16 ? 1 : -1]; diff --git a/clang/test/SemaTemplate/qualified-id.cpp b/clang/test/SemaTemplate/qualified-id.cpp new file mode 100644 index 0000000..64dff1c --- /dev/null +++ b/clang/test/SemaTemplate/qualified-id.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5061 +namespace a { + template <typename T> class C {}; +} +namespace b { + template<typename T> void f0(a::C<T> &a0) { } +} + + +namespace test1 { + int a = 0; + template <class T> class Base { }; + template <class T> class Derived : public Base<T> { + int foo() { + return test1::a; + } + }; +} + +namespace test2 { + class Impl { + public: + int foo(); + }; + template <class T> class Magic : public Impl { + int foo() { + return Impl::foo(); + } + }; +} + +namespace PR6063 { + template <typename T> void f(T, T); + + namespace detail + { + using PR6063::f; + } + + template <typename T> + void g(T a, T b) + { + detail::f(a, b); + } +} + +namespace PR12291 { + template <typename T> + class Outer2 { + template <typename V> + template <typename W> + class Outer2<V>::Inner; // expected-error{{nested name specifier 'Outer2<V>::' for declaration does not refer into a class, class template or class template partial specialization}} + }; +} diff --git a/clang/test/SemaTemplate/qualified-names-diag.cpp b/clang/test/SemaTemplate/qualified-names-diag.cpp new file mode 100644 index 0000000..b2df47b --- /dev/null +++ b/clang/test/SemaTemplate/qualified-names-diag.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace std { + template<typename T> class vector { }; // expected-note{{candidate}} +} + +typedef int INT; +typedef float Real; + +void test() { + using namespace std; + + std::vector<INT> v1; + vector<Real> v2; + v1 = v2; // expected-error{{no viable overloaded '='}} +} diff --git a/clang/test/SemaTemplate/rdar9173693.cpp b/clang/test/SemaTemplate/rdar9173693.cpp new file mode 100644 index 0000000..86b4954 --- /dev/null +++ b/clang/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/clang/test/SemaTemplate/recovery-crash.cpp b/clang/test/SemaTemplate/recovery-crash.cpp new file mode 100644 index 0000000..0ed3258 --- /dev/null +++ b/clang/test/SemaTemplate/recovery-crash.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// We don't expect a fix-it to be applied in this case. Clang used to crash +// trying to recover while adding 'this->' before Work(x); + +template <typename> struct A { + static void Work(int); // expected-note{{must qualify identifier}} +}; + +template <typename T> struct B : public A<T> { + template <typename T2> B(T2 x) { + Work(x); // expected-error{{use of undeclared identifier}} + } +}; + +void Test() { + B<int> b(0); // expected-note{{in instantiation of function template}} +} + diff --git a/clang/test/SemaTemplate/recursive-template-instantiation.cpp b/clang/test/SemaTemplate/recursive-template-instantiation.cpp new file mode 100644 index 0000000..d6a0b24 --- /dev/null +++ b/clang/test/SemaTemplate/recursive-template-instantiation.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> void f(T* t) { // expected-note{{failed template argument deduction}} + f(*t); // expected-error{{no matching function}}\ + // expected-note 3{{requested here}} +} + +void test_f(int ****p) { + f(p); // expected-note{{requested here}} +} diff --git a/clang/test/SemaTemplate/resolve-single-template-id.cpp b/clang/test/SemaTemplate/resolve-single-template-id.cpp new file mode 100644 index 0000000..0c9bacc --- /dev/null +++ b/clang/test/SemaTemplate/resolve-single-template-id.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace std { + class type_info {}; +} + +void one() { } +void two() { } // expected-note 4{{possible target for call}} +void two(int) { } // expected-note 4{{possible target for call}} + +template<class T> void twoT() { } // expected-note 5{{possible target for call}} +template<class T> void twoT(int) { } // expected-note 5{{possible target for call}} + +template<class T> void oneT() { } +template<class T, class U> void oneT(U) { } +/* +The target can be + an object or reference being initialized (8.5, 8.5.3), + the left side of an assignment (5.17), + a parameter of a function (5.2.2), + a parameter of a user-defined operator (13.5), + the return value of a function, operator function, or conversion (6.6.3), + an explicit type conversion (5.2.3, 5.2.9, 5.4), or + a non-type template-parameter (14.3.2) +*/ +//#include <typeinfo> +template<void (*p)(int)> struct test { }; + +int main() +{ + one; // expected-warning {{expression result unused}} + two; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} + oneT<int>; // expected-warning {{expression result unused}} + twoT<int>; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + typeid(oneT<int>); // expected-warning{{expression result unused}} + sizeof(oneT<int>); // expected-warning {{expression result unused}} + sizeof(twoT<int>); //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + decltype(oneT<int>)* fun = 0; + + *one; // expected-warning {{expression result unused}} + *oneT<int>; // expected-warning {{expression result unused}} + *two; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{indirection requires pointer operand}} + *twoT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + !oneT<int>; // expected-warning {{expression result unused}} expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}} + +oneT<int>; // expected-warning {{expression result unused}} + -oneT<int>; //expected-error {{invalid argument type}} + oneT<int> == 0; // expected-warning {{equality comparison result unused}} \ + // expected-note {{use '=' to turn this equality comparison into an assignment}} + 0 == oneT<int>; // expected-warning {{equality comparison result unused}} + 0 != oneT<int>; // expected-warning {{inequality comparison result unused}} + (false ? one : oneT<int>); // expected-warning {{expression result unused}} + void (*p1)(int); p1 = oneT<int>; + + int i = (int) (false ? (void (*)(int))twoT<int> : oneT<int>); //expected-error {{incompatible operand}} + (twoT<int>) == oneT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} + bool b = oneT<int>; // expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}} + void (*p)() = oneT<int>; + test<oneT<int> > ti; + void (*u)(int) = oneT<int>; + + b = (void (*)()) twoT<int>; + + one < one; //expected-warning {{self-comparison always evaluates to false}} \ + //expected-warning {{expression result unused}} + + oneT<int> < oneT<int>; //expected-warning {{self-comparison always evaluates to false}} \ + //expected-warning {{expression result unused}} + + two < two; //expected-error 2 {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{invalid operands to binary expression ('void' and 'void')}} + twoT<int> < twoT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} + oneT<int> == 0; // expected-warning {{equality comparison result unused}} \ + // expected-note {{use '=' to turn this equality comparison into an assignment}} + +} + +struct rdar9108698 { + template<typename> void f(); +}; + +void test_rdar9108698(rdar9108698 x) { + x.f<int>; // expected-error{{reference to non-static member function must be called}} +} diff --git a/clang/test/SemaTemplate/self-comparison.cpp b/clang/test/SemaTemplate/self-comparison.cpp new file mode 100644 index 0000000..50ab660 --- /dev/null +++ b/clang/test/SemaTemplate/self-comparison.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <int A, int B> void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); +} +template <int A, int B> struct S1 { + void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +template <int A, int B> struct S2 { + template <typename T> T foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +struct S3 { + template <int A, int B> void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +template <int A> struct S4 { + template <int B> void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +const int N = 42; +template <int X> void foo2() { + (void)(X == N); + (void)(N == X); +} + +void test() { + foo<1, 1>(); + S1<1, 1> s1; s1.foo(); + S2<1, 1> s2; s2.foo<void>(); + S3 s3; s3.foo<1, 1>(); + S4<1> s4; s4.foo<1>(); + foo2<N>(); +} diff --git a/clang/test/SemaTemplate/temp.cpp b/clang/test/SemaTemplate/temp.cpp new file mode 100644 index 0000000..e037f0f --- /dev/null +++ b/clang/test/SemaTemplate/temp.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + + +namespace test0 { + // p3 + template<typename T> int foo(T), bar(T, T); // expected-error{{single entity}} +} + +// PR7252 +namespace test1 { + namespace A { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}} + namespace B { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}} + + template<typename T> struct Derived : A::Base<char>, B::Base<int> { + // FIXME: the syntax error here is unfortunate + typename Derived::Base<float>::t x; // expected-error {{found in multiple base classes of different types}} \ + // expected-error {{expected member name or ';'}} + }; +} diff --git a/clang/test/SemaTemplate/temp_arg.cpp b/clang/test/SemaTemplate/temp_arg.cpp new file mode 100644 index 0000000..5a4c8fc --- /dev/null +++ b/clang/test/SemaTemplate/temp_arg.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, + int I, + template<typename> class TT> + class A; // expected-note 3 {{template is declared here}} + +template<typename> class X; + +A<int, 0, X> * a1; + +A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}} +A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}} +A a3; // expected-error{{use of class template A requires template arguments}} + +namespace test0 { + template <class t> class foo {}; + template <class t> class bar { + bar(::test0::foo<tee> *ptr) {} // FIXME(redundant): expected-error 2 {{use of undeclared identifier 'tee'}} + }; +} diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp new file mode 100644 index 0000000..747ddcc --- /dev/null +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -0,0 +1,325 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wconversion -verify %s +template<int N> struct A; // expected-note 5{{template parameter is declared here}} + +A<0> *a0; + +A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int ()'}} + +A<int> *a2; // expected-error{{template argument for non-type template parameter must be an expression}} + +A<1 >> 2> *a3; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++11}} + +// C++ [temp.arg.nontype]p5: +A<A> *a4; // expected-error{{must be an expression}} + +enum E { Enumerator = 17 }; +A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}} +template<E Value> struct A1; // expected-note{{template parameter is declared here}} +A1<Enumerator> *a6; // okay +A1<17> *a7; // expected-error{{non-type template argument of type 'int' cannot be converted to a value of type 'E'}} + +const long LongValue = 12345678; +A<LongValue> *a8; +const short ShortValue = 17; +A<ShortValue> *a9; + +int f(int); +A<f(17)> *a10; // expected-error{{non-type template argument of type 'int' is not an integral constant expression}} + +class X { +public: + X(); + X(int, int); + operator int() const; +}; +A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'X' must have an integral or enumeration type}} + +float f(float); + +float g(float); // expected-note 2{{candidate function}} +double g(double); // expected-note 2{{candidate function}} + +int h(int); +float h2(float); + +template<int fp(int)> struct A3; // expected-note 1{{template parameter is declared here}} +A3<h> *a14_1; +A3<&h> *a14_2; +A3<f> *a14_3; +A3<&f> *a14_4; +A3<h2> *a14_6; // expected-error{{non-type template argument of type 'float (float)' cannot be converted to a value of type 'int (*)(int)'}} +A3<g> *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}} + + +struct Y { } y; + +volatile X * X_volatile_ptr; +template<X const &AnX> struct A4; // expected-note 2{{template parameter is declared here}} +X an_X; +A4<an_X> *a15_1; // okay +A4<*X_volatile_ptr> *a15_2; // expected-error{{non-type template argument does not refer to any declaration}} +A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'const X &' cannot bind to template argument of type 'struct Y'}} \ + // FIXME: expected-error{{expected unqualified-id}} + +template<int (&fr)(int)> struct A5; // expected-note{{template parameter is declared here}} +A5<h> *a16_1; +A5<f> *a16_3; +A5<h2> *a16_6; // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'float (float)'}} +A5<g> *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}} + +struct Z { + int foo(int); + float bar(float); + int bar(int); + double baz(double); + + int int_member; + float float_member; +}; +template<int (Z::*pmf)(int)> struct A6; // expected-note{{template parameter is declared here}} +A6<&Z::foo> *a17_1; +A6<&Z::bar> *a17_2; +A6<&Z::baz> *a17_3; // expected-error{{non-type template argument of type 'double (Z::*)(double)' cannot be converted to a value of type 'int (Z::*)(int)'}} + + +template<int Z::*pm> struct A7; // expected-note{{template parameter is declared here}} +template<int Z::*pm> struct A7c; +A7<&Z::int_member> *a18_1; +A7c<&Z::int_member> *a18_2; +A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float Z::*' cannot be converted to a value of type 'int Z::*'}} +A7c<(&Z::int_member)> *a18_4; // expected-warning{{address non-type template argument cannot be surrounded by parentheses}} + +template<unsigned char C> struct Overflow; // expected-note{{template parameter is declared here}} + +Overflow<5> *overflow1; // okay +Overflow<255> *overflow2; // okay +Overflow<256> *overflow3; // expected-warning{{non-type template argument value '256' truncated to '0' for template parameter of type 'unsigned char'}} + + +template<unsigned> struct Signedness; // expected-note{{template parameter is declared here}} +Signedness<10> *signedness1; // okay +Signedness<-10> *signedness2; // expected-warning{{non-type template argument with value '-10' converted to '4294967286' for unsigned template parameter of type 'unsigned int'}} + +template<signed char C> struct SignedOverflow; // expected-note 3 {{template parameter is declared here}} +SignedOverflow<1> *signedoverflow1; +SignedOverflow<-1> *signedoverflow2; +SignedOverflow<-128> *signedoverflow3; +SignedOverflow<-129> *signedoverflow4; // expected-warning{{non-type template argument value '-129' truncated to '127' for template parameter of type 'signed char'}} +SignedOverflow<127> *signedoverflow5; +SignedOverflow<128> *signedoverflow6; // expected-warning{{non-type template argument value '128' truncated to '-128' for template parameter of type 'signed char'}} +SignedOverflow<(unsigned char)128> *signedoverflow7; // expected-warning{{non-type template argument value '128' truncated to '-128' for template parameter of type 'signed char'}} + +// Check canonicalization of template arguments. +template<int (*)(int, int)> struct FuncPtr0; +int func0(int, int); +extern FuncPtr0<&func0> *fp0; +template<int (*)(int, int)> struct FuncPtr0; +extern FuncPtr0<&func0> *fp0; +int func0(int, int); +extern FuncPtr0<&func0> *fp0; + +// PR5350 +namespace ns { + template <typename T> + struct Foo { + static const bool value = true; + }; + + template <bool b> + struct Bar {}; + + const bool value = false; + + Bar<bool(ns::Foo<int>::value)> x; +} + +// PR5349 +namespace ns { + enum E { k }; + + template <E e> + struct Baz {}; + + Baz<k> f1; // This works. + Baz<E(0)> f2; // This too. + Baz<static_cast<E>(0)> f3; // And this. + + Baz<ns::E(0)> b1; // This doesn't work. + Baz<static_cast<ns::E>(0)> b2; // This neither. +} + +// PR5597 +template<int (*)(float)> struct X0 { }; + +struct X1 { + static int pfunc(float); +}; +void test_X0_X1() { + X0<X1::pfunc> x01; +} + +// PR6249 +namespace pr6249 { + template<typename T, T (*func)()> T f() { + return func(); + } + + int h(); + template int f<int, h>(); +} + +namespace PR6723 { + template<unsigned char C> void f(int (&a)[C]); // expected-note {{candidate template ignored}} \ + // expected-note{{substitution failure [with C = '\x00']}} + void g() { + int arr512[512]; + f(arr512); // expected-error{{no matching function for call}} + f<512>(arr512); // expected-error{{no matching function for call}} + } +} + +// Check that we instantiate declarations whose addresses are taken +// for non-type template arguments. +namespace EntityReferenced { + template<typename T, void (*)(T)> struct X { }; + + template<typename T> + struct Y { + static void f(T x) { + x = 1; // expected-error{{assigning to 'int *' from incompatible type 'int'}} + } + }; + + void g() { + typedef X<int*, Y<int*>::f> x; // expected-note{{in instantiation of}} + } +} + +namespace PR6964 { + template <typename ,int, int = 9223372036854775807L > // expected-warning 2{{non-type template argument value '9223372036854775807' truncated to '-1' for template parameter of type 'int'}} \ + // expected-note 2{{template parameter is declared here}} + struct as_nview { }; + + template <typename Sequence, int I0> + struct as_nview<Sequence, I0> // expected-note{{while checking a default template argument used here}} + { }; +} + +// rdar://problem/8302138 +namespace test8 { + template <int* ip> struct A { + int* p; + A() : p(ip) {} + }; + + void test0() { + extern int i00; + A<&i00> a00; + } + + extern int i01; + void test1() { + A<&i01> a01; + } + + + struct C { + int x; + char y; + double z; + }; + + template <C* cp> struct B { + C* p; + B() : p(cp) {} + }; + + void test2() { + extern C c02; + B<&c02> b02; + } + + extern C c03; + void test3() { + B<&c03> b03; + } +} + +namespace PR8372 { + template <int I> void foo() { } // expected-note{{template parameter is declared here}} + void bar() { foo <0x80000000> (); } // expected-warning{{non-type template argument value '2147483648' truncated to '-2147483648' for template parameter of type 'int'}} +} + +namespace PR9227 { + template <bool B> struct enable_if_bool { }; + template <> struct enable_if_bool<true> { typedef int type; }; + void test_bool() { enable_if_bool<false>::type i; } // expected-error{{enable_if_bool<false>}} + + template <char C> struct enable_if_char { }; + template <> struct enable_if_char<'a'> { typedef int type; }; + void test_char_0() { enable_if_char<0>::type i; } // expected-error{{enable_if_char<'\x00'>}} + void test_char_b() { enable_if_char<'b'>::type i; } // expected-error{{enable_if_char<'b'>}} + void test_char_possibly_negative() { enable_if_char<'\x02'>::type i; } // expected-error{{enable_if_char<'\x02'>}} + void test_char_single_quote() { enable_if_char<'\''>::type i; } // expected-error{{enable_if_char<'\''>}} + void test_char_backslash() { enable_if_char<'\\'>::type i; } // expected-error{{enable_if_char<'\\'>}} +} + +namespace PR10579 { + namespace fcppt + { + namespace container + { + namespace bitfield + { + + template< + typename Enum, + Enum Size + > + class basic; + + template< + typename Enum, + Enum Size + > + class basic + { + public: + basic() + { + } + }; + + } + } + } + + namespace + { + + namespace testenum + { + enum type + { + foo, + bar, + size + }; + } + + } + + int main() + { + typedef fcppt::container::bitfield::basic< + testenum::type, + testenum::size + > bitfield_foo; + + bitfield_foo obj; + } + +} + +template <int& I> struct PR10766 { static int *ip; }; +template <int& I> int* PR10766<I>::ip = &I; diff --git a/clang/test/SemaTemplate/temp_arg_template.cpp b/clang/test/SemaTemplate/temp_arg_template.cpp new file mode 100644 index 0000000..c9ce1b6 --- /dev/null +++ b/clang/test/SemaTemplate/temp_arg_template.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<template<typename T> class X> struct A; // expected-note 2{{previous template template parameter is here}} + +template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}} + +template<template<int I> class X> struct C; // expected-note{{previous non-type template parameter with type 'int' is here}} + +template<class> struct X; // expected-note{{too few template parameters in template template argument}} +template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}} +template<long N> struct Ylong; // expected-note{{template non-type parameter has a different type 'long' in template argument}} + +namespace N { + template<class> struct Z; +} +template<class, class> struct TooMany; // expected-note{{too many template parameters in template template argument}} + + +A<X> *a1; +A<N::Z> *a2; +A< ::N::Z> *a3; + +A<Y> *a4; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} +A<TooMany> *a5; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} +B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} +C<Y> *a7; +C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + +template<typename T> void f(int); + +A<f> *a9; // expected-error{{must be a class template}} + +// Evil digraph '<:' is parsed as '[', expect error. +A<::N::Z> *a10; // expected-error{{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} + +// Do not do a digraph correction here. +A<: :N::Z> *a11; // expected-error{{expected expression}} \ + expected-error{{C++ requires a type specifier for all declarations}} + +// PR7807 +namespace N { + template <typename, typename = int> + struct X + { }; + + template <typename ,int> + struct Y + { X<int> const_ref(); }; + + template <template<typename,int> class TT, typename T, int N> + int operator<<(int, TT<T, N> a) { // expected-note{{candidate template ignored}} + 0 << a.const_ref(); // expected-error{{invalid operands to binary expression ('int' and 'X<int>')}} + } + + void f0( Y<int,1> y){ 1 << y; } // expected-note{{in instantiation of function template specialization 'N::operator<<<Y, int, 1>' requested here}} +} + +// PR12179 +template <typename Primitive, template <Primitive...> class F> // expected-warning {{variadic templates are a C++11 extension}} +struct unbox_args { + typedef typename Primitive::template call<F> x; +}; diff --git a/clang/test/SemaTemplate/temp_arg_type.cpp b/clang/test/SemaTemplate/temp_arg_type.cpp new file mode 100644 index 0000000..3970942 --- /dev/null +++ b/clang/test/SemaTemplate/temp_arg_type.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}} + +// [temp.arg.type]p1 +A<0> *a1; // expected-error{{template argument for template type parameter must be a type}} + +A<A> *a2; // expected-error{{use of class template A requires template arguments}} + +A<int> *a3; +A<int()> *a4; +A<int(float)> *a5; +A<A<int> > *a6; + +// Pass an overloaded function template: +template<typename T> void function_tpl(T); +A<function_tpl> a7; // expected-error{{template argument for template type parameter must be a type}} + +// Pass a qualified name: +namespace ns { +template<typename T> class B {}; // expected-note{{template is declared here}} +} +A<ns::B> a8; // expected-error{{use of class template ns::B requires template arguments}} + +// [temp.arg.type]p2 +void f() { + class X { }; + A<X> * a = 0; // expected-warning{{template argument uses local type 'X'}} +} + +struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}} +A<__typeof__(Unnamed)> *a9; // expected-warning{{template argument uses unnamed type}} + +template<typename T, unsigned N> +struct Array { + typedef struct { T x[N]; } type; +}; + +template<typename T> struct A1 { }; +A1<Array<int, 17>::type> ax; + +// FIXME: [temp.arg.type]p3. The check doesn't really belong here (it +// belongs somewhere in the template instantiation section). diff --git a/clang/test/SemaTemplate/temp_class_order.cpp b/clang/test/SemaTemplate/temp_class_order.cpp new file mode 100644 index 0000000..fcf0325 --- /dev/null +++ b/clang/test/SemaTemplate/temp_class_order.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -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/clang/test/SemaTemplate/temp_class_spec.cpp b/clang/test/SemaTemplate/temp_class_spec.cpp new file mode 100644 index 0000000..8a07fd7 --- /dev/null +++ b/clang/test/SemaTemplate/temp_class_spec.cpp @@ -0,0 +1,363 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +struct is_pointer { + static const bool value = false; +}; + +template<typename T> +struct is_pointer<T*> { + static const bool value = true; +}; + +template<typename T> +struct is_pointer<const T*> { + static const bool value = true; +}; + +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]; + +template<typename T> +struct is_lvalue_reference { + static const bool value = false; +}; + +template<typename T> +struct is_lvalue_reference<T&> { + static const bool value = true; +}; + +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; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +typedef int INT; +typedef INT* int_ptr; + +int is_same0[is_same<int, int>::value? 1 : -1]; +int is_same1[is_same<int, INT>::value? 1 : -1]; +int is_same2[is_same<const int, int>::value? -1 : 1]; +int is_same3[is_same<int_ptr, int>::value? -1 : 1]; + +template<typename T> +struct remove_reference { + typedef T type; +}; + +template<typename T> +struct remove_reference<T&> { + typedef T type; +}; + +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; +}; + +template<typename T> +struct is_incomplete_array<T[]> { + static const bool value = true; +}; + +int incomplete_array0[is_incomplete_array<int>::value ? -1 : 1]; +int incomplete_array1[is_incomplete_array<int[1]>::value ? -1 : 1]; +int incomplete_array2[is_incomplete_array<bool[]>::value ? 1 : -1]; +int incomplete_array3[is_incomplete_array<int[]>::value ? 1 : -1]; + +template<typename T> +struct is_array_with_4_elements { + static const bool value = false; +}; + +template<typename T> +struct is_array_with_4_elements<T[4]> { + static const bool value = true; +}; + +int array_with_4_elements0[is_array_with_4_elements<int[]>::value ? -1 : 1]; +int array_with_4_elements1[is_array_with_4_elements<int[1]>::value ? -1 : 1]; +int array_with_4_elements2[is_array_with_4_elements<int[4]>::value ? 1 : -1]; +int array_with_4_elements3[is_array_with_4_elements<int[4][2]>::value ? 1 : -1]; + +template<typename T> +struct get_array_size; + +template<typename T, unsigned N> +struct get_array_size<T[N]> { + static const unsigned value = 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; +}; + +template<typename T, typename U> +struct is_unary_function<T (*)(U)> { + static const bool value = true; +}; + +int is_unary_function0[is_unary_function<int>::value ? -1 : 1]; +int is_unary_function1[is_unary_function<int (*)()>::value ? -1 : 1]; +int is_unary_function2[is_unary_function<int (*)(int, bool)>::value ? -1 : 1]; +int is_unary_function3[is_unary_function<int (*)(bool)>::value ? 1 : -1]; +int is_unary_function4[is_unary_function<int (*)(int)>::value ? 1 : -1]; + +template<typename T> +struct is_unary_function_with_same_return_type_as_argument_type { + static const bool value = false; +}; + +template<typename T> +struct is_unary_function_with_same_return_type_as_argument_type<T (*)(T)> { + static const bool value = true; +}; + +int is_unary_function5[is_unary_function_with_same_return_type_as_argument_type<int>::value ? -1 : 1]; +int is_unary_function6[is_unary_function_with_same_return_type_as_argument_type<int (*)()>::value ? -1 : 1]; +int is_unary_function7[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, bool)>::value ? -1 : 1]; +int is_unary_function8[is_unary_function_with_same_return_type_as_argument_type<int (*)(bool)>::value ? -1 : 1]; +int is_unary_function9[is_unary_function_with_same_return_type_as_argument_type<int (*)(int)>::value ? 1 : -1]; +int is_unary_function10[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, ...)>::value ? -1 : 1]; +int is_unary_function11[is_unary_function_with_same_return_type_as_argument_type<int (* const)(int)>::value ? -1 : 1]; + +template<typename T> +struct is_binary_function { + static const bool value = false; +}; + +template<typename R, typename T1, typename T2> +struct is_binary_function<R(T1, T2)> { + static const bool value = true; +}; + +int is_binary_function0[is_binary_function<int(float, double)>::value? 1 : -1]; + +template<typename T> +struct is_member_pointer { + static const bool value = false; +}; + +template<typename T, typename Class> +struct is_member_pointer<T Class::*> { + static const bool value = true; +}; + +struct X { }; + +int is_member_pointer0[is_member_pointer<int X::*>::value? 1 : -1]; +int is_member_pointer1[is_member_pointer<const int X::*>::value? 1 : -1]; +int is_member_pointer2[is_member_pointer<int (X::*)()>::value? 1 : -1]; +int is_member_pointer3[is_member_pointer<int (X::*)(int) const>::value? 1 : -1]; +int is_member_pointer4[is_member_pointer<int (X::**)(int) const>::value? -1 : 1]; +int is_member_pointer5[is_member_pointer<int>::value? -1 : 1]; + +template<typename T> +struct is_member_function_pointer { + static const bool value = false; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)()> { + static const bool value = true; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)() const> { + static const bool value = true; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)() volatile> { + static const bool value = true; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)() const volatile> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1)> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1) const> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1) volatile> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1) const volatile> { + static const bool value = true; +}; + +int is_member_function_pointer0[ + is_member_function_pointer<int X::*>::value? -1 : 1]; +int is_member_function_pointer1[ + is_member_function_pointer<int (X::*)()>::value? 1 : -1]; +int is_member_function_pointer2[ + is_member_function_pointer<X (X::*)(X&)>::value? 1 : -1]; +int is_member_function_pointer3[ + is_member_function_pointer<int (X::*)() const>::value? 1 : -1]; +int is_member_function_pointer4[ + is_member_function_pointer<int (X::*)(float) const>::value? 1 : -1]; + +// Test substitution of non-dependent arguments back into the template +// argument list of the class template partial specialization. +template<typename T, typename ValueType = T> +struct is_nested_value_type_identity { + static const bool value = false; +}; + +template<typename T> +struct is_nested_value_type_identity<T, typename T::value_type> { + static const bool value = true; +}; + +template<typename T> +struct HasValueType { + typedef T value_type; +}; + +struct HasIdentityValueType { + typedef HasIdentityValueType value_type; +}; + +struct NoValueType { }; + +int is_nested_value_type_identity0[ + is_nested_value_type_identity<HasValueType<int> >::value? -1 : 1]; +int is_nested_value_type_identity1[ + is_nested_value_type_identity<HasIdentityValueType>::value? 1 : -1]; +int is_nested_value_type_identity2[ + is_nested_value_type_identity<NoValueType>::value? -1 : 1]; + + +// C++ [temp.class.spec]p4: +template<class T1, class T2, int I> class A { }; //#1 +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}} + +namespace PR6025 { + template< int N > struct A; + + namespace N + { + template< typename F > + struct B; + } + + template< typename Protect, typename Second > + struct C; + + template <class T> + struct C< T, A< N::B<T>::value > > + { + }; +} + +namespace PR6181 { + template <class T> + class a; + + class s; + + template <class U> + class a<s> // expected-error{{partial specialization of 'a' does not use any of its template parameters}} + { + }; + +} diff --git a/clang/test/SemaTemplate/temp_class_spec_blocks.cpp b/clang/test/SemaTemplate/temp_class_spec_blocks.cpp new file mode 100644 index 0000000..b7b96df --- /dev/null +++ b/clang/test/SemaTemplate/temp_class_spec_blocks.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks +template<typename T> +struct is_unary_block { + static const bool value = false; +}; + +template<typename T, typename U> +struct is_unary_block<T (^)(U)> { + static const bool value = true; +}; + +int is_unary_block0[is_unary_block<int>::value ? -1 : 1]; +int is_unary_block1[is_unary_block<int (^)()>::value ? -1 : 1]; +int is_unary_block2[is_unary_block<int (^)(int, bool)>::value ? -1 : 1]; +int is_unary_block3[is_unary_block<int (^)(bool)>::value ? 1 : -1]; +int is_unary_block4[is_unary_block<int (^)(int)>::value ? 1 : -1]; + +template<typename T> +struct is_unary_block_with_same_return_type_as_argument_type { + static const bool value = false; +}; + +template<typename T> +struct is_unary_block_with_same_return_type_as_argument_type<T (^)(T)> { + static const bool value = true; +}; + +int is_unary_block5[is_unary_block_with_same_return_type_as_argument_type<int>::value ? -1 : 1]; +int is_unary_block6[is_unary_block_with_same_return_type_as_argument_type<int (^)()>::value ? -1 : 1]; +int is_unary_block7[is_unary_block_with_same_return_type_as_argument_type<int (^)(int, bool)>::value ? -1 : 1]; +int is_unary_block8[is_unary_block_with_same_return_type_as_argument_type<int (^)(bool)>::value ? -1 : 1]; +int is_unary_block9[is_unary_block_with_same_return_type_as_argument_type<int (^)(int)>::value ? 1 : -1]; +int is_unary_block10[is_unary_block_with_same_return_type_as_argument_type<int (^)(int, ...)>::value ? -1 : 1]; +int is_unary_block11[is_unary_block_with_same_return_type_as_argument_type<int (^ const)(int)>::value ? -1 : 1]; diff --git a/clang/test/SemaTemplate/temp_class_spec_neg.cpp b/clang/test/SemaTemplate/temp_class_spec_neg.cpp new file mode 100644 index 0000000..be5fbb1 --- /dev/null +++ b/clang/test/SemaTemplate/temp_class_spec_neg.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> struct vector; + +// C++ [temp.class.spec]p6: +namespace N { + namespace M { + template<typename T> struct A; // expected-note{{here}} + } +} + +template<typename T> +struct N::M::A<T*> { }; // expected-warning{{C++11 extension}} + +// C++ [temp.class.spec]p9 +// bullet 1 +template <int I, int J> struct A {}; +template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}} +template <int I, int J> struct B {}; +template <int I> struct B<I, I> {}; //OK + +// bullet 2 +template <class T, T t> struct C {}; // expected-note{{declared here}} +template <class T> struct C<T, 1>; // expected-error{{specializes}} +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<typename T, int N, template<typename X> class TT> +struct Test0; + +// bullet 3 +template<typename T, int N, template<typename X> class TT> +struct Test0<T, N, TT>; // expected-error{{does not specialize}} + +// C++ [temp.class.spec]p10 +template<typename T = int, // expected-error{{default template argument}} + int N = 17, // expected-error{{default template argument}} + template<typename X> class TT = ::vector> // expected-error{{default template argument}} + struct Test0<T*, N, TT> { }; + +template<typename T> struct Test1; +template<typename T, typename U> // expected-note{{non-deducible}} + struct Test1<T*> { }; // expected-warning{{never be used}} diff --git a/clang/test/SemaTemplate/temp_explicit.cpp b/clang/test/SemaTemplate/temp_explicit.cpp new file mode 100644 index 0000000..80c90d0 --- /dev/null +++ b/clang/test/SemaTemplate/temp_explicit.cpp @@ -0,0 +1,151 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s +// +// Tests explicit instantiation of templates. +template<typename T, typename U = T> class X0 { }; + +namespace N { + template<typename T, typename U = T> class X1 { }; +} + +// Check the syntax of explicit instantiations. +template class X0<int, float>; +template class X0<int>; // expected-note{{previous}} + +template class N::X1<int>; +template class ::N::X1<int, float>; + +using namespace N; + +// Check for some bogus syntax that probably means that the user +// wanted to write an explicit specialization, but forgot the '<>' +// after 'template'. +template class X0<double> { }; // expected-error{{explicit specialization}} + +// Check for explicit instantiations that come after other kinds of +// instantiations or declarations. +template class X0<int, int>; // expected-error{{duplicate}} + +template<> class X0<char> { }; // expected-note{{previous}} +template class X0<char>; // expected-warning{{ignored}} + +void foo(X0<short>) { } +template class X0<short>; + +// Check that explicit instantiations actually produce definitions. We +// determine whether this happens by placing semantic errors in the +// definition of the template we're instantiating. +template<typename T> struct X2; // expected-note{{declared here}} + +template struct X2<float>; // expected-error{{undefined template}} + +template<typename T> +struct X2 { + void f0(T*); // expected-error{{pointer to a reference}} +}; + +template struct X2<int>; // okay +template struct X2<int&>; // expected-note{{in instantiation of}} + +// Check that explicit instantiations instantiate member classes. +template<typename T> struct X3 { + struct Inner { + void f(T*); // expected-error{{pointer to a reference}} + }; +}; + +void f1(X3<int&>); // okay, Inner, not instantiated + +template struct X3<int&>; // expected-note{{instantiation}} + +template<typename T> struct X4 { + struct Inner { + struct VeryInner { + void f(T*); // expected-error 2{{pointer to a reference}} + }; + }; +}; + +void f2(X4<int&>); // okay, Inner, not instantiated +void f3(X4<int&>::Inner); // okay, Inner::VeryInner, not instantiated + +template struct X4<int&>; // expected-note{{instantiation}} +template struct X4<float&>; // expected-note{{instantiation}} + +// Check explicit instantiation of member classes +namespace N2 { + +template<typename T> +struct X5 { + struct Inner1 { + void f(T&); + }; + + struct Inner2 { // expected-note {{here}} + struct VeryInner { + void g(T*); // expected-error 2{{pointer to a reference}} + }; + }; +}; + +} + +template struct N2::X5<void>::Inner2; + +using namespace N2; +template struct X5<int&>::Inner2; // expected-note{{instantiation}} + +void f4(X5<float&>::Inner2); +template struct X5<float&>::Inner2; // expected-note{{instantiation}} + +namespace N3 { + template struct N2::X5<int>::Inner2; // expected-warning {{explicit instantiation of 'Inner2' not in a namespace enclosing 'N2'}} +} + +struct X6 { + struct Inner { // expected-note{{here}} + void f(); + }; +}; + +template struct X6::Inner; // expected-error{{non-templated}} + +// PR5559 +template <typename T> +struct Foo; + +template <> +struct Foo<int> // expected-note{{header not required for explicitly-specialized}} +{ + template <typename U> + struct Bar + {}; +}; + +template <> // expected-warning{{extraneous template parameter list}} +template <> +struct Foo<int>::Bar<void> +{}; + +namespace N1 { + + template<typename T> struct X7 { }; // expected-note{{here}} + + namespace Inner { + template<typename T> struct X8 { }; + } + + template struct X7<int>; + template struct Inner::X8<int>; +} + +template<typename T> struct X9 { }; // expected-note{{here}} + +template struct ::N1::Inner::X8<float>; + +namespace N2 { + using namespace N1; + + template struct X7<double>; // expected-warning{{must occur in namespace}} + + template struct X9<float>; // expected-warning{{must occur at global scope}} +} diff --git a/clang/test/SemaTemplate/temp_explicit_cxx0x.cpp b/clang/test/SemaTemplate/temp_explicit_cxx0x.cpp new file mode 100644 index 0000000..e37fcd7 --- /dev/null +++ b/clang/test/SemaTemplate/temp_explicit_cxx0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +namespace N1 { + + template<typename T> struct X0 { }; // expected-note{{here}} + + namespace Inner { + template<typename T> struct X1 { }; + } + + template struct X0<int>; + template struct Inner::X1<int>; +} + +template<typename T> struct X2 { }; // expected-note{{here}} + +template struct ::N1::Inner::X1<float>; + +namespace N2 { + using namespace N1; + + template struct X0<double>; // expected-error{{must occur in namespace 'N1'}} + + template struct X2<float>; // expected-error{{at global scope}} +} diff --git a/clang/test/SemaTemplate/temp_func_order.cpp b/clang/test/SemaTemplate/temp_func_order.cpp new file mode 100644 index 0000000..908354b --- /dev/null +++ b/clang/test/SemaTemplate/temp_func_order.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -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/clang/test/SemaTemplate/template-class-traits.cpp b/clang/test/SemaTemplate/template-class-traits.cpp new file mode 100644 index 0000000..4710294 --- /dev/null +++ b/clang/test/SemaTemplate/template-class-traits.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +#define T(b) (b) ? 1 : -1 +#define F(b) (b) ? -1 : 1 + +struct HasVirt { virtual void a(); }; +template<class T> struct InheritPolymorph : HasVirt {}; +int t01[T(__is_polymorphic(InheritPolymorph<int>))]; + diff --git a/clang/test/SemaTemplate/template-decl-fail.cpp b/clang/test/SemaTemplate/template-decl-fail.cpp new file mode 100644 index 0000000..ad134cd --- /dev/null +++ b/clang/test/SemaTemplate/template-decl-fail.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> typedef T X; // expected-error{{typedef cannot be a template}} + +template<typename T> +enum t0 { A = T::x }; // expected-error{{enumeration cannot be a template}} \ + // expected-warning{{declaration does not declare anything}} + +enum e0 {}; +template<int x> enum e0 f0(int a=x) {} diff --git a/clang/test/SemaTemplate/template-id-expr.cpp b/clang/test/SemaTemplate/template-id-expr.cpp new file mode 100644 index 0000000..4416f92 --- /dev/null +++ b/clang/test/SemaTemplate/template-id-expr.cpp @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR5336 +template<typename FromCl> +struct isa_impl_cl { + template<class ToCl> + static void isa(const FromCl &Val) { } +}; + +template<class X, class Y> +void isa(const Y &Val) { return isa_impl_cl<Y>::template isa<X>(Val); } + +class Value; +void f0(const Value &Val) { isa<Value>(Val); } + +// Implicit template-ids. +template<typename T> +struct X0 { + template<typename U> + void f1(); + + template<typename U> + void f2(U) { + f1<U>(); + } +}; + +void test_X0_int(X0<int> xi, float f) { + xi.f2(f); +} + +// Not template-id expressions, but they almost look like it. +template<typename F> +struct Y { + Y(const F&); +}; + +template<int I> +struct X { + X(int, int); + void f() { + Y<X<I> >(X<I>(0, 0)); + Y<X<I> >(::X<I>(0, 0)); + } +}; + +template struct X<3>; + +// 'template' as a disambiguator. +// PR7030 +struct Y0 { + template<typename U> + void f1(U); + + template<typename U> + static void f2(U); + + void f3(int); + + static int f4(int); + template<typename U> + static void f4(U); + + template<typename U> + void f() { + Y0::template f1<U>(0); + Y0::template f1(0); + this->template f1(0); + + Y0::template f2<U>(0); + Y0::template f2(0); + + Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} + Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} + + int x; + x = Y0::f4(0); + x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} + x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} + + x = this->f4(0); + x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} + x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} + } +}; + +struct A { + template<int I> + struct B { + static void b1(); + }; +}; + +template<int I> +void f5() { + A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}} +} + +template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}} diff --git a/clang/test/SemaTemplate/template-id-printing.cpp b/clang/test/SemaTemplate/template-id-printing.cpp new file mode 100644 index 0000000..047589b --- /dev/null +++ b/clang/test/SemaTemplate/template-id-printing.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-print %s | FileCheck %s +namespace N { + template<typename T, typename U> void f(U); + template<int> void f(); +} + +void g() { + // CHECK: N::f<int>(3.14 + N::f<int>(3.14); + + // CHECK: N::f<double> + void (*fp)(int) = N::f<double>; +} + + +// (NNS qualified) DeclRefExpr. +namespace DRE { + +template <typename T> +void foo(); + +void test() { + // CHECK: DRE::foo<int>; + DRE::foo<int>; + // CHECK: DRE::template foo<int>; + DRE::template foo<int>; + // CHECK: DRE::foo<int>(); + DRE::foo<int>(); + // CHECK: DRE::template foo<int>(); + DRE::template foo<int>(); +} + +} // namespace DRE + + +// MemberExpr. +namespace ME { + +struct S { + template <typename T> + void mem(); +}; + +void test() { + S s; + // CHECK: s.mem<int>(); + s.mem<int>(); + // CHECK: s.template mem<int>(); + s.template mem<int>(); +} + +} // namespace ME + + +// UnresolvedLookupExpr. +namespace ULE { + +template <typename T> +int foo(); + +template <typename T> +void test() { + // CHECK: ULE::foo<T>; + ULE::foo<T>; + // CHECK: ULE::template foo<T>; + ULE::template foo<T>; +} + +} // namespace ULE + + +// UnresolvedMemberExpr. +namespace UME { + +struct S { + template <typename T> + void mem(); +}; + +template <typename U> +void test() { + S s; + // CHECK: s.mem<U>(); + s.mem<U>(); + // CHECK: s.template mem<U>(); + s.template mem<U>(); +} + +} // namespace UME + + +// DependentScopeDeclRefExpr. +namespace DSDRE { + +template <typename T> +struct S; + +template <typename T> +void test() { + // CHECK: S<T>::foo; + S<T>::foo; + // CHECK: S<T>::template foo; + S<T>::template foo; + // CHECK: S<T>::template foo<>; + S<T>::template foo<>; + // CHECK: S<T>::template foo<T>; + S<T>::template foo<T>; +} + +} // namespace DSDRE + + +// DependentScopeMemberExpr. +namespace DSME { + +template <typename T> +struct S; + +template <typename T> +void test() { + S<T> s; + // CHECK: s.foo; + s.foo; + // CHECK: s.template foo; + s.template foo; + // CHECK: s.template foo<>; + s.template foo<>; + // CHECK: s.template foo<T>; + s.template foo<T>; +} + +} // namespace DSME + +namespace DSDRE_withImplicitTemplateArgs { + +template <typename T> void foo() { + // CHECK: T::template bar(); + T::template bar(); +} + +} // namespace DSDRE_withImplicitTemplateArgs diff --git a/clang/test/SemaTemplate/typename-specifier-2.cpp b/clang/test/SemaTemplate/typename-specifier-2.cpp new file mode 100644 index 0000000..551cac3 --- /dev/null +++ b/clang/test/SemaTemplate/typename-specifier-2.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename MetaFun, typename T> +struct bind_metafun { + typedef typename MetaFun::template apply<T> type; +}; + +struct add_pointer { + template<typename T> + struct apply { + typedef T* type; + }; +}; + +int i; +// FIXME: if we make the declarator below a pointer (e.g., with *ip), +// the error message isn't so good because we don't get the handy +// 'aka' telling us that we're dealing with an int**. Should we fix +// getDesugaredType to dig through pointers and such? +bind_metafun<add_pointer, int>::type::type ip = &i; +bind_metafun<add_pointer, float>::type::type fp = &i; // expected-error{{cannot initialize a variable of type 'bind_metafun<add_pointer, float>::type::type' (aka 'float *') with an rvalue of type 'int *'}} + + +template<typename T> +struct extract_type_type { + typedef typename T::type::type t; +}; + +double d; +extract_type_type<bind_metafun<add_pointer, double> >::t dp = &d; diff --git a/clang/test/SemaTemplate/typename-specifier-3.cpp b/clang/test/SemaTemplate/typename-specifier-3.cpp new file mode 100644 index 0000000..a463d88 --- /dev/null +++ b/clang/test/SemaTemplate/typename-specifier-3.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR4364 +template<class T> struct a { + T b() { + return typename T::x(); + } +}; +struct B { + typedef B x; +}; +B c() { + a<B> x; + return x.b(); +} + +// Some extra tests for invalid cases +template<class T> struct test2 { T b() { return typename T::a; } }; // expected-error{{expected '(' for function-style cast or type construction}} +template<class T> struct test3 { T b() { return typename a; } }; // expected-error{{expected a qualified name after 'typename'}} diff --git a/clang/test/SemaTemplate/typename-specifier-4.cpp b/clang/test/SemaTemplate/typename-specifier-4.cpp new file mode 100644 index 0000000..44cf966 --- /dev/null +++ b/clang/test/SemaTemplate/typename-specifier-4.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -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>, // expected-warning{{'template' keyword outside of a template}} \ + // expected-warning{{'typename' occurs outside of a template}} + 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}} +}; + +namespace PR6236 { + template<typename T, typename U> struct S { }; + + template<typename T> struct S<T, T> { + template<typename U> struct K { }; + + void f() { + typedef typename S<T, T>::template K<T> Foo; + } + }; +} + +namespace PR6268 { + template <typename T> + struct Outer { + template <typename U> + struct Inner {}; + + template <typename U> + typename Outer<T>::template Inner<U> + foo(typename Outer<T>::template Inner<U>); + }; + + template <typename T> + template <typename U> + typename Outer<T>::template Inner<U> + Outer<T>::foo(typename Outer<T>::template Inner<U>) { + return Inner<U>(); + } +} + +namespace PR6463 { + struct B { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}} + struct C { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}} + + template<typename T> + struct A : B, C { + type& a(); // expected-error{{found in multiple base classes}} + int x; + }; + + // FIXME: Improve source location info here. + template<typename T> + typename A<T>::type& A<T>::a() { // expected-error{{found in multiple base classes}} + return x; + } +} + +namespace PR7419 { + template <typename T> struct S { + typedef typename T::Y T2; + typedef typename T2::Z T3; + typedef typename T3::W T4; + T4 *f(); + + typedef typename T::template Y<int> TT2; + typedef typename TT2::template Z<float> TT3; + typedef typename TT3::template W<double> TT4; + TT4 g(); + }; + + template <typename T> typename T::Y::Z::W *S<T>::f() { } + template <typename T> typename T::template Y<int>::template Z<float>::template W<double> S<T>::g() { } +} + +namespace rdar8740998 { + template<typename T> + struct X : public T { + using T::iterator; // expected-note{{add 'typename' to treat this using declaration as a type}} \ + // expected-error{{dependent using declaration resolved to type without 'typename'}} + + void f() { + typename X<T>::iterator i; // expected-error{{typename specifier refers to a dependent using declaration for a value 'iterator' in 'X<T>'}} + } + }; + + struct HasIterator { + typedef int *iterator; // expected-note{{target of using declaration}} + }; + + void test_X(X<HasIterator> xi) { // expected-note{{in instantiation of template class}} + xi.f(); + } +} + +namespace rdar9068589 { + // From GCC PR c++/13950 + template <class T> struct Base {}; + template <class T> struct Derived: public Base<T> { + typename Derived::template Base<double>* p1; + }; +} diff --git a/clang/test/SemaTemplate/typename-specifier.cpp b/clang/test/SemaTemplate/typename-specifier.cpp new file mode 100644 index 0000000..9eb4f33 --- /dev/null +++ b/clang/test/SemaTemplate/typename-specifier.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace N { + struct A { + typedef int type; + }; + + struct B { + }; + + struct C { + struct type { }; + int type; // expected-note 2{{referenced member 'type' is declared here}} + }; +} + +int i; + +typename N::A::type *ip1 = &i; // expected-warning{{'typename' occurs outside of a template}} +typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}} \ +// expected-warning{{'typename' occurs outside of a template}} +typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} \ +// expected-warning{{'typename' occurs outside of a template}} + +void test(double d) { + typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}} \ + // expected-warning 2{{'typename' occurs outside of a template}} + int five = f(5); + + using namespace N; + for (typename A::type i = 0; i < 10; ++i) // expected-warning{{'typename' occurs outside of a template}} + five += 1; + + const typename N::A::type f2(d); // expected-warning{{'typename' occurs outside of a template}} +} + +namespace N { + template<typename T> + struct X { + typedef typename T::type type; // expected-error {{no type named 'type' in 'N::B'}} \ + // expected-error {{no type named 'type' in '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}} + }; +} + +N::X<N::A>::type *ip4 = &i; +N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'N::X<N::B>' requested here}} +N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'N::X<N::C>' requested here}} + +N::X<int>::type fail1; // expected-note{{in instantiation of template class 'N::X<int>' requested here}} + +template<typename T> +struct Y { + typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'N::X<B>' requested here}} \ + // expected-note{{in instantiation of template class 'N::X<C>' requested here}} +}; + +struct A { + typedef int type; +}; + +struct B { +}; + +struct C { + struct type { }; + int type; // expected-note{{referenced member 'type' is declared here}} +}; + +::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; + +namespace PR10925 { + template< int mydim, typename Traits > + class BasicGeometry + { + typedef int some_type_t; + }; + + template<class ctype, int mydim, int coorddim> + class MockGeometry : BasicGeometry<mydim, int>{ + using typename BasicGeometry<mydim, int>::operator[]; // expected-error {{typename is allowed for identifiers only}} + }; +} diff --git a/clang/test/SemaTemplate/typo-dependent-name.cpp b/clang/test/SemaTemplate/typo-dependent-name.cpp new file mode 100644 index 0000000..96554e9 --- /dev/null +++ b/clang/test/SemaTemplate/typo-dependent-name.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct Base { + T inner; +}; + +template<typename T> +struct X { + template<typename U> + struct Inner { + }; + + bool f(T other) { + return this->inner < other; + } +}; diff --git a/clang/test/SemaTemplate/unresolved-construct.cpp b/clang/test/SemaTemplate/unresolved-construct.cpp new file mode 100644 index 0000000..bb9ed8e --- /dev/null +++ b/clang/test/SemaTemplate/unresolved-construct.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +class A +{ +public: + A() {} + + template <class _F> + explicit A(_F&& __f); + + A(A&&) {} + A& operator=(A&&) {return *this;} +}; + +template <class T> +void f(T t) +{ + A a; + a = f(t); +} diff --git a/clang/test/SemaTemplate/unused-variables.cpp b/clang/test/SemaTemplate/unused-variables.cpp new file mode 100644 index 0000000..1b9350b --- /dev/null +++ b/clang/test/SemaTemplate/unused-variables.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused -verify %s + +struct X0 { + ~X0(); +}; + +struct X1 { }; + +template<typename T> +void f() { + X0 x0; + X1 x1; // expected-warning{{unused variable 'x1'}} +} + +template<typename T, typename U> +void g() { + T t; + U u; // expected-warning{{unused variable 'u'}} +} + +template void g<X0, X1>(); // expected-note{{in instantiation of}} diff --git a/clang/test/SemaTemplate/value-dependent-null-pointer-constant.cpp b/clang/test/SemaTemplate/value-dependent-null-pointer-constant.cpp new file mode 100644 index 0000000..223500e --- /dev/null +++ b/clang/test/SemaTemplate/value-dependent-null-pointer-constant.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -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)); +} diff --git a/clang/test/SemaTemplate/virtual-member-functions.cpp b/clang/test/SemaTemplate/virtual-member-functions.cpp new file mode 100644 index 0000000..974f664 --- /dev/null +++ b/clang/test/SemaTemplate/virtual-member-functions.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5557 { +template <class T> struct A { + A(); + virtual void anchor(); + virtual int a(T x); +}; +template<class T> A<T>::A() {} +template<class T> void A<T>::anchor() { } + +template<class T> int A<T>::a(T x) { + return *x; // expected-error{{requires pointer operand}} +} + +void f(A<int> x) { + x.anchor(); // expected-note{{instantiation}} +} + +template<typename T> +struct X { + virtual void f(); +}; + +template<> +void X<int>::f() { } +} + +template<typename T> +struct Base { + virtual ~Base() { + int *ptr = 0; + T t = ptr; // expected-error{{cannot initialize}} + } +}; + +template<typename T> +struct Derived : Base<T> { + virtual void foo() { } +}; + +template struct Derived<int>; // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}} + +template<typename T> +struct HasOutOfLineKey { + HasOutOfLineKey() { } + virtual T *f(float *fp); +}; + +template<typename T> +T *HasOutOfLineKey<T>::f(float *fp) { + return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}} +} + +HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::f' requested here}} + +namespace std { + class type_info; +} + +namespace PR7114 { + class A { virtual ~A(); }; // expected-note{{declared private here}} + + template<typename T> + class B { + public: + class Inner : public A { }; // expected-error{{base class 'PR7114::A' has private destructor}} + static Inner i; + static const unsigned value = sizeof(i) == 4; + }; + + int f() { return B<int>::value; } + + void test_typeid(B<float>::Inner bfi) { + (void)typeid(bfi); // expected-note{{implicit default destructor}} + } + + template<typename T> + struct X : A { + void f() { } + }; + + void test_X(X<int> xi, X<float> xf) { + xi.f(); + } +} |