diff options
Diffstat (limited to 'clang/test/CXX/temp')
157 files changed, 8544 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/p3.cpp b/clang/test/CXX/temp/p3.cpp new file mode 100644 index 0000000..c146bc4 --- /dev/null +++ b/clang/test/CXX/temp/p3.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +template<typename T> struct S { + static int a, b; +}; + +template<typename T> int S<T>::a, S<T>::b; // expected-error {{can only declare a single entity}} + +template<typename T> struct A { static A a; } A<T>::a; // expected-error {{expected ';' after struct}} \ + expected-error {{use of undeclared identifier 'T'}} \ + expected-warning{{extra qualification}} + +template<typename T> struct B { } f(); // expected-error {{expected ';' after struct}} \ + expected-error {{requires a type specifier}} + +template<typename T> struct C { } // expected-error {{expected ';' after struct}} + +A<int> c; diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp new file mode 100644 index 0000000..59ce8b6 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +namespace std { + typedef decltype(nullptr) nullptr_t; +} + +template<int *ip> struct IP { // expected-note 4 {{template parameter is declared here}} + IP<ip> *ip2; +}; + +constexpr std::nullptr_t get_nullptr() { return nullptr; } + +constexpr std::nullptr_t np = nullptr; + +std::nullptr_t nonconst_np; // expected-note{{declared here}} + +IP<0> ip0; // expected-error{{null non-type template argument must be cast to template parameter type 'int *'}} +IP<(0)> ip1; // expected-error{{null non-type template argument must be cast to template parameter type 'int *'}} +IP<nullptr> ip2; +IP<get_nullptr()> ip3; +IP<(int*)0> ip4; +IP<np> ip5; +IP<nonconst_np> ip5; // expected-error{{non-type template argument of type 'std::nullptr_t' (aka 'nullptr_t') is not a constant expression}} \ +// expected-note{{read of non-constexpr variable 'nonconst_np' is not allowed in a constant expression}} +IP<(float*)0> ip6; // expected-error{{null non-type template argument of type 'float *' does not match template parameter of type 'int *'}} + +struct X { }; +template<int X::*pm> struct PM { // expected-note 2 {{template parameter is declared here}} + PM<pm> *pm2; +}; + +PM<0> pm0; // expected-error{{null non-type template argument must be cast to template parameter type 'int X::*'}} +PM<(0)> pm1; // expected-error{{null non-type template argument must be cast to template parameter type 'int X::*'}} +PM<nullptr> pm2; +PM<get_nullptr()> pm3; +PM<(int X::*)0> pm4; +PM<np> pm5; + +template<int (X::*pmf)(int)> struct PMF { // expected-note 2 {{template parameter is declared here}} + PMF<pmf> *pmf2; +}; + +PMF<0> pmf0; // expected-error{{null non-type template argument must be cast to template parameter type 'int (X::*)(int)'}} +PMF<(0)> pmf1; // expected-error{{null non-type template argument must be cast to template parameter type 'int (X::*)(int)'}} +PMF<nullptr> pmf2; +PMF<get_nullptr()> pmf3; +PMF<(int (X::*)(int))0> pmf4; +PMF<np> pmf5; + + +template<std::nullptr_t np> struct NP { // expected-note 2{{template parameter is declared here}} + NP<np> *np2; +}; + +NP<nullptr> np1; +NP<np> np2; +NP<get_nullptr()> np3; +NP<0> np4; // expected-error{{null non-type template argument must be cast to template parameter type 'std::nullptr_t' (aka 'nullptr_t')}} +constexpr int i = 7; +NP<i> np5; // expected-error{{non-type template argument of type 'const int' cannot be converted to a value of type 'std::nullptr_t'}} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp new file mode 100644 index 0000000..c4db002 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple=x86_64-linux-gnu %s + +// C++11 [temp.arg.nontype]p1: +// +// A template-argument for a non-type, non-template template-parameter shall +// be one of: +// -- an integral constant expression; or +// -- the name of a non-type template-parameter ; or +namespace non_type_tmpl_param { + template <int N> struct X0 { X0(); }; + template <int N> X0<N>::X0() { } + template <int* N> struct X1 { X1(); }; + template <int* N> X1<N>::X1() { } + template <int& N> struct X3 { X3(); }; + template <int& N> X3<N>::X3() { } + template <int (*F)(int)> struct X4 { X4(); }; + template <int (*F)(int)> X4<F>::X4() { } + template <typename T, int (T::* M)(int)> struct X5 { X5(); }; + template <typename T, int (T::* M)(int)> X5<T, M>::X5() { } +} + +// -- a constant expression that designates the address of an object with +// static storage duration and external or internal linkage or a function +// with external or internal linkage, including function templates and +// function template-ids, but excluting non-static class members, expressed +// (ignoring parentheses) as & id-expression, except that the & may be +// omitted if the name refers to a function or array and shall be omitted +// if the corresopnding template-parameter is a reference; or +namespace addr_of_obj_or_func { + template <int* p> struct X0 { }; // expected-note 4{{here}} + template <int (*fp)(int)> struct X1 { }; + template <int &p> struct X2 { }; // expected-note 4{{here}} + template <const int &p> struct X2k { }; // expected-note {{here}} + template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}} + + int i = 42; + int iarr[10]; + int f(int i); + const int ki = 9; // expected-note 5{{here}} + __thread int ti = 100; // expected-note 2{{here}} + static int f_internal(int); // expected-note 4{{here}} + template <typename T> T f_tmpl(T t); + + void test() { + X0<i> x0a; // expected-error {{must have its address taken}} + X0<&i> x0a_addr; + X0<iarr> x0b; + X0<&iarr> x0b_addr; // expected-error {{cannot be converted to a value of type 'int *'}} + X0<ki> x0c; // expected-error {{must have its address taken}} expected-warning {{internal linkage is a C++11 extension}} + X0<&ki> x0c_addr; // expected-error {{cannot be converted to a value of type 'int *'}} expected-warning {{internal linkage is a C++11 extension}} + X0<&ti> x0d_addr; // expected-error {{refers to thread-local object}} + X1<f> x1a; + X1<&f> x1a_addr; + X1<f_tmpl> x1b; + X1<&f_tmpl> x1b_addr; + X1<f_tmpl<int> > x1c; + X1<&f_tmpl<int> > x1c_addr; + X1<f_internal> x1d; // expected-warning {{internal linkage is a C++11 extension}} + X1<&f_internal> x1d_addr; // expected-warning {{internal linkage is a C++11 extension}} + X2<i> x2a; + X2<&i> x2a_addr; // expected-error {{address taken}} + X2<iarr> x2b; // expected-error {{cannot bind to template argument of type 'int [10]'}} + X2<&iarr> x2b_addr; // expected-error {{address taken}} + X2<ki> x2c; // expected-error {{ignores qualifiers}} expected-warning {{internal linkage is a C++11 extension}} + X2k<ki> x2kc; // expected-warning {{internal linkage is a C++11 extension}} + X2k<&ki> x2kc_addr; // expected-error {{address taken}} expected-warning {{internal linkage is a C++11 extension}} + X2<ti> x2d_addr; // expected-error {{refers to thread-local object}} + X3<f> x3a; + X3<&f> x3a_addr; // expected-error {{address taken}} + X3<f_tmpl> x3b; + X3<&f_tmpl> x3b_addr; // expected-error {{address taken}} + X3<f_tmpl<int> > x3c; + X3<&f_tmpl<int> > x3c_addr; // expected-error {{address taken}} + X3<f_internal> x3d; // expected-warning {{internal linkage is a C++11 extension}} + X3<&f_internal> x3d_addr; // expected-error {{address taken}} expected-warning {{internal linkage is a C++11 extension}} + + int n; // expected-note {{here}} + X0<&n> x0_no_linkage; // expected-error {{non-type template argument refers to object 'n' that does not have linkage}} + struct Local { static int f() {} }; // expected-note {{here}} + X1<&Local::f> x1_no_linkage; // expected-error {{non-type template argument refers to function 'f' that does not have linkage}} + } +} + +// -- a constant expression that evaluates to a null pointer value (4.10); or +// -- a constant expression that evaluates to a null member pointer value +// (4.11); or +// -- a pointer to member expressed as described in 5.3.1. + +namespace bad_args { + template <int* N> struct X0 { }; // expected-note 2{{template parameter is declared here}} + int i = 42; + X0<&i + 2> x0a; // expected-error{{non-type template argument does not refer to any declaration}} + int* iptr = &i; + X0<iptr> x0b; // expected-error{{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp new file mode 100644 index 0000000..9b9b532 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -0,0 +1,205 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.arg.nontype] p5: +// The following conversions are performed on each expression used as +// a non-type template-argument. If a non-type template-argument cannot be +// converted to the type of the corresponding template-parameter then the +// program is ill-formed. +// -- for a non-type template-parameter of integral or enumeration type, +// integral promotions (4.5) and integral conversions (4.7) are applied. +namespace integral_parameters { + template<short s> struct X0 { }; + X0<17> x0i; + X0<'a'> x0c; + template<char c> struct X1 { }; + X1<100l> x1l; +} + +// -- for a non-type template-parameter of type pointer to object, +// qualification conversions (4.4) and the array-to-pointer conversion +// (4.2) are applied; if the template-argument is of type +// std::nullptr_t, the null pointer conversion (4.10) is applied. +namespace pointer_to_object_parameters { + // PR6226 + struct Str { + Str(const char *); + }; + + template<const char *s> + struct A { + Str get() { return s; } + }; + + char hello[6] = "Hello"; + extern const char world[6]; + const char world[6] = "world"; + void test() { + (void)A<hello>().get(); + (void)A<world>().get(); + } + + class X { + public: + X(); + X(int, int); + operator int() const; + }; + + template<X const *Ptr> struct A2; // expected-note{{template parameter is declared here}} + + X *X_ptr; + X an_X; + X array_of_Xs[10]; + A2<X_ptr> *a12; // expected-error{{must have its address taken}} + A2<array_of_Xs> *a13; + A2<&an_X> *a13_2; + A2<(&an_X)> *a13_3; // expected-warning{{address non-type template argument cannot be surrounded by parentheses}} + + // PR6244 + struct X1 {} X1v; + template <X1*> struct X2 { }; + template <X1* Value> struct X3 : X2<Value> { }; + struct X4 : X3<&X1v> { }; + + // PR6563 + int *bar; + template <int *> struct zed {}; // expected-note 2{{template parameter is declared here}} + void g(zed<bar>*); // expected-error{{must have its address taken}} + + int baz; + void g2(zed<baz>*); // expected-error{{must have its address taken}} + + void g3(zed<&baz>*); // okay +} + +// -- For a non-type template-parameter of type reference to object, no +// conversions apply. The type referred to by the reference may be more +// cv-qualified than the (otherwise identical) type of the +// template-argument. The template-parameter is bound directly to the +// template-argument, which shall be an lvalue. +namespace reference_parameters { + template <int& N> struct S0 { }; // expected-note 3 {{template parameter is declared here}} + template <const int& N> struct S1 { }; // expected-note 2 {{template parameter is declared here}} + template <volatile int& N> struct S2 { }; // expected-note 2 {{template parameter is declared here}} + template <const volatile int& N> struct S3 { }; + int i; + extern const int ci; + volatile int vi; + extern const volatile int cvi; + void test() { + S0<i> s0; + S0<ci> s0c; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'const int' ignores qualifiers}} + S0<vi> s0v; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'volatile int' ignores qualifiers}} + S0<cvi> s0cv; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'const volatile int' ignores qualifiers}} + + S1<i> s1; + S1<ci> s1c; + S1<vi> s1v; // expected-error{{reference binding of non-type template parameter of type 'const int &' to template argument of type 'volatile int' ignores qualifiers}} + S1<cvi> s1cv; // expected-error{{reference binding of non-type template parameter of type 'const int &' to template argument of type 'const volatile int' ignores qualifiers}} + + S2<i> s2; + S2<ci> s2c; // expected-error{{reference binding of non-type template parameter of type 'volatile int &' to template argument of type 'const int' ignores qualifiers}} + S2<vi> s2v; + S2<cvi> s2cv; // expected-error{{reference binding of non-type template parameter of type 'volatile int &' to template argument of type 'const volatile int' ignores qualifiers}} + + S3<i> s3; + S3<ci> s3c; + S3<vi> s3v; + S3<cvi> s3cv; + } + + namespace PR6250 { + template <typename T, const T &ref> void inc() { + ref++; // expected-error{{read-only variable is not assignable}} + } + + template<typename T, const T &ref> void bind() { + T &ref2 = ref; // expected-error{{drops qualifiers}} + } + + int counter; + void test() { + inc<int, counter>(); // expected-note{{instantiation of}} + bind<int, counter>(); // expected-note{{instantiation of}} + } + } + + namespace PR6749 { + template <int& i> struct foo {}; // expected-note{{template parameter is declared here}} + int x, &y = x; + foo<y> f; // expected-error{{is not an object}} + } +} + +// -- For a non-type template-parameter of type pointer to function, the +// function-to-pointer conversion (4.3) is applied; if the +// template-argument is of type std::nullptr_t, the null pointer +// conversion (4.10) is applied. If the template-argument represents +// a set of overloaded functions (or a pointer to such), the matching +// function is selected from the set (13.4). +namespace pointer_to_function { + template<int (*)(int)> struct X0 { }; // expected-note 3{{template parameter is declared here}} + int f(int); + int f(float); + int g(float); + int (*funcptr)(int); + void x0a(X0<f>); + void x0b(X0<&f>); + void x0c(X0<g>); // expected-error{{non-type template argument of type 'int (float)' cannot be converted to a value of type 'int (*)(int)'}} + void x0d(X0<&g>); // expected-error{{non-type template argument of type 'int (*)(float)' cannot be converted to a value of type 'int (*)(int)'}} + void x0e(X0<funcptr>); // expected-error{{must have its address taken}} +} + +// -- For a non-type template-parameter of type reference to function, no +// conversions apply. If the template-argument represents a set of +// overloaded functions, the matching function is selected from the set +// (13.4). +namespace reference_to_function { + template<int (&)(int)> struct X0 { }; // expected-note 4{{template parameter is declared here}} + int f(int); + int f(float); + int g(float); + int (*funcptr)(int); + void x0a(X0<f>); + void x0b(X0<&f>); // expected-error{{address taken in non-type template argument for template parameter of reference type 'int (&)(int)'}} + void x0c(X0<g>); // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'int (float)'}} + void x0d(X0<&g>); // expected-error{{address taken in non-type template argument for template parameter of reference type 'int (&)(int)'}} + void x0e(X0<funcptr>); // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'int (*)(int)'}} +} +// -- For a non-type template-parameter of type pointer to member function, +// if the template-argument is of type std::nullptr_t, the null member +// pointer conversion (4.11) is applied; otherwise, no conversions +// apply. If the template-argument represents a set of overloaded member +// functions, the matching member function is selected from the set +// (13.4). +namespace pointer_to_member_function { + struct X { }; + struct Y : X { + int f(int); + int g(int); + int g(float); + float h(float); + }; + + template<int (Y::*)(int)> struct X0 {}; // expected-note{{template parameter is declared here}} + X0<&Y::f> x0a; + X0<&Y::g> x0b; + X0<&Y::h> x0c; // expected-error{{non-type template argument of type 'float (pointer_to_member_function::Y::*)(float)' cannot be converted to a value of type 'int (pointer_to_member_function::Y::*)(int)'}} +} + +// -- For a non-type template-parameter of type pointer to data member, +// qualification conversions (4.4) are applied; if the template-argument +// is of type std::nullptr_t, the null member pointer conversion (4.11) +// is applied. +namespace pointer_to_member_data { + struct X { int x; }; + struct Y : X { int y; }; + + template<int Y::*> struct X0 {}; // expected-note{{template parameter is declared here}} + X0<&Y::y> x0a; + X0<&Y::x> x0b; // expected-error{{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int pointer_to_member_data::Y::*'}} + + // Test qualification conversions + template<const int Y::*> struct X1 {}; + X1<&Y::y> x1a; +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp new file mode 100644 index 0000000..1c13bff --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template <class T> struct eval; // expected-note 3{{template is declared here}} + +template <template <class, class...> class TT, class T1, class... Rest> +struct eval<TT<T1, Rest...>> { }; + +template <class T1> struct A; +template <class T1, class T2> struct B; +template <int N> struct C; +template <class T1, int N> struct D; +template <class T1, class T2, int N = 17> struct E; + +eval<A<int>> eA; +eval<B<int, float>> eB; +eval<C<17>> eC; // expected-error{{implicit instantiation of undefined template 'eval<C<17> >'}} +eval<D<int, 17>> eD; // expected-error{{implicit instantiation of undefined template 'eval<D<int, 17> >'}} +eval<E<int, float>> eE; // expected-error{{implicit instantiation of undefined template 'eval<E<int, float, 17> >}} + +template<template <int ...N> class TT> struct X0 { }; // expected-note{{previous non-type template parameter with type 'int' is here}} +template<int I, int J, int ...Rest> struct X0a; +template<int ...Rest> struct X0b; +template<int I, long J> struct X0c; // expected-note{{template non-type parameter has a different type 'long' in template argument}} + +X0<X0a> inst_x0a; +X0<X0b> inst_x0b; +X0<X0c> inst_x0c; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + +template<typename T, + template <T ...N> class TT> // expected-note{{previous non-type template parameter with type 'short' is here}} +struct X1 { }; +template<int I, int J, int ...Rest> struct X1a; +template<long I, long ...Rest> struct X1b; +template<short I, short J> struct X1c; +template<short I, long J> struct X1d; // expected-note{{template non-type parameter has a different type 'long' in template argument}} + +X1<int, X1a> inst_x1a; +X1<long, X1b> inst_x1b; +X1<short, X1c> inst_x1c; +X1<short, X1d> inst_x1d; // expected-error{{template template argument has different template parameters than its corresponding template template paramete}} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp new file mode 100644 index 0000000..b03ed46 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// C++03 imposed restrictions in this paragraph that were lifted with 0x, so we +// just test that the example given now parses cleanly. + +template <class T> class X { }; +template <class T> void f(T t) { } +struct { } unnamed_obj; +void f() { + struct A { }; + enum { e1 }; + typedef struct { } B; + B b; + X<A> x1; + X<A*> x2; + X<B> x3; + f(e1); + f(unnamed_obj); + f(b); +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp new file mode 100644 index 0000000..0fd9a7e --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> struct A { + static T t; // expected-error{{static data member instantiated with function type 'int ()'}} +}; +typedef int function(); +A<function> a; // expected-note{{instantiation of}} + +template<typename T> struct B { + B() { T t; } // expected-error{{variable instantiated with function type 'int ()'}} +}; +B<function> b; // expected-note{{instantiation of}} + +template <typename T> int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}} +enum {e}; // expected-note{{unnamed type used in template argument was declared here}} + +void test_f0(int n) { + int i = f0(0, e); // expected-warning{{template argument uses unnamed type}} + int vla[n]; + f0(0, vla); // expected-error{{no matching function for call to 'f0'}} +} + +namespace N0 { + template <typename R, typename A1> void f0(R (*)(A1)); + template <typename T> int f1(T); + template <typename T, typename U> int f1(T, U); + enum {e1}; // expected-note 2{{unnamed type used in template argument was declared here}} + enum {e2}; // expected-note 2{{unnamed type used in template argument was declared here}} + enum {e3}; // expected-note{{unnamed type used in template argument was declared here}} + + template<typename T> struct X; + template<typename T> struct X<T*> { }; + + void f() { + f0( // expected-warning{{template argument uses unnamed type}} + &f1<__typeof__(e1)>); // expected-warning{{template argument uses unnamed type}} + int (*fp1)(int, __typeof__(e2)) = f1; // expected-warning{{template argument uses unnamed type}} + f1(e2); // expected-warning{{template argument uses unnamed type}} + f1(e2); + + X<__typeof__(e3)*> x; // expected-warning{{template argument uses unnamed type}} + } +} diff --git a/clang/test/CXX/temp/temp.decls/p3.cpp b/clang/test/CXX/temp/temp.decls/p3.cpp new file mode 100644 index 0000000..41811ff --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/p3.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> using A = int; +template<typename T> using A<T*> = char; // expected-error {{partial specialization of alias templates is not permitted}} +template<> using A<char> = char; // expected-error {{explicit specialization of alias templates is not permitted}} +template using A<char> = char; // expected-error {{explicit instantiation of alias templates is not permitted}} +using A<char> = char; // expected-error {{name defined in alias declaration must be an identifier}} diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p1.cpp new file mode 100644 index 0000000..966e3c1 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p1.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> using U = T; + +// The name of the alias template is a template-name. +U<char> x; +void f(U<int>); +typedef U<U<U<U<int>>>> I; diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp new file mode 100644 index 0000000..a5b39fe --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> using U = T; + +using I = U<U<U<U<int>>>>; +using I = int; + +template<typename A, typename B> using Fst = A; +template<typename A, typename B> using Snd = B; + +using I = Fst<Snd<char,int>,double>; + +namespace StdExample { + // Prerequisites for example. + template<class T, class A> struct vector { /* ... */ }; + + + template<class T> struct Alloc {}; + template<class T> using Vec = vector<T, Alloc<T>>; + Vec<int> v; + + template<class T> + void process(Vec<T>& v) // expected-note {{previous definition is here}} + { /* ... */ } + + template<class T> + void process(vector<T, Alloc<T>>& w) // expected-error {{redefinition of 'process'}} + { /* ... */ } + + template<template<class> class TT> + void f(TT<int>); // expected-note {{candidate template ignored}} + + template<template<class,class> class TT> + void g(TT<int, Alloc<int>>); + + int h() { + f(v); // expected-error {{no matching function for call to 'f'}} + g(v); // OK: TT = vector + } + + + // v's type is same as vector<int, Alloc<int>>. + using VTest = vector<int, Alloc<int>>; + using VTest = decltype(v); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp new file mode 100644 index 0000000..afd9b4b --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// The example given in the standard (this is rejected for other reasons anyway). +template<class T> struct A; +template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<T>'}} +template<class T> struct A { + typedef B<T> U; // expected-note {{in instantiation of template type alias 'B' requested here}} +}; +B<short> b; + +template<typename T> using U = int; +// FIXME: This is illegal, but probably only because CWG1044 missed this paragraph. +template<typename T> using U = U<T>; diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp new file mode 100644 index 0000000..d0fc797 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test class template partial specializations of member templates. +template<typename T> +struct X0 { + template<typename U> struct Inner0 { + static const unsigned value = 0; + }; + + template<typename U> struct Inner0<U*> { + static const unsigned value = 1; + }; +}; + +template<typename T> template<typename U> +struct X0<T>::Inner0<const U*> { + static const unsigned value = 2; +}; + +int array0[X0<int>::Inner0<int>::value == 0? 1 : -1]; +int array1[X0<int>::Inner0<int*>::value == 1? 1 : -1]; +int array2[X0<int>::Inner0<const int*>::value == 2? 1 : -1]; + +// Make sure we can provide out-of-line class template partial specializations +// for member templates (and instantiate them). +template<class T> struct A { + struct C { + template<class T2> struct B; + }; +}; + +// partial specialization of A<T>::C::B<T2> +template<class T> template<class T2> struct A<T>::C::B<T2*> { }; + +A<short>::C::B<int*> absip; + +// Check for conflicts during template instantiation. +template<typename T, typename U> +struct Outer { + template<typename X, typename Y> struct Inner; + template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous}} + template<typename Y> struct Inner<U, Y> {}; // expected-error{{cannot be redeclared}} +}; + +Outer<int, int> outer; // expected-note{{instantiation}} + +// Test specialization of class template partial specialization members. +template<> template<typename Z> +struct X0<float>::Inner0<Z*> { + static const unsigned value = 3; +}; + +int array3[X0<float>::Inner0<int>::value == 0? 1 : -1]; +int array4[X0<float>::Inner0<int*>::value == 3? 1 : -1]; +int array5[X0<float>::Inner0<const int*>::value == 2? 1 : -1]; + +namespace rdar8651930 { + template<typename OuterT> + struct Outer { + template<typename T, typename U> + struct Inner; + + template<typename T> + struct Inner<T, T> { + static const bool value = true; + }; + + template<typename T, typename U> + struct Inner { + static const bool value = false; + }; + }; + + int array0[Outer<int>::Inner<int, int>::value? 1 : -1]; + int array1[Outer<int>::Inner<int, float>::value? -1 : 1]; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp new file mode 100644 index 0000000..aa1e2d4 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<int ...Values> struct X1; + +template<int ...Values> +struct X1<0, Values+1 ...>; // expected-error{{non-type template argument depends on a template parameter of the partial specialization}} + + diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp new file mode 100644 index 0000000..b754368 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// -- The argument list of the specialization shall not be identical +// to the implicit argument list of the primary template. + +template<typename T, typename ...Types> +struct X1; + +template<typename T, typename ...Types> +struct X1<T, Types...> // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} +{ }; + + diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp new file mode 100644 index 0000000..2a3e914 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR8905 +template<char C1, char C2> +struct X { + static const bool value = 0; +}; + +template<int C1> +struct X<C1, C1> { + static const bool value = 1; +}; + +int check0[X<1, 2>::value == 0? 1 : -1]; +int check1[X<1, 1>::value == 1? 1 : -1]; + +template<int, int, int> struct int_values { + static const unsigned value = 0; +}; + +template<unsigned char C1, unsigned char C3> +struct int_values<C1, 12, C3> { + static const unsigned value = 1; +}; + +int check2[int_values<256, 12, 3>::value == 0? 1 : -1]; diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp new file mode 100644 index 0000000..97457ea --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<int I, int J, class T> struct X { + static const int value = 0; +}; + +template<int I, int J> struct X<I, J, int> { + static const int value = 1; +}; + +template<int I> struct X<I, I, int> { + static const int value = 2; +}; + +int array0[X<0, 0, float>::value == 0? 1 : -1]; +int array1[X<0, 1, int>::value == 1? 1 : -1]; +int array2[X<0, 0, int>::value == 2? 1 : -1]; + +namespace DependentSubstPartialOrdering { + template<typename T, typename U = void, typename V = void> + struct X { + static const unsigned value = 1; + }; + + template<typename T, typename U> + struct X<T, U, typename T::is_b> { + static const unsigned value = 2; + }; + + template<typename T> + struct X<T, typename T::is_a, typename T::is_b> { + static const unsigned value = 3; + }; + + struct X1 { }; + + struct X2 { + typedef void is_b; + }; + + struct X3 { + typedef void is_a; + typedef void is_b; + }; + + int check_X1[X<X1, void, void>::value == 1? 1 : -1]; + int check_X2[X<X2, void, void>::value == 2? 1 : -1]; + int check_X3[X<X3, void, void>::value == 3? 1 : -1]; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp new file mode 100644 index 0000000..59253db --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, int N> +struct A; + +template<typename T> // expected-note{{previous template declaration}} +struct A<T*, 2> { + void f0(); + void f1(); + void f2(); +}; + +template<> +struct A<int, 1> { + void g0(); +}; + +// FIXME: We should probably give more precise diagnostics here, but the +// diagnostics we give aren't terrible. +// FIXME: why not point to the first parameter that's "too many"? +template<typename T, int N> // expected-error{{too many template parameters}} +void A<T*, 2>::f0() { } + +template<typename T, int N> +void A<T, N>::f1() { } // expected-error{{out-of-line definition}} diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp new file mode 100644 index 0000000..87e21e4 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, int N> +struct A; + +template<typename T> +struct A<T*, 2> { + A(T); + ~A(); + + void f(T*); + + operator T*(); + + static T value; +}; + +template<class X> void A<X*, 2>::f(X*) { } + +template<class X> X A<X*, 2>::value; + +template<class X> A<X*, 2>::A(X) { value = 0; } + +template<class X> A<X*, 2>::~A() { } + +template<class X> A<X*, 2>::operator X*() { return 0; } diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp new file mode 100644 index 0000000..b65e1d0 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, typename U> +struct X0 { + struct Inner; +}; + +template<typename T, typename U> +struct X0<T, U>::Inner { + T x; + U y; + + void f() { x = y; } // expected-error{{incompatible}} +}; + + +void test(int i, float f) { + X0<int, float>::Inner inner; + inner.x = 5; + inner.y = 3.4; + inner.f(); + + X0<int*, float *>::Inner inner2; + inner2.x = &i; + inner2.y = &f; + inner2.f(); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp new file mode 100644 index 0000000..f8cc009 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<typename T> struct A { + enum E : T; // expected-note {{here}} + E v; + E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}} + E g() { return E::e1; } + E h(); +}; + +A<int> a; +A<int>::E a0 = A<int>().v; +int n = A<int>::E::e1; // expected-error {{implicit instantiation of undefined member}} + +template<typename T> enum A<T>::E : T { e1, e2 }; + +// FIXME: Now that A<T>::E is defined, we are supposed to inject its enumerators +// into the already-instantiated class A<T>. This seems like a really bad idea, +// though, so we don't implement that, but what we do implement is inconsistent. +// +// Either do as the standard says, or only include enumerators lexically defined +// within the class in its scope. +A<int>::E a1 = A<int>::e1; // expected-error {{no member named 'e1' in 'A<int>'}} + +A<char>::E a2 = A<char>::e2; + +template<typename T> typename A<T>::E A<T>::h() { return e2; } +A<short>::E a3 = A<short>().h(); + + +template<typename T> struct B { + enum class E; + E v; + E f() { return E::e1; } + E g(); +}; + +B<int> b; +B<int>::E b0 = B<int>().v; + +template<typename T> enum class B<T>::E { e1, e2 }; +B<int>::E b1 = B<int>::E::e1; + +B<char>::E b2 = B<char>::E::e2; + +template<typename T> typename B<T>::E B<T>::g() { return e2; } +B<short>::E b3 = B<short>().g(); + + +// Enumeration members of class templates can be explicitly specialized. For +// unscoped enumerations, specializations must be defined before the primary +// template is, since otherwise the primary template will be implicitly +// instantiated when we parse the nested name specifier. +template<> enum A<long long>::E : long long { e3, e4 }; // expected-error {{explicit specialization of 'E' after instantiation}} expected-note {{first required here}} + +template<> enum class B<long long>::E { e3, e4 }; +B<long long>::E b4 = B<long long>::E::e4; + +B<long>::E b5; +template<> enum class B<long>::E { e5 }; +void fb5() { b5 = decltype(b5)::e5; } +B<long>::E b6 = B<long>::E::e5; + + +template<typename T> struct C { + enum class E : T; +}; + +template<> enum class C<long long>::E : long long { e3, e4 }; +C<long long>::E c0 = C<long long>::E::e3; + +C<long>::E c1; +template<> enum class C<long>::E : long { e5 }; +void fc1() { c1 = decltype(c1)::e5; } +C<long>::E c2 = C<long>::E::e5; + +template<> enum class C<int>::E : int { e6 }; +template<typename T> enum class C<T>::E : T { e0 }; +C<int>::E c3 = C<int>::E::e6; +C<int>::E c4 = C<int>::E::e0; // expected-error {{no member named 'e0' in 'C<int>::E'}} + + +// Enumeration members can't be partially-specialized. +template<typename T> enum class B<T*>::E { e5, e6 }; // expected-error {{nested name specifier for a declaration cannot depend on a template parameter}} + + +// Explicit specializations can be forward-declared. +template<typename T> +struct D { + enum class E { e1 }; +}; +template<> enum class D<int>::E; +D<int>::E d1 = D<int>::E::e1; // expected-error {{incomplete type 'D<int>::E'}} +template<> enum class D<int>::E { e2 }; +D<int>::E d2 = D<int>::E::e2; +D<char>::E d3 = D<char>::E::e1; // expected-note {{first required here}} +D<char>::E d4 = D<char>::E::e2; // expected-error {{no member named 'e2'}} +template<> enum class D<char>::E { e3 }; // expected-error {{explicit specialization of 'E' after instantiation}} + +template<> enum class D<short>::E; +struct F { + // Per C++11 [class.friend]p3, these friend declarations have no effect. + // Only classes and functions can be friends. + template<typename T> friend enum D<T>::E; + template<> friend enum D<short>::E; + + template<> friend enum D<double>::E { e3 }; // expected-error {{cannot define a type in a friend declaration}} + +private: + static const int n = 1; // expected-note {{private here}} +}; +template<> enum class D<short>::E { + e = F::n // expected-error {{private member}} +}; + +class Access { + friend class X; + + template<typename T> + class Priv { + friend class X; + + enum class E : T; + }; + + class S { + typedef int N; // expected-note {{here}} + static const int k = 3; // expected-note {{here}} + + friend class Priv<char>; + }; + + static const int k = 5; +}; + +template<> enum class Access::Priv<Access::S::N>::E + : Access::S::N { // expected-error {{private member}} + a = Access::k, // ok + b = Access::S::k // expected-error {{private member}} +}; + +template<typename T> enum class Access::Priv<T>::E : T { + c = Access::k, + d = Access::S::k +}; + +class X { + Access::Priv<int>::E a = Access::Priv<int>::E::a; + Access::Priv<char>::E c = Access::Priv<char>::E::d; + // FIXME: We should see an access error for this enumerator. + Access::Priv<short>::E b = Access::Priv<short>::E::d; +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp new file mode 100644 index 0000000..4c05c62 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct X1 { }; + +template<typename T> +struct X0 { + typedef int size_type; + typedef T value_type; + + size_type f0() const; + value_type *f1(); + X1<value_type*> f2(); +}; + +template<typename T> +typename X0<T>::size_type X0<T>::f0() const { + return 0; +} + +template<typename U> +typename X0<U>::value_type *X0<U>::f1() { + return 0; +}; + +template<typename U> +X1<typename X0<U>::value_type*> X0<U>::f2() { + return 0; +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp new file mode 100644 index 0000000..1764563 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U> // expected-note{{previous template}} +class X0 { +public: + typedef int size_type; + + X0(int); + ~X0(); + + void f0(const T&, const U&); + + T& operator[](int i) const; + + void f1(size_type) const; + void f2(size_type) const; + void f3(size_type) const; + void f4() ; + + operator T*() const; + + T value; +}; + +template<typename T, typename U> +void X0<T, U>::f0(const T&, const U&) { // expected-note{{previous definition}} +} + +template<class X, class Y> +X& X0<X, Y>::operator[](int i) const { + (void)i; + return value; +} + +template<class X, class Y> +void X0<X, Y>::f1(int) const { } + +template<class X, class Y> +void X0<X, Y>::f2(size_type) const { } + +template<class X, class Y, class Z> // expected-error{{too many template parameters}} +void X0<X, Y>::f3(size_type) const { +} + +template<class X, class Y> +void X0<Y, X>::f4() { } // expected-error{{does not refer}} + +// FIXME: error message should probably say, "redefinition of 'X0<T, U>::f0'" +// rather than just "redefinition of 'f0'" +template<typename T, typename U> +void X0<T, U>::f0(const T&, const U&) { // expected-error{{redefinition}} +} + +// Test out-of-line constructors, destructors +template<typename T, typename U> +X0<T, U>::X0(int x) : value(x) { } + +template<typename T, typename U> +X0<T, U>::~X0() { } + +// Test out-of-line conversion functions. +template<typename T, typename U> +X0<T, U>::operator T*() const { + return &value; +} + +namespace N { template <class X> class A {void a();}; } +namespace N { template <class X> void A<X>::a() {} } + +// PR5566 +template<typename T> +struct X1 { + template<typename U> + struct B { void f(); }; +}; + +template<typename T> +template<typename U> +void X1<T>::template B<U>::f() { } + +// PR5527 +template <template <class> class T> +class X2 { + template <class F> + class Bar { + void Func(); + }; +}; + +template <template <class> class T> +template <class F> +void X2<T>::Bar<F>::Func() {} + +// PR5528 +template <template <class> class T> +class X3 { + void F(); +}; + +template <template <class> class T> +void X3<T>::F() {} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp new file mode 100644 index 0000000..f09faa9 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// Test instantiation of member functions of class templates defined out-of-line +template<typename T, typename U> +struct X0 { + void f(T *t, const U &u); + void f(T *); +}; + +template<typename T, typename U> +void X0<T, U>::f(T *t, const U &u) { + *t = u; // expected-error{{not assignable}} +} + +void test_f(X0<float, int> xfi, X0<void, int> xvi, float *fp, void *vp, int i) { + xfi.f(fp, i); + xvi.f(vp, i); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp new file mode 100644 index 0000000..70c9c70 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern "C" void * malloc(int); + +template <typename T> struct A { + void *malloc(int); +}; + +template <typename T> +inline void *A<T>::malloc(int) +{ + return 0; +} + +void f() { + malloc(10); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp new file mode 100644 index 0000000..9fc4a58 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test instantiation of static data members declared out-of-line. + +template<typename T> +struct X { + static T value; +}; + +template<typename T> + T X<T>::value = 17; // expected-error{{no viable conversion}} + +struct InitOkay { + InitOkay(int) { } +}; + +struct CannotInit { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + +int &returnInt() { return X<int>::value; } +float &returnFloat() { return X<float>::value; } + +InitOkay &returnInitOkay() { return X<InitOkay>::value; } + +unsigned long sizeOkay() { return sizeof(X<CannotInit>::value); } + +CannotInit &returnError() { + return X<CannotInit>::value; // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp new file mode 100644 index 0000000..2eae112 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + static T value; +}; + +template<typename T> +T X0<T>::value = 0; // expected-error{{no viable conversion}} + +struct X1 { + X1(int); +}; + +struct X2 { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + +int& get_int() { return X0<int>::value; } +X1& get_X1() { return X0<X1>::value; } + +double*& get_double_ptr() { return X0<int*>::value; } // expected-error{{non-const lvalue reference to type 'double *' cannot bind to a value of unrelated type 'int *'}} + +X2& get_X2() { + return X0<X2>::value; // expected-note{{instantiation}} +} + +template<typename T> T x; // expected-error{{variable 'x' declared as a template}} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp new file mode 100644 index 0000000..63909fb --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Core DR 532. +namespace PR8130 { + struct A { }; + + template<class T> struct B { + template<class R> int &operator*(R&); + }; + + template<class T, class R> float &operator*(T&, R&); + void test() { + A a; + B<A> b; + int &ir = b * a; + } +} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp new file mode 100644 index 0000000..2ffdd95 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace DeduceVsMember { + template<typename T> + struct X { + template<typename U> + int &operator==(const U& other) const; + }; + + template<typename T, typename U> + float &operator==(const T&, const X<U>&); + + void test(X<int> xi, X<float> xf) { + float& ir = (xi == xf); + } +} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp new file mode 100644 index 0000000..b2a6219 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> struct A { A(); }; +template<class T> int &f(T); +template<class T> float &f(T*); +template<class T> double &f(const T*); + +template<class T> void g(T); // expected-note{{candidate}} +template<class T> void g(T&); // expected-note{{candidate}} + +template<class T> int &h(const T&); +template<class T> float &h(A<T>&); + +void m() { + const int *p; + double &dr1 = f(p); + float x; + g(x); // expected-error{{ambiguous}} + A<int> z; + float &fr1 = h(z); + const A<int> z2; + int &ir1 = h(z2); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp new file mode 100644 index 0000000..4d34968 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> int &f(T); +template<class T> float &f(T*, int=1); + +template<class T> int &g(T); +template<class T> float &g(T*, ...); + +int main() { + int* ip; + float &fr1 = f(ip); + float &fr2 = g(ip); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp new file mode 100644 index 0000000..e9a3eaa --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> void f0(T) { } // expected-note{{previous}} +template<class U> void f0(U) { } // expected-error{{redefinition}} + +template<int I> void f0() { } // expected-note{{previous}} +template<int> void f0() { } // expected-error{{redefinition}} + +typedef int INT; + +template<template<class T, T Value1, INT> class X> + void f0() { } // expected-note{{previous}} +template<template<typename T, T Value1, int> class> + void f0() { } // expected-error{{redefinition}} + +template<typename T> +struct MetaFun; + +template<typename T> + typename MetaFun<T*>::type f0(const T&) { while (1) {} } // expected-note{{previous}} +template<class U> + typename MetaFun<U*>::type f0(const U&) { while (1) {} } // expected-error{{redefinition}} + +// FIXME: We need canonicalization of expressions for this to work +// template<int> struct A { }; +// template<int I> void f0(A<I>) { } // Xpected-note{{previous}} +// template<int J> void f0(A<J>) { } // Xpected-error{{redefinition}} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp new file mode 100644 index 0000000..f42b94a --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// All of these function templates are distinct. +template<typename T> void f0(T) { } +template<typename T, typename U> void f0(T) { } +template<typename T, typename U> void f0(U) { } +void f0(); +template<typename T> void f0(T*); +void f0(int); +template<int I> void f0(); +template<typename T> void f0(); + + diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp new file mode 100644 index 0000000..a668ada --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<int N, int M> +struct A0 { + void g0(); +}; + +template<int X, int Y> void f0(A0<X, Y>) { } // expected-note{{previous}} +template<int N, int M> void f0(A0<M, N>) { } +template<int V1, int V2> void f0(A0<V1, V2>) { } // expected-error{{redefinition}} + +template<int X, int Y> void f1(A0<0, (X + Y)>) { } // expected-note{{previous}} +template<int X, int Y> void f1(A0<0, (X - Y)>) { } +template<int A, int B> void f1(A0<0, (A + B)>) { } // expected-error{{redefinition}} + +template<int X, int Y> void A0<X, Y>::g0() { } diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp new file mode 100644 index 0000000..63f569b --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -0,0 +1,358 @@ +// RUN: %clang_cc1 -verify -emit-llvm-only %s + +namespace test0 { +template <typename T> struct Num { + T value_; + +public: + Num(T value) : value_(value) {} + T get() const { return value_; } + + template <typename U> struct Rep { + U count_; + Rep(U count) : count_(count) {} + + friend Num operator*(const Num &a, const Rep &n) { + Num x = 0; + for (U count = n.count_; count; --count) + x += a; + return x; + } + }; + + friend Num operator+(const Num &a, const Num &b) { + return a.value_ + b.value_; + } + + Num& operator+=(const Num& b) { + value_ += b.value_; + return *this; + } + + class Representation {}; + friend class Representation; +}; + +class A { + template <typename T> friend bool iszero(const A &a) throw(); +}; + +template <class T> class B_iterator; +template <class T> class B { + friend class B_iterator<T>; +}; + +int calc1() { + Num<int> left = -1; + Num<int> right = 1; + Num<int> result = left + right; + return result.get(); +} + +int calc2() { + Num<int> x = 3; + Num<int>::Rep<char> n = (char) 10; + Num<int> result = x * n; + return result.get(); +} +} + +// Reduced from GNU <locale> +namespace test1 { + class A { + bool b; // expected-note {{declared private here}} + template <typename T> friend bool has(const A&); + }; + template <typename T> bool has(const A &x) { + return x.b; + } + template <typename T> bool hasnot(const A &x) { + return x.b; // expected-error {{'b' is a private member of 'test1::A'}} + } +} + +namespace test2 { + class A { + bool b; // expected-note {{declared private here}} + template <typename T> friend class HasChecker; + }; + template <typename T> class HasChecker { + bool check(A *a) { + return a->b; + } + }; + template <typename T> class HasNotChecker { + bool check(A *a) { + return a->b; // expected-error {{'b' is a private member of 'test2::A'}} + } + }; +} + +namespace test3 { + class Bool; + template <class T> class User; + template <class T> T transform(class Bool, T); + + class Bool { + friend class User<bool>; + friend bool transform<>(Bool, bool); + + bool value; // expected-note 2 {{declared private here}} + }; + + template <class T> class User { + static T compute(Bool b) { + return b.value; // expected-error {{'value' is a private member of 'test3::Bool'}} + } + }; + + template <class T> T transform(Bool b, T value) { + if (b.value) // expected-error {{'value' is a private member of 'test3::Bool'}} + return value; + return value + 1; + } + + template bool transform(Bool, bool); + template int transform(Bool, int); // expected-note {{requested here}} + + template class User<bool>; + template class User<int>; // expected-note {{requested here}} +} + +namespace test4 { + template <class T> class A { + template <class T0> friend class B; + bool foo(const A<T> *) const; + }; + + template <class T> class B { + bool bar(const A<T> *a, const A<T> *b) { + return a->foo(b); + } + }; + + template class B<int>; +} + +namespace test5 { + template <class T, class U=int> class A {}; + template <class T> class B { + template <class X, class Y> friend class A; + }; + template class B<int>; + template class A<int>; +} + +namespace Dependent { + template<typename T, typename Traits> class X; + template<typename T, typename Traits> + X<T, Traits> operator+(const X<T, Traits>&, const T*); + + template<typename T, typename Traits> class X { + typedef typename Traits::value_type value_type; + friend X operator+<>(const X&, const value_type*); + }; +} + +namespace test7 { + template <class T> class A { // expected-note {{declared here}} + friend class B; + int x; // expected-note {{declared private here}} + }; + + class B { + int foo(A<int> &a) { + return a.x; + } + }; + + class C { + int foo(A<int> &a) { + return a.x; // expected-error {{'x' is a private member of 'test7::A<int>'}} + } + }; + + // This shouldn't crash. + template <class T> class D { + friend class A; // expected-error {{elaborated type refers to a template}} + }; + template class D<int>; +} + +namespace test8 { + template <class N> class A { + static int x; + template <class T> friend void foo(); + }; + template class A<int>; + + template <class T> void foo() { + A<int>::x = 0; + } + template void foo<int>(); +} + +namespace test9 { + template <class T> class A { + class B; class C; + + int foo(B *b) { + return b->x; + } + + int foo(C *c) { + return c->x; // expected-error {{'x' is a private member}} + } + + class B { + int x; + friend int A::foo(B*); + }; + + class C { + int x; // expected-note {{declared private here}} + }; + }; + + template class A<int>; // expected-note {{in instantiation}} +} + +namespace test10 { + template <class T> class A; + template <class T> A<T> bar(const T*, const A<T>&); + template <class T> class A { + private: + void foo(); // expected-note {{declared private here}} + friend A bar<>(const T*, const A<T>&); + }; + + template <class T> A<T> bar(const T *l, const A<T> &r) { + A<T> l1; + l1.foo(); + + A<char> l2; + l2.foo(); // expected-error {{'foo' is a private member of 'test10::A<char>'}} + + return l1; + } + + template A<int> bar<int>(const int *, const A<int> &); // expected-note {{in instantiation}} +} + +// PR6752: this shouldn't crash. +namespace test11 { + struct Foo { + template<class A> + struct IteratorImpl { + template<class T> friend class IteratorImpl; + }; + }; + + template struct Foo::IteratorImpl<int>; + template struct Foo::IteratorImpl<long>; +} + +// PR6827 +namespace test12 { + template <typename T> class Foo; + template <typename T> Foo<T> foo(T* t){ return Foo<T>(t, true); } + + template <typename T> class Foo { + public: + Foo(T*); + friend Foo<T> foo<T>(T*); + private: + Foo(T*, bool); // expected-note {{declared private here}} + }; + + // Should work. + int globalInt; + Foo<int> f = foo(&globalInt); + + // Shouldn't work. + long globalLong; + template <> Foo<long> foo(long *t) { + Foo<int> s(&globalInt, false); // expected-error {{calling a private constructor}} + return Foo<long>(t, true); + } +} + +// PR6514 +namespace test13 { + template <int N, template <int> class Temp> + class Role : public Temp<N> { + friend class Temp<N>; + int x; + }; + + template <int N> class Foo { + void foo(Role<N, test13::Foo> &role) { + (void) role.x; + } + }; + + template class Foo<0>; +} + +namespace test14 { + template <class T> class B; + template <class T> class A { + friend void B<T>::foo(); + static void foo(); // expected-note {{declared private here}} + }; + + template <class T> class B { + void foo() { return A<long>::foo(); } // expected-error {{'foo' is a private member of 'test14::A<long>'}} + }; + + template class B<int>; // expected-note {{in instantiation}} +} + +namespace test15 { + template <class T> class B; + template <class T> class A { + friend void B<T>::foo(); + + // This shouldn't be misrecognized as a templated-scoped reference. + template <class U> friend void B<T>::bar(U); + + static void foo(); // expected-note {{declared private here}} + }; + + template <class T> class B { + void foo() { return A<long>::foo(); } // expected-error {{'foo' is a private member of 'test15::A<long>'}} + }; + + template <> class B<float> { + void foo() { return A<float>::foo(); } + template <class U> void bar(U u) { + (void) A<float>::foo(); + } + }; + + template class B<int>; // expected-note {{in instantiation}} +} + +namespace PR10913 { + template<class T> class X; + + template<class T> void f(X<T> *x) { + x->member = 0; + } + + template<class U, class T> void f2(X<T> *x) { + x->member = 0; // expected-error{{'member' is a protected member of 'PR10913::X<int>'}} + } + + template<class T> class X { + friend void f<T>(X<T> *x); + friend void f2<T>(X<int> *x); + + protected: + int member; // expected-note{{declared protected here}} + }; + + template void f(X<int> *); + template void f2<int>(X<int> *); + template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp new file mode 100644 index 0000000..0b2a25e --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> class A { + typedef int Member; +}; + +class B { + template <class T> friend class A; + template <class T> friend class Undeclared; + + template <class T> friend typename A<T>::Member; // expected-error {{friend type templates must use an elaborated type}} +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p4.cpp new file mode 100644 index 0000000..e036cef --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p4.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X1 { + friend void f6(int) { } // expected-error{{redefinition of}} \ + // expected-note{{previous definition}} +}; + +X1<int> x1a; +X1<float> x1b; // expected-note {{in instantiation of}} + +template<typename T> +struct X2 { + operator int(); + + friend void f(int x) { } // expected-error{{redefinition}} \ + // expected-note{{previous definition}} +}; + +int array0[sizeof(X2<int>)]; +int array1[sizeof(X2<float>)]; // expected-note{{instantiation of}} + +void g() { + X2<int> xi; + f(xi); + X2<float> xf; + f(xf); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp new file mode 100644 index 0000000..63fd3df --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + template <class T> class A { + class Member {}; + }; + + class B { + template <class T> friend class A<T>::Member; + }; + + A<int> a; + B b; +} + +// rdar://problem/8204127 +namespace test1 { + template <class T> struct A; + + class C { + static void foo(); + template <class T> friend void A<T>::f(); + }; + + template <class T> struct A { + void f() { C::foo(); } + }; + + template <class T> struct A<T*> { + void f() { C::foo(); } + }; + + template <> struct A<char> { + void f() { C::foo(); } + }; +} + +// FIXME: these should fail! +namespace test2 { + template <class T> struct A; + + class C { + static void foo(); + template <class T> friend void A<T>::g(); + }; + + template <class T> struct A { + void f() { C::foo(); } + }; + + template <class T> struct A<T*> { + void f() { C::foo(); } + }; + + template <> struct A<char> { + void f() { C::foo(); } + }; +} + +// Tests 3, 4 and 5 were all noted in <rdar://problem/8540527>. +namespace test3 { + template <class T> struct A { + struct Inner { + static int foo(); + }; + }; + + template <class U> class C { + int i; + template <class T> friend struct A<T>::Inner; + }; + + template <class T> int A<T>::Inner::foo() { + C<int> c; + c.i = 0; + return 0; + } + + int test = A<int>::Inner::foo(); +} + +namespace test4 { + template <class T> struct X { + template <class U> void operator+=(U); + + template <class V> + template <class U> + friend void X<V>::operator+=(U); + }; + + void test() { + X<int>() += 1.0; + } +} + +namespace test5 { + template<template <class> class T> struct A { + template<template <class> class T> friend void A<T>::foo(); + }; + + template <class> struct B {}; + template class A<B>; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p8.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p8.cpp new file mode 100644 index 0000000..d0221a3 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p8.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> class A { }; + +class X { + template<class T> friend class A<T*>; // expected-error{{partial specialization cannot be declared as a friend}} +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp new file mode 100644 index 0000000..f5f1205 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> struct A { + static T cond; + + template <class U> struct B { + static T twice(U value) { + return (cond ? value + value : value); + } + }; +}; + +int foo() { + A<bool>::cond = true; + return A<bool>::B<int>::twice(4); +} + +namespace PR6376 { + template<typename T> + struct X { + template<typename Y> + struct Y1 { }; // + }; + + template<> + struct X<float> { + template<typename Y> + struct Y1 { }; + }; + + template<typename T, typename U> + struct Z : public X<T>::template Y1<U> { }; + + Z<float, int> z0; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p3.cpp new file mode 100644 index 0000000..0eb747b --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p3.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> struct AA { + template <class C> virtual void g(C); // expected-error{{'virtual' can not be specified on member function templates}} + virtual void f(); +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp new file mode 100644 index 0000000..8bcd773 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { + template <class T> operator T*(); +}; + +template <class T> A::operator T*() { return 0; } +template <> A::operator char*(){ return 0; } // specialization +template A::operator void*(); // explicit instantiation + +int main() { + A a; + int *ip; + ip = a.operator int*(); +} + +// PR5742 +namespace PR5742 { + template <class T> struct A { }; + template <class T> struct B { }; + + struct S { + template <class T> operator T(); + } s; + + void f() { + s.operator A<A<int> >(); + s.operator A<B<int> >(); + s.operator A<B<A<int> > >(); + } +} + +// PR5762 +class Foo { + public: + template <typename T> operator T(); + + template <typename T> + T As() { + return this->operator T(); + } + + template <typename T> + T As2() { + return operator T(); + } + + int AsInt() { + return this->operator int(); + } +}; + +template float Foo::As(); +template double Foo::As2(); + +// Partial ordering with conversion function templates. +struct X0 { + template<typename T> operator T*() { + T x = 1; + x = 17; // expected-error{{read-only variable is not assignable}} + } + + template<typename T> operator T*() const; // expected-note{{explicit instantiation refers here}} + + template<typename T> operator const T*() const { + T x = T(); + return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} \ + // expected-error{{cannot initialize return object of type 'const int *' with an lvalue of type 'int'}} + } +}; + +template X0::operator const char*() const; // expected-note{{'X0::operator const char *<char>' requested here}} +template X0::operator const int*(); // expected-note{{'X0::operator const int *<const int>' requested here}} +template X0::operator float*() const; // expected-error{{explicit instantiation of undefined function template}} + +void test_X0(X0 x0, const X0 &x0c) { + x0.operator const int*(); // expected-note{{in instantiation of function template specialization}} + x0.operator float *(); + x0c.operator const char*(); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp new file mode 100644 index 0000000..fec8060 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +namespace DeductionForInstantiation { + template<unsigned I, typename ...Types> + struct X { }; + + template<typename ...Types> + void f0(X<sizeof...(Types), Types&...>) { } + + // No explicitly-specified arguments + template void f0(X<0>); + template void f0(X<1, int&>); + template void f0(X<2, int&, short&>); + + // One explicitly-specified argument + template void f0<float>(X<1, float&>); + template void f0<double>(X<1, double&>); + + // Two explicitly-specialized arguments + template void f0<char, unsigned char>(X<2, char&, unsigned char&>); + template void f0<signed char, char>(X<2, signed char&, char&>); + + // FIXME: Extension of explicitly-specified arguments + // template void f0<short, int>(X<3, short&, int&, long&>); +} + +namespace DeductionWithConversion { + template<char...> struct char_values { + static const unsigned value = 0; + }; + + template<int C1, char C3> + struct char_values<C1, 12, C3> { + static const unsigned value = 1; + }; + + int check0[char_values<1, 12, 3>::value == 1? 1 : -1]; + + template<int...> struct int_values { + static const unsigned value = 0; + }; + + template<unsigned char C1, unsigned char C3> + struct int_values<C1, 12, C3> { + static const unsigned value = 1; + }; + + int check1[int_values<256, 12, 3>::value == 0? 1 : -1]; + int check2[int_values<3, 12, 3>::value == 1? 1 : -1]; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp new file mode 100644 index 0000000..db28eea --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp @@ -0,0 +1,352 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Example bind implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +// Helper type traits +template<typename T> +struct add_reference { + typedef T &type; +}; + +template<typename T> +struct add_reference<T&> { + typedef T &type; +}; + +template<typename T> +struct add_const_reference { + typedef T const &type; +}; + +template<typename T> +struct add_const_reference<T&> { + typedef T &type; +}; + +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> +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template<typename T> reference_wrapper<T> ref(T& t) { + return reference_wrapper<T>(t); +} +template<typename T> reference_wrapper<const T> cref(const T& t) { + return reference_wrapper<const T>(t); +} + +template<typename... Values> class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template<typename Head, typename... Tail> +class tuple<Head, Tail...> : private tuple<Tail...> { + typedef tuple<Tail...> inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference<Head>::type v, + typename add_const_reference<Tail>::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template<typename... VValues> tuple(const tuple<VValues...>& other) + : m_head(other.head()), inherited(other.tail()) { } + + template<typename... VValues> tuple& + operator=(const tuple<VValues...>& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference<Head>::type head() { return m_head; } + typename add_reference<const Head>::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + +protected: + Head m_head; +}; + +// Creation functions +template<typename T> +struct make_tuple_result { + typedef T type; +}; + +template<typename T> +struct make_tuple_result<reference_wrapper<T> > { + typedef T& type; +}; + +template<typename... Values> +tuple<typename make_tuple_result<Values>::type...> +make_tuple(const Values&... values) { + return tuple<typename make_tuple_result<Values>::type...>(values...); +} + +template<typename... Values> +tuple<Values&...> tie(Values&... values) { + return tuple<Values&...>(values...); +} + +// Helper classes +template<typename Tuple> struct tuple_size; + +template<typename... Values> struct tuple_size<tuple<Values...> > { + static const int value = sizeof...(Values); +}; + +template<int I, typename Tuple> struct tuple_element; + +template<int I, typename Head, typename... Tail> +struct tuple_element<I, tuple<Head, Tail...> > { + typedef typename tuple_element<I-1, tuple<Tail...> >::type type; +}; + +template<typename Head, typename... Tail> +struct tuple_element<0, tuple<Head, Tail...> > { + typedef Head type; +}; + +// Element access +template<int I, typename Tuple> class get_impl; +template<int I, typename Head, typename... Values> +class get_impl<I, tuple<Head, Values...> > { + typedef typename tuple_element<I-1, tuple<Values...> >::type Element; + typedef typename add_reference<Element>::type RJ; + typedef typename add_const_reference<Element>::type PJ; + typedef get_impl<I-1, tuple<Values...> > Next; +public: + static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } + static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } +}; + +template<typename Head, typename... Values> +class get_impl<0, tuple<Head, Values...> > { + typedef typename add_reference<Head>::type RJ; + typedef typename add_const_reference<Head>::type PJ; +public: + static RJ get(tuple<Head, Values...>& t) { return t.head(); } + static PJ get(const tuple<Head, Values...>& t) { return t.head(); } +}; + +template<int I, typename... Values> typename add_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +template<int I, typename... Values> typename add_const_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(const tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +// Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template<typename... TValues, typename... UValues> +bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template<typename... TValues, typename... UValues> +bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return u < t; +} + +template<typename... TValues, typename... UValues> +bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(u < t); +} + +template<typename... TValues, typename... UValues> +bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t < u); +} + +// make_indices helper +template<int...> struct int_tuple {}; +// make_indexes impl is a helper for make_indexes +template<int I, typename IntTuple, typename... Types> struct make_indexes_impl; + +template<int I, int... Indexes, typename T, typename... Types> +struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...> { + typedef typename make_indexes_impl<I+1, int_tuple<Indexes..., I>, Types...>::type type; +}; + +template<int I, int... Indexes> +struct make_indexes_impl<I, int_tuple<Indexes...> > { + typedef int_tuple<Indexes...> type; +}; + +template<typename... Types> +struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { +}; + +// Bind +template<typename T> struct is_bind_expression { + static const bool value = false; +}; + +template<typename T> struct is_placeholder { + static const int value = 0; +}; + + +template<typename F, typename... BoundArgs> class bound_functor { + typedef typename make_indexes<BoundArgs...>::type indexes; +public: + typedef typename F::result_type result_type; + explicit bound_functor(const F& f, const BoundArgs&... bound_args) + : f(f), bound_args(bound_args...) { } template<typename... Args> + typename F::result_type operator()(Args&... args); +private: F f; + tuple<BoundArgs...> bound_args; +}; + +template<typename F, typename... BoundArgs> +inline bound_functor<F, BoundArgs...> bind(const F& f, const BoundArgs&... bound_args) { + return bound_functor<F, BoundArgs...>(f, bound_args...); +} + +template<typename F, typename ...BoundArgs> +struct is_bind_expression<bound_functor<F, BoundArgs...> > { + static const bool value = true; +}; + +// enable_if helper +template<bool Cond, typename T = void> +struct enable_if; + +template<typename T> +struct enable_if<true, T> { + typedef T type; +}; + +template<typename T> +struct enable_if<false, T> { }; + +// safe_tuple_element helper +template<int I, typename Tuple, typename = void> +struct safe_tuple_element { }; + +template<int I, typename... Values> +struct safe_tuple_element<I, tuple<Values...>, + typename enable_if<(I >= 0 && I < tuple_size<tuple<Values...> >::value)>::type> { + typedef typename tuple_element<I, tuple<Values...> >::type type; +}; + +// mu +template<typename Bound, typename... Args> +inline typename safe_tuple_element<is_placeholder<Bound>::value -1, + tuple<Args...> >::type +mu(Bound& bound_arg, const tuple<Args&...>& args) { + return get<is_placeholder<Bound>::value-1>(args); +} + +template<typename T, typename... Args> +inline T& mu(reference_wrapper<T>& bound_arg, const tuple<Args&...>&) { + return bound_arg.get(); +} + +template<typename F, int... Indexes, typename... Args> +inline typename F::result_type +unwrap_and_forward(F& f, int_tuple<Indexes...>, const tuple<Args&...>& args) { + return f(get<Indexes>(args)...); +} + +template<typename Bound, typename... Args> +inline typename enable_if<is_bind_expression<Bound>::value, + typename Bound::result_type>::type +mu(Bound& bound_arg, const tuple<Args&...>& args) { + typedef typename make_indexes<Args...>::type Indexes; + return unwrap_and_forward(bound_arg, Indexes(), args); +} + +template<typename T> +struct is_reference_wrapper { + static const bool value = false; +}; + +template<typename T> +struct is_reference_wrapper<reference_wrapper<T>> { + static const bool value = true; +}; + +template<typename Bound, typename... Args> +inline typename enable_if<(!is_bind_expression<Bound>::value + && !is_placeholder<Bound>::value + && !is_reference_wrapper<Bound>::value), + Bound&>::type +mu(Bound& bound_arg, const tuple<Args&...>&) { + return bound_arg; +} + +template<typename F, typename... BoundArgs, int... Indexes, typename... Args> +typename F::result_type apply_functor(F& f, tuple<BoundArgs...>& bound_args, + int_tuple<Indexes...>, + const tuple<Args&...>& args) { + return f(mu(get<Indexes>(bound_args), args)...); +} + +template<typename F, typename... BoundArgs> +template<typename... Args> +typename F::result_type bound_functor<F, BoundArgs...>::operator()(Args&... args) { + return apply_functor(f, bound_args, indexes(), tie(args...)); +} + +template<int N> struct placeholder { }; +template<int N> +struct is_placeholder<placeholder<N>> { + static const int value = N; +}; + +template<typename T> +struct plus { + typedef T result_type; + + T operator()(T x, T y) { return x + y; } +}; + +placeholder<1> _1; + +// Test bind +void test_bind() { + int x = 17; + int y = 25; + bind(plus<int>(), x, _1)(y); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp new file mode 100644 index 0000000..e15203a --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Example function implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +template<typename Signature> class function; + +template<typename R, typename... Args> class invoker_base { +public: + virtual ~invoker_base() { } + virtual R invoke(Args...) = 0; + virtual invoker_base* clone() = 0; +}; + +template<typename F, typename R, typename... Args> +class functor_invoker : public invoker_base<R, Args...> { +public: + explicit functor_invoker(const F& f) : f(f) { } + R invoke(Args... args) { return f(args...); } + functor_invoker* clone() { return new functor_invoker(f); } + +private: + F f; +}; + +template<typename R, typename... Args> +class function<R (Args...)> { +public: + typedef R result_type; + function() : invoker (0) { } + function(const function& other) : invoker(0) { + if (other.invoker) + invoker = other.invoker->clone(); + } + + template<typename F> function(const F& f) : invoker(0) { + invoker = new functor_invoker<F, R, Args...>(f); + } + + ~function() { + if (invoker) + delete invoker; + } + + function& operator=(const function& other) { + function(other).swap(*this); + return *this; + } + + template<typename F> + function& operator=(const F& f) { + function(f).swap(*this); + return *this; + } + + void swap(function& other) { + invoker_base<R, Args...>* tmp = invoker; + invoker = other.invoker; + other.invoker = tmp; + } + + result_type operator()(Args... args) const { + return invoker->invoke(args...); + } + +private: + invoker_base<R, Args...>* invoker; +}; + +template<typename T> +struct add { + T operator()(T x, T y) { return x + y; } +}; + +int add_ints(int x, int y) { return x + y; } + +void test_function() { + function<int(int, int)> f2a; + function<int(int, int)> f2b = add<int>(); + function<int(int, int)> f2c = add<float>(); + function<int(int, int)> f2d(f2b); + function<int(int, int)> f2e = &add_ints; + f2c = f2d; + f2d = &add_ints; + f2c(1.0, 3); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp new file mode 100644 index 0000000..9de5fa8 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp @@ -0,0 +1,260 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Example tuple implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +// Helper type traits +template<typename T> +struct add_reference { + typedef T &type; +}; + +template<typename T> +struct add_reference<T&> { + typedef T &type; +}; + +template<typename T> +struct add_const_reference { + typedef T const &type; +}; + +template<typename T> +struct add_const_reference<T&> { + typedef T &type; +}; + +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> +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template<typename T> reference_wrapper<T> ref(T& t) { + return reference_wrapper<T>(t); +} +template<typename T> reference_wrapper<const T> cref(const T& t) { + return reference_wrapper<const T>(t); +} + +template<typename... Values> class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template<typename Head, typename... Tail> +class tuple<Head, Tail...> : private tuple<Tail...> { + typedef tuple<Tail...> inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference<Head>::type v, + typename add_const_reference<Tail>::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template<typename... VValues> tuple(const tuple<VValues...>& other) + : m_head(other.head()), inherited(other.tail()) { } + + template<typename... VValues> tuple& + operator=(const tuple<VValues...>& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference<Head>::type head() { return m_head; } + typename add_reference<const Head>::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + +protected: + Head m_head; +}; + +void test_tuple() { + tuple<> t0a; + tuple<> t0b(t0a); + t0a = t0b; + + tuple<int> t1a; + tuple<int> t1b(17); + tuple<int> t1c(t1b); + t1a = t1b; + + tuple<float> t1d(3.14159); + tuple<float> t1e(t1d); + t1d = t1e; + + int i; + float f; + double d; + tuple<int*, float*, double*> t3a(&i, &f, &d); +} + +// Creation functions +template<typename T> +struct make_tuple_result { + typedef T type; +}; + +template<typename T> +struct make_tuple_result<reference_wrapper<T> > { + typedef T& type; +}; + +template<typename... Values> +tuple<typename make_tuple_result<Values>::type...> +make_tuple(const Values&... values) { + return tuple<typename make_tuple_result<Values>::type...>(values...); +} + +template<typename... Values> +tuple<Values&...> tie(Values&... values) { + return tuple<Values&...>(values...); +} + +template<typename T> const T *addr(const T& ref) { return &ref; } +void test_creation_functions() { + int i; + float f; + double d; + const tuple<int, float&, const double&> *t3p = addr(make_tuple(i, ref(f), cref(d))); + const tuple<int&, float&, double&> *t3q = addr(tie(i, f, d)); +} + +// Helper classes +template<typename Tuple> struct tuple_size; + +template<typename... Values> struct tuple_size<tuple<Values...> > { + static const int value = sizeof...(Values); +}; + +int check_tuple_size_0[tuple_size<tuple<> >::value == 0? 1 : -1]; +int check_tuple_size_1[tuple_size<tuple<int>>::value == 1? 1 : -1]; +int check_tuple_size_2[tuple_size<tuple<float, double>>::value == 2? 1 : -1]; +int check_tuple_size_3[tuple_size<tuple<char, unsigned char, signed char>>::value == 3? 1 : -1]; + +template<int I, typename Tuple> struct tuple_element; + +template<int I, typename Head, typename... Tail> +struct tuple_element<I, tuple<Head, Tail...> > { + typedef typename tuple_element<I-1, tuple<Tail...> >::type type; +}; + +template<typename Head, typename... Tail> +struct tuple_element<0, tuple<Head, Tail...> > { + typedef Head type; +}; + +int check_tuple_element_0[is_same<tuple_element<0, tuple<int&, float, double>>::type, + int&>::value? 1 : -1]; + +int check_tuple_element_1[is_same<tuple_element<1, tuple<int&, float, double>>::type, + float>::value? 1 : -1]; + +int check_tuple_element_2[is_same<tuple_element<2, tuple<int&, float, double>>::type, + double>::value? 1 : -1]; + +// Element access +template<int I, typename Tuple> class get_impl; +template<int I, typename Head, typename... Values> +class get_impl<I, tuple<Head, Values...> > { + typedef typename tuple_element<I-1, tuple<Values...> >::type Element; + typedef typename add_reference<Element>::type RJ; + typedef typename add_const_reference<Element>::type PJ; + typedef get_impl<I-1, tuple<Values...> > Next; +public: + static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } + static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } +}; + +template<typename Head, typename... Values> +class get_impl<0, tuple<Head, Values...> > { + typedef typename add_reference<Head>::type RJ; + typedef typename add_const_reference<Head>::type PJ; +public: + static RJ get(tuple<Head, Values...>& t) { return t.head(); } + static PJ get(const tuple<Head, Values...>& t) { return t.head(); } +}; + +template<int I, typename... Values> typename add_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +template<int I, typename... Values> typename add_const_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(const tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +void test_element_access(tuple<int*, float*, double*&> t3) { + int i; + float f; + double d; + get<0>(t3) = &i; + get<1>(t3) = &f; + get<2>(t3) = &d; +} + +// Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template<typename... TValues, typename... UValues> +bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template<typename... TValues, typename... UValues> +bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return u < t; +} + +template<typename... TValues, typename... UValues> +bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(u < t); +} + +template<typename... TValues, typename... UValues> +bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t < u); +} + +void test_relational_operators(tuple<int*, float*, double*> t3) { + (void)(t3 == t3); + (void)(t3 != t3); + (void)(t3 < t3); + (void)(t3 <= t3); + (void)(t3 >= t3); + (void)(t3 > t3); +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp new file mode 100644 index 0000000..6d9d8c5 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -fblocks -fsyntax-only -verify %s + +// Tests the use of blocks with variadic templates. +template<typename ...Args> +int f0(Args ...args) { + return ^ { + return sizeof...(Args); + }() + ^ { + return sizeof...(args); + }(); +} + +template<typename ...Args> +int f1(Args ...args) { + return ^ { + return f0(args...); + }(); +} + +template int f0(int, float, double); +template int f1(const char*, int, float, double); + +template<typename ...Args> +int f2(Args ...args) { + return ^(Args ...block_args) { + return f1(block_args...); + }(args + 0 ...); +} + +template int f2(const char*, int, float, double); + +template<typename ...Args> +int f3(Args ...args) { + return ^(Args *...block_args) { + return f1(block_args...); + }(&args...); +} + +template int f3(const char*, int, float, double); + +template<typename ...Args> +int PR9953(Args ...args) { + return ^(Args *...block_args) { + return f1(block_args); // expected-error{{expression contains unexpanded parameter pack 'block_args'}} + }(&args...); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp new file mode 100644 index 0000000..fb72754 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T, typename U> struct pair { }; +template<typename ...Types> struct tuple { }; + +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 ExpandIntoFixed { + template<typename T, + typename U, + typename V = pair<T, U>, + typename W = V*> + class X0 { }; + + template<typename ...Ts> + class X1 { + public: + typedef X0<Ts...> type; + }; + + static_assert(is_same<X1<int, int>::type, + X0<int, int, pair<int, int>, pair<int, int>*>>::value, + "fails with two default arguments"); + + static_assert(is_same<X1<int, int, float>::type, + X0<int, int, float, float*>>::value, + "fails with one default argument"); + + static_assert(is_same<X1<int, int, float, double>::type, + X0<int, int, float, double>>::value, + "fails with no default arguments"); +} + +namespace ExpandIntoFixedShifted { + template<typename T, + typename U, + typename V = pair<T, U>, + typename W = V*> + class X0 { }; + + template<typename ...Ts> + class X1 { + public: + typedef X0<char, Ts...> type; + }; + + static_assert(is_same<X1<int>::type, + X0<char, int, pair<char, int>, pair<char, int>*>>::value, + "fails with two default arguments"); + + static_assert(is_same<X1<int, float>::type, + X0<char, int, float, float*>>::value, + "fails with one default argument"); + + static_assert(is_same<X1<int, float, double>::type, + X0<char, int, float, double>>::value, + "fails with no default arguments"); +} + +namespace Deduction { + template <typename X, typename Y = double> struct Foo {}; + template <typename ...Args> tuple<Args...> &foo(Foo<Args...>); + + void call_foo(Foo<int, float> foo_if, Foo<int> foo_i) { + tuple<int, float> &t1 = foo(foo_if); + tuple<int, double> &t2 = foo(foo_i); + } +} + +namespace PR9021a { + template<typename, typename> + struct A { }; + + template<typename ...T> + struct B { + A<T...> a1; + }; + + void test() { + B<int, int> c; + } +} + +namespace PR9021b { + template<class, class> + struct t2 + { + + }; + + template<template<class...> class M> + struct m + { + template<class... B> + using inner = M<B...>; + }; + + m<t2> sta2; +} + +namespace PartialSpecialization { + template<typename T, typename U, typename V = U> + struct X0; // expected-note{{template is declared here}} + + template<typename ...Ts> + struct X0<Ts...> { + }; + + X0<int> x0i; // expected-error{{too few template arguments for class template 'X0'}} + X0<int, float> x0if; + X0<int, float, double> x0ifd; +} + +namespace FixedAliasTemplate { + template<typename,typename,typename> struct S {}; + template<typename T, typename U> using U = S<T, int, U>; + template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); + S<int, int, double> &s1 = f({}, 0, 0.0); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp new file mode 100644 index 0000000..b5786ac --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Check for declaration matching with out-of-line declarations and +// variadic templates, which involves proper computation of the +// injected-class-name. +template<typename T, typename ...Types> +struct X0 { + typedef T type; + + void f0(T); + type f1(T); +}; + +template<typename T, typename ...Types> +void X0<T, Types...>::f0(T) { } + +template<typename T, typename ...Types> +typename X0<T, Types...>::type X0<T, Types...>::f1(T) { } + +template<typename T, typename ...Types> +struct X0<T, T, Types...> { + typedef T* result; + result f3(); + + template<typename... InnerTypes> + struct Inner; +}; + +template<typename T, typename ...Types> +typename X0<T, T, Types...>::result X0<T, T, Types...>::f3() { return 0; } + +template<typename T, typename ...Types> +template<typename ...InnerTypes> +struct X0<T, T, Types...>::Inner { + template<typename ...ReallyInner> void f4(); +}; + +template<typename T, typename ...Types> +template<typename ...InnerTypes> +template<typename ...ReallyInner> +void X0<T, T, Types...>::Inner<InnerTypes...>::f4() { } + +namespace rdar8848837 { + // Out-of-line definitions that cause rebuilding in the current + // instantiation. + template<typename F> struct X; + + template<typename R, typename ...ArgTypes> + struct X<R(ArgTypes...)> { + X<R(ArgTypes...)> f(); + }; + + template<typename R, typename ...ArgTypes> + X<R(ArgTypes...)> X<R(ArgTypes...)>::f() { return *this; } + + + X<int(float, double)> xif; + + template<unsigned> struct unsigned_c { }; + template<typename ...ArgTypes> int g(ArgTypes...); + + template<typename F> struct X1; + + template<typename R, typename ...ArgTypes> + struct X1<R(ArgTypes...)> { + unsigned_c<sizeof(1 + g(ArgTypes()...))> f(); + }; + + template<typename R, typename ...ArgTypes> + unsigned_c<sizeof(1 + g(ArgTypes()...))> X1<R(ArgTypes...)>::f() { + return unsigned_c<sizeof(int)>(); + } + + X1<int(float, double)> xif2; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp new file mode 100644 index 0000000..73cbd07 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp @@ -0,0 +1,274 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// This is a collection of various template metafunctions involving +// variadic templates, which are meant to exercise common use cases. +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...> struct tuple { }; +template<int ...> struct int_tuple { }; +template<typename T, typename U> struct pair { }; + +namespace Count { + template<typename Head, typename ...Tail> + struct count { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<typename T> + struct count<T> { + static const unsigned value = 1; + }; + + int check1[count<int>::value == 1? 1 : -1]; + int check2[count<float, double>::value == 2? 1 : -1]; + int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1]; +} + +namespace CountWithPackExpansion { + template<typename ...> struct count; + + template<typename Head, typename ...Tail> + struct count<Head, Tail...> { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<> + struct count<> { + static const unsigned value = 0; + }; + + int check0[count<>::value == 0? 1 : -1]; + int check1[count<int>::value == 1? 1 : -1]; + int check2[count<float, double>::value == 2? 1 : -1]; + int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1]; +} + +namespace Replace { + // Simple metafunction that replaces the template arguments of + // template template parameters with 'int'. + template<typename T> + struct EverythingToInt; + + template<template<typename ...> class TT, typename T1, typename T2> + struct EverythingToInt<TT<T1, T2> > { + typedef TT<int, int> type; + }; + + int check0[is_same<EverythingToInt<tuple<double, float>>::type, + tuple<int, int>>::value? 1 : -1]; +} + +namespace Math { + template<int ...Values> + struct double_values { + typedef int_tuple<Values*2 ...> type; + }; + + int check0[is_same<double_values<1, 2, -3>::type, + int_tuple<2, 4, -6>>::value? 1 : -1]; + + template<int ...Values> + struct square { + typedef int_tuple<(Values*Values)...> type; + }; + + int check1[is_same<square<1, 2, -3>::type, + int_tuple<1, 4, 9>>::value? 1 : -1]; + + template<typename IntTuple> struct square_tuple; + + template<int ...Values> + struct square_tuple<int_tuple<Values...>> { + typedef int_tuple<(Values*Values)...> type; + }; + + int check2[is_same<square_tuple<int_tuple<1, 2, -3> >::type, + int_tuple<1, 4, 9>>::value? 1 : -1]; + + template<int ...Values> struct sum; + + template<int First, int ...Rest> + struct sum<First, Rest...> { + static const int value = First + sum<Rest...>::value; + }; + + template<> + struct sum<> { + static const int value = 0; + }; + + int check3[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1]; + + template<int ... Values> + struct lazy_sum { + int operator()() { + return sum<Values...>::value; + } + }; + + void f() { + lazy_sum<1, 2, 3, 4, 5>()(); + } +} + +namespace ListMath { + template<typename T, T ... V> struct add; + + template<typename T, T i, T ... V> + struct add<T, i, V...> { + static const T value = i + add<T, V...>::value; + }; + + template<typename T> + struct add<T> { + static const T value = T(); + }; + + template<typename T, T ... V> + struct List { + struct sum { + static const T value = add<T, V...>::value; + }; + }; + + template<int ... V> + struct ListI : public List<int, V...> { + }; + + int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1]; +} + +namespace Indices { + template<unsigned I, unsigned N, typename IntTuple> + struct build_indices_impl; + + template<unsigned I, unsigned N, int ...Indices> + struct build_indices_impl<I, N, int_tuple<Indices...> > + : build_indices_impl<I+1, N, int_tuple<Indices..., I> > { + }; + + template<unsigned N, int ...Indices> + struct build_indices_impl<N, N, int_tuple<Indices...> > { + typedef int_tuple<Indices...> type; + }; + + template<unsigned N> + struct build_indices : build_indices_impl<0, N, int_tuple<> > { }; + + int check0[is_same<build_indices<5>::type, + int_tuple<0, 1, 2, 3, 4>>::value? 1 : -1]; +} + +namespace TemplateTemplateApply { + template<typename T, template<class> class ...Meta> + struct apply_each { + typedef tuple<typename Meta<T>::type...> type; + }; + + template<typename T> + struct add_reference { + typedef T& type; + }; + + template<typename T> + struct add_pointer { + typedef T* type; + }; + + template<typename T> + struct add_const { + typedef const T type; + }; + + int check0[is_same<apply_each<int, + add_reference, add_pointer, add_const>::type, + tuple<int&, int*, int const>>::value? 1 : -1]; + + template<typename T, template<class> class ...Meta> + struct apply_each_indirect { + typedef typename apply_each<T, Meta...>::type type; + }; + + int check1[is_same<apply_each_indirect<int, add_reference, add_pointer, + add_const>::type, + tuple<int&, int*, int const>>::value? 1 : -1]; + + template<typename T, typename ...Meta> + struct apply_each_nested { + typedef typename apply_each<T, Meta::template apply...>::type type; + }; + + struct add_reference_meta { + template<typename T> + struct apply { + typedef T& type; + }; + }; + + struct add_pointer_meta { + template<typename T> + struct apply { + typedef T* type; + }; + }; + + struct add_const_meta { + template<typename T> + struct apply { + typedef const T type; + }; + }; + + int check2[is_same<apply_each_nested<int, add_reference_meta, + add_pointer_meta, add_const_meta>::type, + tuple<int&, int*, int const>>::value? 1 : -1]; + +} + +namespace FunctionTypes { + template<typename FunctionType> + struct Arity; + + template<typename R, typename ...Types> + struct Arity<R(Types...)> { + static const unsigned value = sizeof...(Types); + }; + + template<typename R, typename ...Types> + struct Arity<R(Types......)> { + static const unsigned value = sizeof...(Types); + }; + + template<typename R, typename T1, typename T2, typename T3, typename T4> + struct Arity<R(T1, T2, T3, T4)>; // expected-note{{template is declared here}} + + int check0[Arity<int()>::value == 0? 1 : -1]; + int check1[Arity<int(float, double)>::value == 2? 1 : -1]; + int check2[Arity<int(float...)>::value == 1? 1 : -1]; + int check3[Arity<int(float, double, long double...)>::value == 3? 1 : -1]; + Arity<int(float, double, long double, char)> check4; // expected-error{{implicit instantiation of undefined template 'FunctionTypes::Arity<int (float, double, long double, char)>'}} +} + +namespace SuperReplace { + template<typename T> + struct replace_with_int { + typedef int type; + }; + + template<template<typename ...> class TT, typename ...Types> + struct replace_with_int<TT<Types...>> { + typedef TT<typename replace_with_int<Types>::type...> type; + }; + + int check0[is_same<replace_with_int<pair<tuple<float, double, short>, + pair<char, unsigned char>>>::type, + pair<tuple<int, int, int>, pair<int, int>>>::value? 1 : -1]; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp new file mode 100644 index 0000000..21aa24f --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp @@ -0,0 +1,251 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T, T ...Values> struct value_tuple {}; +template<typename...> struct tuple { }; +template<typename T, typename U> struct pair { }; + +template<typename T, T Value> struct value_c; + +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 X0 { + template<T ...Values> + void f(value_tuple<T, Values...> * = 0); +}; + +void test_X0() { + X0<int>().f<1, 2, 3, 4, 5>(); +} + +namespace PacksAtDifferentLevels { + + template<typename ...Types> + struct X { + template<typename> struct Inner { + static const unsigned value = 1; + }; + + template<typename ...YTypes> + struct Inner<tuple<pair<Types, YTypes>...> > { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check0[X<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>> + >::value == 0? 1 : -1]; + + int check1[X<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>> + >::value == 1? 1 : -1]; + + template<unsigned ...Values> struct unsigned_tuple { }; + template<typename ...Types> + struct X1 { + template<typename, typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...YTypes> + struct Inner<tuple<pair<Types, YTypes>...>, + unsigned_tuple<sizeof(Types) + sizeof(YTypes)...>> { + static const unsigned value = 1; + }; + }; + + int check2[X1<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + unsigned_tuple<sizeof(short) + sizeof(unsigned short), + sizeof(int) + sizeof(unsigned int), + sizeof(long) + sizeof(unsigned long)> + >::value == 1? 1 : -1]; + int check3[X1<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + unsigned_tuple<sizeof(short) + sizeof(unsigned short), + sizeof(int) + sizeof(unsigned int), + sizeof(long) + sizeof(unsigned long)> + >::value == 0? 1 : -1]; + + template<typename ...Types> + struct X2 { + template<typename> struct Inner { + static const unsigned value = 1; + }; + + template<typename R, typename ...YTypes> + struct Inner<R(pair<Types, YTypes>...)> { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check4[X2<short, int, long>::Inner<int(pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>) + >::value == 0? 1 : -1]; + + int check5[X2<short, int>::Inner<int(pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>) + >::value == 1? 1 : -1]; + + template<typename T, typename U> + struct some_function_object { + template<typename> + struct result_of; + }; + + template<template<class> class...> struct metafun_tuple { }; + + template<typename ...Types1> + struct X3 { + template<typename, typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...Types2> + struct Inner<tuple<pair<Types1, Types2>...>, + metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > { + static const unsigned value = 1; + }; + }; + + int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + metafun_tuple< + some_function_object<short, unsigned short>::result_of, + some_function_object<int, unsigned int>::result_of, + some_function_object<long, unsigned long>::result_of> + >::value == 1? 1 : -1]; + int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + metafun_tuple< + some_function_object<short, unsigned short>::result_of, + some_function_object<int, unsigned int>::result_of, + some_function_object<long, unsigned long>::result_of> + >::value == 0? 1 : -1]; + + template<unsigned I, unsigned J> struct unsigned_pair { }; + + template<unsigned ...Values1> + struct X4 { + template<typename> struct Inner { + static const unsigned value = 0; + }; + + template<unsigned ...Values2> + struct Inner<tuple<unsigned_pair<Values1, Values2>...>> { + static const unsigned value = 1; + }; + }; + + int check8[X4<1, 3, 5>::Inner<tuple<unsigned_pair<1, 2>, + unsigned_pair<3, 4>, + unsigned_pair<5, 6>> + >::value == 1? 1 : -1]; + int check9[X4<1, 3>::Inner<tuple<unsigned_pair<1, 2>, + unsigned_pair<3, 4>, + unsigned_pair<5, 6>> + >::value == 0? 1 : -1]; + + template<class> struct add_reference; + template<class> struct add_pointer; + template<class> struct add_const; + + template<template<class> class ...Templates> + struct X5 { + template<typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...Types> + struct Inner<tuple<Templates<Types>...>> { + static const unsigned value = 1; + }; + }; + + int check10[X5<add_reference, add_pointer, add_const> + ::Inner<tuple<add_reference<int>, + add_pointer<float>, + add_const<double>>>::value == 1? 1 : -1]; + int check11[X5<add_reference, add_pointer> + ::Inner<tuple<add_reference<int>, + add_pointer<float>, + add_const<double>>>::value == 0? 1 : -1]; + +} + +namespace ExpandingNonTypeTemplateParameters { + template<typename ...Types> + struct tuple_of_values { + template<Types ...Values> // expected-error{{a non-type template parameter cannot have type 'float'}} \ + // expected-note{{template parameter is declared here}} + struct apply { // expected-note 2{{template is declared here}} + typedef tuple<value_c<Types, Values>...> type; + }; + }; + + int i; + float f; + int check_tuple_of_values_1[ + is_same<tuple_of_values<int&, float&, char, int>::apply<i, f, 'a', 17> + ::type, + tuple<value_c<int&, i>, value_c<float&, f>, value_c<char, 'a'>, + value_c<int, 17>> + >::value? 1 : -1]; + + tuple_of_values<int, float> tv1; // expected-note{{in instantiation of template class 'ExpandingNonTypeTemplateParameters::tuple_of_values<int, float>' requested here}} + + tuple_of_values<int&, float&>::apply<i, i>::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}} + + tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{too few template arguments for class template 'apply'}} + + tuple_of_values<int&, float&>::apply<i, f, i>::type tv4; // expected-error{{too many template arguments for class template 'apply'}} +} + +namespace ExpandingFunctionParameters { + template<typename ...T> + struct X0 { + typedef int type; + }; + + template<typename ...T> + struct X1 { + template<typename ... U> + typename X0<T(T, U...)...>::type f(U...); + }; + + void test() { + X1<float> x1; + x1.f(17, 3.14159); + } +} + +namespace PR10230 { + template<typename> + struct s + { + template<typename... Args> + auto f() -> int(&)[sizeof...(Args)]; + }; + + void main() + { + int (&ir1)[1] = s<int>().f<int>(); + int (&ir3)[3] = s<int>().f<int, float, double>(); + } +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp new file mode 100644 index 0000000..daff9d1 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<class ...Types> struct Tuple; + +Tuple<> *t0; +Tuple<int> *t1; +Tuple<int, char> *t2a; +Tuple<int, float> *t2b = t2a; // expected-error{{cannot initialize a variable of type 'Tuple<int, float> *' with an lvalue of type 'Tuple<int, char> *'}} +Tuple<int, float, double> *t3; diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp new file mode 100644 index 0000000..ce19582 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<class ... Types> void f(Types ... args); + +void test() { + f(); + f(1); + f(2, 1.0); +} + +// Test simple recursive variadic function template +template<typename Head, typename ...Tail> +void recurse_until_fail(const Head &, const Tail &...tail) { // expected-note{{candidate function template not viable: requires at least 1 argument, but 0 were provided}} + recurse_until_fail(tail...); // expected-error{{no matching function for call to 'recurse_until_fail'}} \ + // expected-note{{in instantiation of function template specialization 'recurse_until_fail<char [7], >' requested here}} \ + // expected-note{{in instantiation of function template specialization 'recurse_until_fail<double, char [7]>' requested here}} +} + +void test_recurse_until_fail() { + recurse_until_fail(1, 3.14159, "string"); // expected-note{{in instantiation of function template specialization 'recurse_until_fail<int, double, char [7]>' requested here}} + +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp new file mode 100644 index 0000000..d8294a1 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -0,0 +1,193 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fexceptions -fcxx-exceptions -verify %s + +template<typename... Types> struct tuple; +template<int I> struct int_c; + +template<typename T> +struct identity { + typedef T type; +}; + +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; +}; + +// FIXME: Several more bullets to go + +// In a function parameter pack, the pattern is the parameter-declaration +// without the ellipsis. +namespace PR11850 { + template<typename ...T> struct S { + int f(T...a, int b) { return b; } + }; + S<> s; + S<int*, char, const double&> t; + int k = s.f(0); + int l = t.f(&k, 'x', 5.9, 4); + + template<typename ...As> struct A { + template<typename ...Bs> struct B { + template<typename ...Cs> struct C { + C(As..., Bs..., int &k, Cs...); + }; + }; + }; + A<>::B<>::C<> c000(k); + A<int>::B<>::C<int> c101(1, k, 3); + A<>::B<int>::C<int> c011(1, k, 3); + A<int>::B<int>::C<> c110(1, 2, k); + A<int, int>::B<int, int>::C<int, int> c222(1, 2, 3, 4, k, 5, 6); + A<int, int, int>::B<>::C<> c300(1, 2, 3, k); + + int &f(); + char &f(void*); + template<typename ...A> struct U { + template<typename ...B> struct V { + auto g(A...a, B...b) -> decltype(f(a...)); + }; + }; + U<>::V<int*> v0; + U<int*>::V<> v1; + int &v0f = v0.g(0); + char &v1f = v1.g(0); +} +namespace PR12096 { + void Foo(int) {} + void Foo(int, int) = delete; + template<typename ...Args> struct Var { + Var(const Args &...args, int *) { Foo(args...); } + }; + Var<int> var(1, 0); +} + +// In an initializer-list (8.5); the pattern is an initializer-clause. +// Note: this also covers expression-lists, since expression-list is +// just defined as initializer-list. +void five_args(int, int, int, int, int); // expected-note{{candidate function not viable: requires 5 arguments, but 6 were provided}} + +template<int ...Values> +void initializer_list_expansion() { + int values[5] = { Values... }; // expected-error{{excess elements in array initializer}} + five_args(Values...); // expected-error{{no matching function for call to 'five_args'}} +} + +template void initializer_list_expansion<1, 2, 3, 4, 5>(); +template void initializer_list_expansion<1, 2, 3, 4, 5, 6>(); // expected-note{{in instantiation of function template specialization 'initializer_list_expansion<1, 2, 3, 4, 5, 6>' requested here}} + +namespace PR8977 { + struct A { }; + template<typename T, typename... Args> void f(Args... args) { + // An empty expression-list performs value initialization. + constexpr T t(args...); + }; + + template void f<A>(); +} + +// In a base-specifier-list (Clause 10); the pattern is a base-specifier. +template<typename ...Mixins> +struct HasMixins : public Mixins... { + HasMixins(); + HasMixins(const HasMixins&); + HasMixins(int i); +}; + +struct A { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}} \ +// expected-note{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A' for 1st argument}} \ +// expected-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} +struct B { }; +struct C { }; +struct D { }; + +A *checkA = new HasMixins<A, B, C, D>; +B *checkB = new HasMixins<A, B, C, D>; +D *checkD = new HasMixins<A, B, C, D>; +C *checkC = new HasMixins<A, B, D>; // expected-error{{cannot initialize a variable of type 'C *' with an rvalue of type 'HasMixins<A, B, D> *'}} +HasMixins<> *checkNone = new HasMixins<>; + +template<typename Mixins> +struct BrokenMixins : public Mixins... { }; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + +// In a mem-initializer-list (12.6.2); the pattern is a mem-initializer. +template<typename ...Mixins> +HasMixins<Mixins...>::HasMixins(): Mixins()... { } + +template<typename ...Mixins> +HasMixins<Mixins...>::HasMixins(const HasMixins &other): Mixins(other)... { } + +template<typename ...Mixins> +HasMixins<Mixins...>::HasMixins(int i): Mixins(i)... { } // expected-error{{no matching constructor for initialization of 'A'}} + +void test_has_mixins() { + HasMixins<A, B> ab; + HasMixins<A, B> ab2 = ab; + HasMixins<A, B> ab3(17); // expected-note{{in instantiation of member function 'HasMixins<A, B>::HasMixins' requested here}} +} + +template<typename T> +struct X { + T member; + + X() : member()... { } // expected-error{{pack expansion for initialization of member 'member'}} +}; + +// There was a bug in the delayed parsing code for the +// following case. +template<typename ...T> +struct DelayedParseTest : T... +{ + int a; + DelayedParseTest(T... i) : T{i}..., a{10} {} +}; + + +// In a template-argument-list (14.3); the pattern is a template-argument. +template<typename ...Types> +struct tuple_of_refs { + typedef tuple<Types& ...> types; +}; + +tuple<int&, float&> *t_int_ref_float_ref; +tuple_of_refs<int&, float&>::types *t_int_ref_float_ref_2 = t_int_ref_float_ref; + +template<typename ...Types> +struct extract_nested_types { + typedef tuple<typename Types::type...> types; +}; + +tuple<int, float> *t_int_float; +extract_nested_types<identity<int>, identity<float> >::types *t_int_float_2 + = t_int_float; + +template<int ...N> +struct tuple_of_ints { + typedef tuple<int_c<N>...> type; +}; + +int check_temp_arg_1[is_same<tuple_of_ints<1, 2, 3, 4, 5>::type, + tuple<int_c<1>, int_c<2>, int_c<3>, int_c<4>, + int_c<5>>>::value? 1 : -1]; + +// In a dynamic-exception-specification (15.4); the pattern is a type-id. +template<typename ...Types> +struct f_with_except { + virtual void f() throw(Types...); // expected-note{{overridden virtual function is here}} +}; + +struct check_f_with_except_1 : f_with_except<int, float> { + virtual void f() throw(int, float); +}; + +struct check_f_with_except_2 : f_with_except<int, float> { + virtual void f() throw(int); +}; + +struct check_f_with_except_3 : f_with_except<int, float> { + virtual void f() throw(int, float, double); // expected-error{{exception specification of overriding function is more lax than base version}} +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp new file mode 100644 index 0000000..726e222 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -0,0 +1,403 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -fblocks -fms-extensions -fsyntax-only -verify %s + +template<typename T, typename U> struct pair; +template<typename ...> struct tuple; + +// A parameter pack whose name appears within the pattern of a pack +// expansion is expanded by that pack expansion. An appearance of the +// name of a parameter pack is only expanded by the innermost +// enclosing pack expansion. The pattern of a pack expansion shall +// name one or more parameter packs that are not expanded by a nested +// pack expansion. +template<typename... Types> +struct Expansion { + typedef pair<Types..., int> expand_with_pacs; // okay + typedef pair<Types, int...> expand_no_packs; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + typedef pair<pair<Types..., int>..., int> expand_with_expanded_nested; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} +}; + +// All of the parameter packs expanded by a pack expansion shall have +// the same number of arguments specified. +template<typename ...Types> +struct ExpansionLengthMismatch { + template<typename ...OtherTypes> + struct Inner { + typedef tuple<pair<Types, OtherTypes>...> type; // expected-error{{pack expansion contains parameter packs 'Types' and 'OtherTypes' that have different lengths (3 vs. 2)}} + }; +}; + +ExpansionLengthMismatch<int, long>::Inner<unsigned int, unsigned long>::type + *il_pairs; +tuple<pair<int, unsigned int>, pair<long, unsigned long> >*il_pairs_2 = il_pairs; + +ExpansionLengthMismatch<short, int, long>::Inner<unsigned int, unsigned long>::type // expected-note{{in instantiation of template class 'ExpansionLengthMismatch<short, int, long>::Inner<unsigned int, unsigned long>' requested here}} + *il_pairs_bad; + + +// An appearance of a name of a parameter pack that is not expanded is +// ill-formed. + +// Test for unexpanded parameter packs in each of the type nodes. +template<typename T, int N, typename ... Types> +struct TestPPName + : public Types, public T // expected-error{{base type contains unexpanded parameter pack 'Types'}} +{ + // BuiltinType is uninteresting + // FIXME: ComplexType is uninteresting? + // PointerType + typedef Types *types_pointer; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // BlockPointerType + typedef Types (^block_pointer_1)(int); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef int (^block_pointer_2)(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // LValueReferenceType + typedef Types &lvalue_ref; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // RValueReferenceType + typedef Types &&rvalue_ref; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // MemberPointerType + typedef Types TestPPName::* member_pointer_1; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef int Types::*member_pointer_2; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // ConstantArrayType + typedef Types constant_array[17]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // IncompleteArrayType + typedef Types incomplete_array[]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // VariableArrayType + void f(int i) { + Types variable_array[i]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + } + + // DependentSizedArrayType + typedef Types dependent_sized_array[N]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // DependentSizedExtVectorType + typedef Types dependent_sized_ext_vector __attribute__((ext_vector_type(N))); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // VectorType is uninteresting + + // ExtVectorType + typedef Types ext_vector __attribute__((ext_vector_type(4))); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // FunctionProtoType + typedef Types (function_type_1)(int); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef int (function_type_2)(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // FunctionNoProtoType is uninteresting + // UnresolvedUsingType is uninteresting + // ParenType is uninteresting + // TypedefType is uninteresting + + // TypeOfExprType + typedef __typeof__((static_cast<Types>(0))) typeof_expr; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // TypeOfType + typedef __typeof__(Types) typeof_type; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // DecltypeType + typedef decltype((static_cast<Types>(0))) typeof_expr; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // RecordType is uninteresting + // EnumType is uninteresting + // ElaboratedType is uninteresting + + // TemplateTypeParmType + typedef Types template_type_parm; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // SubstTemplateTypeParmType is uninteresting + + // TemplateSpecializationType + typedef pair<Types, int> template_specialization; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // InjectedClassName is uninteresting. + + // DependentNameType + typedef typename Types::type dependent_name; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // DependentTemplateSpecializationType + typedef typename Types::template apply<int> dependent_name_1; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef typename T::template apply<Types> dependent_name_2; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // ObjCObjectType is uninteresting + // ObjCInterfaceType is uninteresting + // ObjCObjectPointerType is uninteresting +}; + +// FIXME: Test for unexpanded parameter packs in each of the expression nodes. +template<int ...Values> +void test_unexpanded_in_exprs() { + // PredefinedExpr is uninteresting + // DeclRefExpr + Values; // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // IntegerLiteral is uninteresting + // FloatingLiteral is uninteresting + // ImaginaryLiteral is uninteresting + // StringLiteral is uninteresting + // CharacterLiteral is uninteresting + (Values); // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // UnaryOperator + -Values; // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // OffsetOfExpr + struct OffsetMe { + int array[17]; + }; + __builtin_offsetof(OffsetMe, array[Values]); // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // FIXME: continue this... +} + +template<typename ... Types> +void TestPPNameFunc(int i) { + f(static_cast<Types>(i)); // expected-error{{expression contains unexpanded parameter pack 'Types'}} +} + +template<typename T, template<class> class ...Meta> +struct TestUnexpandedTTP { + typedef tuple<typename Meta<T>::type> type; // expected-error{{declaration type contains unexpanded parameter pack 'Meta'}} +}; + +// Test for unexpanded parameter packs in declarations. +template<typename T, typename... Types> +// FIXME: this should test that the diagnostic reads "type contains..." +struct alignas(Types) TestUnexpandedDecls : T{ // expected-error{{expression contains unexpanded parameter pack 'Types'}} + void member_function(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + void member_function () throw(Types); // expected-error{{exception type contains unexpanded parameter pack 'Types'}} + operator Types() const; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + Types data_member; // expected-error{{data member type contains unexpanded parameter pack 'Types'}} + static Types static_data_member; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + unsigned bit_field : static_cast<Types>(0); // expected-error{{bit-field size contains unexpanded parameter pack 'Types'}} + static_assert(static_cast<Types>(0), "Boom"); // expected-error{{static assertion contains unexpanded parameter pack 'Types'}} + + enum E0 : Types { // expected-error{{fixed underlying type contains unexpanded parameter pack 'Types'}} + EnumValue = static_cast<Types>(0) // expected-error{{enumerator value contains unexpanded parameter pack 'Types'}} + }; + + using typename Types::type; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}} + using Types::value; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}} + using T::operator Types; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}} + + friend class Types::foo; // expected-error{{friend declaration contains unexpanded parameter pack 'Types'}} + friend void friend_func(Types); // expected-error{{friend declaration contains unexpanded parameter pack 'Types'}} + friend void Types::other_friend_func(int); // expected-error{{friend declaration contains unexpanded parameter pack 'Types'}} + + void test_initializers() { + T copy_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + T direct_init(0, static_cast<Types>(0)); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + T list_init = { static_cast<Types>(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + } + + T in_class_member_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + TestUnexpandedDecls() : + Types(static_cast<Types>(0)), // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + Types(static_cast<Types>(0))..., + in_class_member_init(static_cast<Types>(0)) {} // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + + void default_function_args(T = static_cast<Types>(0)); // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + + template<typename = Types*> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_1; + template<int = static_cast<Types>(0)> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_2; + template<template<typename> class = Types::template apply> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_3; + + template<Types value> // expected-error{{non-type template parameter type contains unexpanded parameter pack 'Types'}} + struct non_type_template_param_type; + + void decls_in_stmts() { + Types t; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + for (Types *t = 0; ; ) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + for (; Types *t = 0; ) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + T a[] = { T(), T(), T() }; + for (Types t : a) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + switch(Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + while(Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + if (Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + try { + } catch (Types*) { // expected-error{{exception type contains unexpanded parameter pack 'Types'}} + } + } +}; + +// FIXME: Test for unexpanded parameter packs in each of the statements. +struct X { + void f(int, int); + template<typename ...Types> + void f(Types...); +}; + +namespace std { + class type_info; +} + +typedef struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; +} GUID; + +template<typename T, typename ...Types> +void test_unexpanded_exprs(Types ...values) { + // CXXOperatorCallExpr + (void)(values + 0); // expected-error{{expression contains unexpanded parameter pack 'values'}} + (void)(0 + values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXMemberCallExpr + values.f(); // expected-error{{expression contains unexpanded parameter pack 'values'}} + X x; + x.f(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + x.Types::f(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + x.f<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXStaticCastExpr + (void)static_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXDynamicCastExpr + (void)dynamic_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXReinterpretCastExpr + (void)reinterpret_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXConstCastExpr + (void)const_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXTypeidExpr + (void)typeid(Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + (void)typeid(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXUuidofExpr + (void)__uuidof(Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + (void)__uuidof(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXThisExpr is uninteresting + + // CXXThrowExpr + throw Types(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + throw values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXDefaultArgExpr is uninteresting + + // CXXBindTemporaryExpr is uninteresting + + // CXXConstructExpr is uninteresting + + // CXXFunctionalCastExpr + (void)Types(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXTemporaryObjectExpr + (void)X(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXScalarValueInitExpr is uninteresting + + // CXXNewExpr + (void)new Types; // expected-error{{expression contains unexpanded parameter pack 'Types'}} + (void)new X(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + (void)new (values) X(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + (void)new X [values]; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXDeleteExpr + delete values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + delete [] values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXPseudoDestructorExpr + T t; + values.~T(); // expected-error{{expression contains unexpanded parameter pack 'values'}} + t.~Types(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + t.Types::~T(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnaryTypeTraitExpr + __is_pod(Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // BinaryTypeTraitExpr + __is_base_of(Types, T); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + __is_base_of(T, Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnresolvedLookupExpr + test_unexpanded_exprs(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + test_unexpanded_exprs<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // DependentScopeDeclRefExpr + Types::test_unexpanded_exprs(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + T::template test_unexpanded_exprs<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXUnresolvedConstructExpr + Types(5); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXDependentScopeMemberExpr + values.foo(); // expected-error{{expression contains unexpanded parameter pack 'values'}} + t.foo(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // FIXME: There's an evil ambiguity here, because we don't know if + // Types refers to the template type parameter pack in scope or a + // non-pack member. + // t.Types::foo(); + + t.template foo<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnresolvedMemberExpr + x.f<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + x.f(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXNoexceptExpr + noexcept(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // PackExpansionExpr is uninteresting + // SizeOfPackExpr is uninteresting + + // FIXME: Objective-C expressions will need to go elsewhere + + for (auto t : values) { } // expected-error{{expression contains unexpanded parameter pack 'values'}} +} + +// Test unexpanded parameter packs in partial specializations. +template<typename ...Types> +struct TestUnexpandedDecls<int, Types>; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}} + +// Test for diagnostics in the presence of multiple unexpanded +// parameter packs. +template<typename T, typename U> struct pair; + +template<typename ...OuterTypes> +struct MemberTemplatePPNames { + template<typename ...InnerTypes> + struct Inner { + typedef pair<OuterTypes, InnerTypes>* types; // expected-error{{declaration type contains unexpanded parameter packs 'OuterTypes' and 'InnerTypes'}} + + template<typename ...VeryInnerTypes> + struct VeryInner { + typedef pair<pair<VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types; // expected-error{{declaration type contains unexpanded parameter packs 'VeryInnerTypes', 'OuterTypes', ...}} + }; + }; +}; + +// Example from working paper +namespace WorkingPaperExample { + template<typename...> struct Tuple {}; + template<typename T1, typename T2> struct Pair {}; + + template<class ... Args1> struct zip { + template<class ... Args2> struct with { + typedef Tuple<Pair<Args1, Args2> ... > type; // expected-error{{pack expansion contains parameter packs 'Args1' and 'Args2' that have different lengths (1 vs. 2)}} + }; + }; + + typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> + typedef Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> T1; + + typedef zip<short>::with<unsigned short, unsigned>::type T2; // expected-note{{in instantiation of template class}} + + template<class ... Args> void f(Args...); + template<class ... Args> void h(Args...); + + template<class ... Args> + void g(Args ... args) { + f(const_cast<const Args*>(&args)...); // OK: "Args" and "args" are expanded within f + f(5 ...); // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + f(args); // expected-error{{expression contains unexpanded parameter pack 'args'}} + f(h(args ...) + args ...); + } +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp new file mode 100644 index 0000000..79340c3 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Check for template type parameter pack (mis-)matches with template +// type parameters. +template<typename ...T> struct X0t; +template<typename ...T> struct X0t; + +template<typename ...T> struct X1t; // expected-note{{previous template type parameter pack declared here}} +template<typename T> struct X1t; // expected-error{{template type parameter conflicts with previous template type parameter pack}} + +template<typename T> struct X2t; // expected-note{{previous template type parameter declared here}} +template<typename ...T> struct X2t; // expected-error{{template type parameter pack conflicts with previous template type parameter}} + +template<template<typename ...T> class> struct X0t_intt; +template<template<typename ...T> class> struct X0t_intt; + +template<template<typename ...T> class> struct X1t_intt; // expected-note{{previous template type parameter pack declared here}} +template<template<typename T> class> struct X1t_intt; // expected-error{{template type parameter conflicts with previous template type parameter pack}} + +template<template<typename T> class> struct X2t_intt; // expected-note{{previous template type parameter declared here}} +template<template<typename ...T> class> struct X2t_intt; // expected-error{{template type parameter pack conflicts with previous template type parameter}} + +template<int ...Values> struct X1nt; // expected-note{{previous non-type template parameter pack declared here}} +template<int Values> struct X1nt; // expected-error{{non-type template parameter conflicts with previous non-type template parameter pack}} + +template<template<class T> class> class X1tt; // expected-note{{previous template template parameter declared here}} +template<template<class T> class...> class X1tt; // expected-error{{template template parameter pack conflicts with previous template template parameter}} + +// Check for matching with out-of-line definitions +namespace rdar8859985 { + template<typename ...> struct tuple { }; + template<int ...> struct int_tuple { }; + + template<typename T> + struct X { + template<typename ...Args1, int ...Indices1> + X(tuple<Args1...>, int_tuple<Indices1...>); + }; + + template<typename T> + template<typename ...Args1, int ...Indices1> + X<T>::X(tuple<Args1...>, int_tuple<Indices1...>) {} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp new file mode 100644 index 0000000..71bd6aa --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Various tests related to partial ordering of variadic templates. +template<typename ...Types> struct tuple; + +template<typename Tuple> +struct X1 { + static const unsigned value = 0; +}; + +template<typename Head, typename ...Tail> +struct X1<tuple<Head, Tail...> > { + static const unsigned value = 1; +}; + +template<typename Head, typename ...Tail> +struct X1<tuple<Head, Tail&...> > { + static const unsigned value = 2; +}; + +template<typename Head, typename ...Tail> +struct X1<tuple<Head&, Tail&...> > { + static const unsigned value = 3; +}; + +int check0[X1<tuple<>>::value == 0? 1 : -1]; +int check1[X1<tuple<int>>::value == 2? 1 : -1]; +int check2[X1<tuple<int, int>>::value == 1? 1 : -1]; +int check3[X1<tuple<int, int&>>::value == 2? 1 : -1]; +int check4[X1<tuple<int&, int&>>::value == 3? 1 : -1]; + +// Partial ordering of function templates. +template<typename T1, typename T2, typename ...Rest> +int &f0(T1, T2, Rest...); + +template<typename T1, typename T2> +float &f0(T1, T2); + +void test_f0() { + int &ir1 = f0(1, 2.0, 'a'); + float &fr1 = f0(1, 2.0); +} + +template<typename T1, typename T2, typename ...Rest> +int &f1(T1, T2, Rest...); + +template<typename T1, typename T2> +float &f1(T1, T2, ...); + +void test_f1() { + int &ir1 = f1(1, 2.0, 'a'); +} + +template<typename T1, typename T2, typename ...Rest> +int &f2(T1, T2, Rest...); + +float &f2(...); + +void test_f2() { + int &ir1 = f2(1, 2.0, 'a'); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp new file mode 100644 index 0000000..0aef6ad --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> struct A { }; + +template<typename T> T make(); +template<typename T> T make2(const T&); + +void test_make() { + int& ir0 = make<int&>(); + A<int> a0 = make< A<int> >(); + A<int> a1 = make2< A<int> >(A<int>()); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp new file mode 100644 index 0000000..4d29b74 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +namespace ParameterPacksWithFunctions { + template<typename ...> struct count; + + template<typename Head, typename ...Tail> + struct count<Head, Tail...> { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<> + struct count<> { + static const unsigned value = 0; + }; + + template<unsigned> struct unsigned_c { }; + + template<typename ... Types> + unsigned_c<count<Types...>::value> f(); + + void test_f() { + unsigned_c<0> uc0a = f(); // okay, deduced to an empty pack + unsigned_c<0> uc0b = f<>(); + unsigned_c<1> uc1 = f<int>(); + unsigned_c<2> uc2 = f<float, double>(); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp new file mode 100644 index 0000000..de3b44f --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5811 +template <class F> void Call(F f) { f(1); } +template <typename T> void f(T); +void a() { Call(f<int>); } + +// Check the conversion of a template-id to a pointer +template<typename T, T* Address> struct Constant { }; +Constant<void(int), &f<int> > constant0; + +template<typename T, T* Address> void constant_func(); +void test_constant_func() { + constant_func<void(int), &f<int> >(); +} + + +// Check typeof() on a template-id referring to a single function +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 typeof0[is_same<__typeof__(f<int>), void (int)>::value? 1 : -1]; +int typeof1[is_same<__typeof__(&f<int>), void (*)(int)>::value? 1 : -1]; + +template <typename T> void g(T); // expected-note{{possible target for call}} +template <typename T> void g(T, T); // expected-note{{possible target for call}} + +int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \ + // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp new file mode 100644 index 0000000..5556f35 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} + +void g() { + f<int,char*,double>("aa",3.0); // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int,char*>("aa",3.0); // Z is deduced to be double \ + // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int>("aa",3.0); // Y is deduced to be char*, and + // Z is deduced to be double + f("aa",3.0); // expected-error{{no matching}} +} + +// PR5910 +namespace PR5910 { + template <typename T> + void Func() {} + + template <typename R> + void Foo(R (*fp)()); + + void Test() { + Foo(Func<int>); + } +} + +// PR5949 +namespace PR5949 { + struct Bar; + + template <class Container> + void quuz(const Container &cont) { + } + + template<typename T> + int Foo(Bar *b, void (*Baz)(const T &t), T * = 0) { + return 0; + } + + template<typename T> + int Quux(Bar *b, T * = 0) + { + return Foo<T>(b, quuz); + } +} + +// PR7641 +namespace PR7641 { + namespace N2 + { + template<class> + int f0(int); + } + namespace N + { + using N2::f0; + } + + template<class R,class B1> + int + f1(R(a)(B1)); + + void f2() + { f1(N::f0<int>); } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp new file mode 100644 index 0000000..81addfe --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +// Test explicit specification of function template arguments. +void test_explicit_spec_simple() { + int *ip1 = first_arg<int *>(0); + int *ip2 = first_arg<int *, float*>(0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); +} + +// Template argument deduction can extend the sequence of template +// arguments corresponding to a template parameter pack, even when the +// sequence contains explicitly specified template arguments. +void test_explicit_spec_extension(double *dp) { + int *ip1 = first_arg<int *>(0, 0); + int *ip2 = first_arg<int *, float*>(0, 0, 0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); + int *i1 = second_arg<float *>(0, (int*)0, 0); + double *dp1 = first_arg<>(dp); +} + +template<typename ...Types> +struct tuple { }; + +template<typename ...Types> +void accept_tuple(tuple<Types...>); + +void test_explicit_spec_extension_targs(tuple<int, float, double> t3) { + accept_tuple(t3); + accept_tuple<int, float, double>(t3); + accept_tuple<int>(t3); + accept_tuple<int, float>(t3); +} + +template<typename R, typename ...ParmTypes> +void accept_function_ptr(R(*)(ParmTypes...)); + +void test_explicit_spec_extension_funcparms(int (*f3)(int, float, double)) { + accept_function_ptr(f3); + accept_function_ptr<int>(f3); + accept_function_ptr<int, int>(f3); + accept_function_ptr<int, int, float>(f3); + accept_function_ptr<int, int, float, double>(f3); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp new file mode 100644 index 0000000..c14b063 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +#if !__has_feature(cxx_access_control_sfinae) +# error No support for access control as part of SFINAE? +#endif + +typedef char yes_type; +typedef char (&no_type)[2]; + +template<unsigned N> struct unsigned_c { }; + +template<typename T> +class has_copy_constructor { + static T t; + + template<typename U> static yes_type check(unsigned_c<sizeof(U(t))> * = 0); + template<typename U> static no_type check(...); + +public: + static const bool value = (sizeof(check<T>(0)) == sizeof(yes_type)); +}; + +struct HasCopy { }; + +struct HasNonConstCopy { + HasNonConstCopy(HasNonConstCopy&); +}; + +struct HasDeletedCopy { + HasDeletedCopy(const HasDeletedCopy&) = delete; +}; + +struct HasPrivateCopy { +private: + HasPrivateCopy(const HasPrivateCopy&); +}; + +int check0[has_copy_constructor<HasCopy>::value? 1 : -1]; +int check1[has_copy_constructor<HasNonConstCopy>::value? 1 : -1]; +int check2[has_copy_constructor<HasDeletedCopy>::value? -1 : 1]; +int check3[has_copy_constructor<HasPrivateCopy>::value? -1 : 1]; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp new file mode 100644 index 0000000..c27261c --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <int> int f(int); // expected-note 2{{candidate}} +template <signed char> int f(int); // expected-note 2{{candidate}} +int i1 = f<1>(0); // expected-error{{ambiguous}} +int i2 = f<1000>(0); // expected-error{{ambiguous}} + +namespace PR6707 { + template<typename T, T Value> + struct X { }; + + template<typename T, T Value> + void f(X<T, Value>); + + void g(X<int, 10> x) { + f(x); + } + + static const unsigned char ten = 10; + template<typename T, T Value, typename U> + void f2(X<T, Value>, X<U, Value>); + + void g2() { + f2(X<int, 10>(), X<char, ten>()); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp new file mode 100644 index 0000000..6481485 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -verify %s + +typedef char one_byte; +struct two_bytes { char data[2]; }; + +template<typename T> one_byte __is_class_check(int T::*); +template<typename T> two_bytes __is_class_check(...); + +template<typename T> struct is_class { + static const bool value = sizeof(__is_class_check<T>(0)) == 1; +}; + +struct X { }; + +int array0[is_class<X>::value? 1 : -1]; +int array1[is_class<int>::value? -1 : 1]; +int array2[is_class<char[3]>::value? -1 : 1]; + +namespace instantiation_order1 { + template<typename T> + struct it_is_a_trap { + typedef typename T::trap type; + }; + + template<bool, typename T = void> + struct enable_if { + typedef T type; + }; + + template<typename T> + struct enable_if<false, T> { }; + + template<typename T> + typename enable_if<sizeof(T) == 17>::type + f(const T&, typename it_is_a_trap<T>::type* = 0); + + void f(...); + + void test_f() { + f('a'); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp new file mode 100644 index 0000000..90d2949 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +template<typename T> A<T> f0(T*); + +void test_f0(int *ip, float const *cfp) { + A<int> a0 = f0(ip); + A<const float> a1 = f0(cfp); +} + +template<typename T> void f1(T*, int); + +void test_f1(int *ip, float fv) { + f1(ip, fv); +} + +// TODO: this diagnostic can and should improve +template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: failed template argument deduction}} \ +// expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'float')}} + +struct ConvToIntPtr { + operator int*() const; +}; + +void test_f2(int *ip, float *fp) { + f2(ip, ConvToIntPtr()); // expected-error{{no matching function}} + f2(ip, ip); // okay + f2(ip, fp); // expected-error{{no matching function}} +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp new file mode 100644 index 0000000..8b192fa --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename T, typename U> struct pair { }; +template<typename T, typename U> pair<T, U> make_pair(T, U); + +// For a function parameter pack that occurs at the end of the +// parameter-declaration-list, the type A of each remaining argument +// of the call is compared with the type P of the declarator-id of the +// function parameter pack. +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +void test_simple_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg(ip); + int *ip2 = first_arg(ip, fp); + int *ip3 = first_arg(ip, fp, dp); + no_type nt1 = first_arg(); +} + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg_ref(Args&...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg_ref(Args&...); + +void test_simple_ref_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg_ref(ip); + int *ip2 = first_arg_ref(ip, fp); + int *ip3 = first_arg_ref(ip, fp, dp); + no_type nt1 = first_arg_ref(); +} + + +template<typename ...Args1, typename ...Args2> +typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: failed template argument deduction}} + +template<typename ...Args1, typename ...Args2> +typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...); + +void test_pair_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg_pair(make_pair(ip, 17)); + int *ip2 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); + int *ip3 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17), + make_pair(dp, 17)); + float *fp1 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); + float *fp2 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17), + make_pair(dp, 17)); + no_type nt1 = first_arg_pair(); + no_type nt2 = second_arg_pair(); + no_type nt3 = second_arg_pair(make_pair(ip, 17)); + + + first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}} +} + +// For a function parameter pack that does not occur at the end of the +// parameter-declaration-list, the type of the parameter pack is a +// non-deduced context. +template<typename ...Types> struct tuple { }; + +template<typename ...Types> +void pack_not_at_end(tuple<Types...>, Types... values, int); + +void test_pack_not_at_end(tuple<int*, double*> t2) { + pack_not_at_end(t2, 0, 0, 0); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp new file mode 100644 index 0000000..c165c45 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> struct A { }; + +// bullet 1 +template<typename T> A<T> f0(T* ptr); + +void test_f0_bullet1() { + int arr0[6]; + A<int> a0 = f0(arr0); + const int arr1[] = { 1, 2, 3, 4, 5 }; + A<const int> a1 = f0(arr1); +} + +// bullet 2 +int g0(int, int); +float g1(float); + +void test_f0_bullet2() { + A<int(int, int)> a0 = f0(g0); + A<float(float)> a1 = f0(g1); +} + +// bullet 3 +struct X { }; +const X get_X(); + +template<typename T> A<T> f1(T); + +void test_f1_bullet3() { + A<X> a0 = f1(get_X()); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp new file mode 100644 index 0000000..e470dd0 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + + +// If P is an rvalue reference to a cv-unqualified template parameter +// and the argument is an lvalue, the type "lvalue reference to A" is +// used in place of A for type deduction. +template<typename T> struct X { }; + +template<typename T> X<T> f0(T&&); + +struct Y { }; + +template<typename T> T prvalue(); +template<typename T> T&& xvalue(); +template<typename T> T& lvalue(); + +void test_f0() { + X<int> xi0 = f0(prvalue<int>()); + X<int> xi1 = f0(xvalue<int>()); + X<int&> xi2 = f0(lvalue<int>()); + X<Y> xy0 = f0(prvalue<Y>()); + X<Y> xy1 = f0(xvalue<Y>()); + X<Y&> xy2 = f0(lvalue<Y>()); +} + +template<typename T> X<T> f1(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} \ +// expected-note{{candidate function [with T = Y] not viable: no known conversion from 'Y' to 'const Y &&' for 1st argument}} + +void test_f1() { + X<int> xi0 = f1(prvalue<int>()); + X<int> xi1 = f1(xvalue<int>()); + f1(lvalue<int>()); // expected-error{{no matching function for call to 'f1'}} + X<Y> xy0 = f1(prvalue<Y>()); + X<Y> xy1 = f1(xvalue<Y>()); + f1(lvalue<Y>()); // expected-error{{no matching function for call to 'f1'}} +} + +namespace std_example { + template <class T> int f(T&&); + template <class T> int g(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} + + int i; + int n1 = f(i); + int n2 = f(0); + int n3 = g(i); // expected-error{{no matching function for call to 'g'}} +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp new file mode 100644 index 0000000..295f080 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp @@ -0,0 +1,148 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +// Top-level cv-qualifiers of P's type are ignored for type deduction. +template<typename T> A<T> f0(const T); + +void test_f0(int i, const int ci) { + A<int> a0 = f0(i); + A<int> a1 = f0(ci); +} + +// If P is a reference type, the type referred to by P is used for type +// deduction. +template<typename T> A<T> f1(T&); + +void test_f1(int i, const int ci, volatile int vi) { + A<int> a0 = f1(i); + A<const int> a1 = f1(ci); + A<volatile int> a2 = f1(vi); +} + +template<typename T, unsigned N> struct B { }; +template<typename T, unsigned N> B<T, N> g0(T (&array)[N]); +template<typename T, unsigned N> B<T, N> g0b(const T (&array)[N]); + +void test_g0() { + int array0[5]; + B<int, 5> b0 = g0(array0); + const int array1[] = { 1, 2, 3}; + B<const int, 3> b1 = g0(array1); + B<int, 3> b2 = g0b(array1); +} + +template<typename T> B<T, 0> g1(const A<T>&); + +void test_g1(A<float> af) { + B<float, 0> b0 = g1(af); + B<int, 0> b1 = g1(A<int>()); +} + +// - If the original P is a reference type, the deduced A (i.e., the type +// referred to by the reference) can be more cv-qualified than the +// transformed A. +template<typename T> A<T> f2(const T&); + +void test_f2(int i, const int ci, volatile int vi) { + A<int> a0 = f2(i); + A<int> a1 = f2(ci); + A<volatile int> a2 = f2(vi); +} + +// PR5913 +template <typename T, int N> +void Foo(const T (&a)[N]) { + T x; + x = 0; +} + +const int a[1] = { 0 }; + +void Test() { + Foo(a); +} + +// - The transformed A can be another pointer or pointer to member type that +// can be converted to the deduced A via a qualification conversion (4.4). +template<typename T> A<T> f3(T * * const * const); + +void test_f3(int ***ip, volatile int ***vip) { + A<int> a0 = f3(ip); + A<volatile int> a1 = f3(vip); +} + +// Also accept conversions for pointer types which require removing +// [[noreturn]]. +namespace noreturn_stripping { + template <class R> + void f(R (*function)()); + + void g() __attribute__ ((__noreturn__)); + void h(); + void test() { + f(g); + f(h); + } +} + +// - If P is a class, and P has the form template-id, then A can be a +// derived class of the deduced A. Likewise, if P is a pointer to a class +// of the form template-id, A can be a pointer to a derived class pointed +// to by the deduced A. +template<typename T, int I> struct C { }; + +struct D : public C<int, 1> { }; +struct E : public D { }; +struct F : A<float> { }; +struct G : A<float>, C<int, 1> { }; + +template<typename T, int I> + C<T, I> *f4a(const C<T, I>&); +template<typename T, int I> + C<T, I> *f4b(C<T, I>); +template<typename T, int I> + C<T, I> *f4c(C<T, I>*); +int *f4c(...); + +void test_f4(D d, E e, F f, G g) { + C<int, 1> *ci1a = f4a(d); + C<int, 1> *ci2a = f4a(e); + C<int, 1> *ci1b = f4b(d); + C<int, 1> *ci2b = f4b(e); + C<int, 1> *ci1c = f4c(&d); + C<int, 1> *ci2c = f4c(&e); + C<int, 1> *ci3c = f4c(&g); + int *ip1 = f4c(&f); +} + +// PR8462 +namespace N { + struct T0; + struct T1; + + template<typename X, typename Y> struct B {}; + + struct J : B<T0,T0> {}; + struct K : B<T1,T1> {}; + + struct D : J, K {}; + + template<typename X, typename Y> void F(B<Y,X>); + + void test() + { + D d; + N::F<T0>(d); // Fails + N::F<T1>(d); // OK + } +} + +namespace PR9233 { + template<typename T> void f(const T **q); // expected-note{{candidate template ignored: substitution failure [with T = int]}} + + void g(int **p) { + f(p); // expected-error{{no matching function for call to 'f'}} + } + +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp new file mode 100644 index 0000000..83b5f23 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8598 { + template<class T> struct identity { typedef T type; }; + + template<class T, class C> + void f(T C::*, typename identity<T>::type*){} + + struct X { void f() {}; }; + + void g() { (f)(&X::f, 0); } +} + +namespace PR12132 { + template<typename S> void fun(const int* const S::* member) {} + struct A { int* x; }; + void foo() { + fun(&A::x); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp new file mode 100644 index 0000000..8b18189 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + template<class T> void apply(T x, void (*f)(T)) { f(x); } // expected-note 2 {{candidate template ignored: deduced conflicting types for parameter 'T'}}\ + // expected-note {{no overload of 'temp2' matching 'void (*)(int)'}} + + template<class A> void temp(A); + void test0() { + // okay: deduce T=int from first argument, A=int during overload + apply(0, &temp); + apply(0, &temp<>); + + // okay: deduce T=int from first and second arguments + apply(0, &temp<int>); + + // deduction failure: T=int from first, T=long from second + apply(0, &temp<long>); // expected-error {{no matching function for call to 'apply'}} + } + + void over(int); + int over(long); + + void test1() { + // okay: deductions match + apply(0, &over); + + // deduction failure: deduced T=long from first argument, T=int from second + apply(0L, &over); // expected-error {{no matching function for call to 'apply'}} + } + + void over(short); + + void test2() { + // deduce T=int from first arg, second arg is undeduced context, + // pick correct overload of 'over' during overload resolution for 'apply' + apply(0, &over); + } + + template<class A, class B> B temp2(A); + void test3() { + // deduce T=int from first arg, A=int B=void during overload resolution + apply(0, &temp2); + apply(0, &temp2<>); + apply(0, &temp2<int>); + + // overload failure + apply(0, &temp2<long>); // expected-error {{no matching function for call to 'apply'}} + } +} + +namespace test1 { + template<class T> void invoke(void (*f)(T)) { f(T()); } // expected-note 6 {{couldn't infer template argument}} \ + // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} + + template<class T> void temp(T); + void test0() { + // deduction failure: overload has template => undeduced context + invoke(&temp); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp<>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp<int>); + } + + void over(int); + int over(long); + + void test1() { + // okay: only one overload matches + invoke(&over); + } + + void over(short); + + void test2() { + // deduction failure: overload has multiple matches => undeduced context + invoke(&over); // expected-error {{no matching function for call to 'invoke'}} + } + + template<class A, class B> B temp2(A); + void test3() { + // deduction failure: overload has template => undeduced context + // (even though partial application temp2<int> could in theory + // let us infer T=int) + invoke(&temp2); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<>); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<int>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp2<int, void>); + + // overload failure + invoke(&temp2<int, int>); // expected-error {{no matching function for call to 'invoke'}} + } +} + +namespace rdar8360106 { + template<typename R, typename T> void f0(R (*)(T), T); + template<typename R, typename T> void f1(R (&)(T) , T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + template<typename R, typename T> void f2(R (* const&)(T), T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + + int g(int); + int g(int, int); + + void h() { + f0(g, 1); + f0(&g, 1); + f1(g, 1); + f1(&g, 1); // expected-error{{no matching function for call to 'f1'}} + f2(g, 1); // expected-error{{no matching function for call to 'f2'}} + f2(&g, 1); + } +} + +namespace PR11713 { + template<typename T> + int f(int, int, int); + + template<typename T> + float f(float, float); + + template<typename R, typename B1, typename B2, typename A1, typename A2> + R& g(R (*)(B1, B2), A1, A2); + + void h() { + float &fr = g(f<int>, 1, 2); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp new file mode 100644 index 0000000..5a9ea08 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: [temp.deduct.conv]p2 bullets 1 and 2 can't actually happen without +// references? +// struct ConvertibleToArray { +// // template<typename T, unsigned N> +// // operator T(()[]) const; + +// private: +// typedef int array[17]; + +// operator array() const; +// }; + +// void test_array(ConvertibleToArray cta) { +// int *ip = cta; +// ip = cta; +// const float *cfp = cta; +// } + +// bullet 2 +// struct ConvertibleToFunction { +// template<typename T, typename A1, typename A2> +// operator T(A1, A2) const () { }; +// }; + +// bullet 3 +struct ConvertibleToCVQuals { + template<typename T> + operator T* const() const; +}; + +void test_cvqual_conv(ConvertibleToCVQuals ctcv) { + int *ip = ctcv; + const int *icp = ctcv; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp new file mode 100644 index 0000000..e23e98a --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct AnyPtr { + template<typename T> + operator T*() const; +}; + +// If A is a cv-qualified type, the top level cv-qualifiers of A's type +// are ignored for type deduction. +void test_cvquals(AnyPtr ap) { + int* const ip = ap; + const float * const volatile fp = ap; +} + +// If A is a reference type, the type referred to by A is used for +// type deduction. +void test_ref_arg(AnyPtr ap) { + const int* const &ip = ap; + double * const &dp = ap; +} + +struct AnyRef { + template<typename T> + operator T&() const; +}; + +void test_ref_param(AnyRef ar) { + int &ir = ar; + const float &fr = ar; + int i = ar; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp new file mode 100644 index 0000000..4dca820 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +struct AnyT { + template<typename T> + operator T(); +}; + +void test_cvqual_ref(AnyT any) { + const int &cir = any; +} + +struct AnyThreeLevelPtr { + template<typename T> + operator T***() const + { + T x = 0; + // FIXME: looks like we get this wrong, too! + // x = 0; // will fail if T is deduced to a const type + // (EDG and GCC get this wrong) + return 0; + } +}; + +struct X { }; + +void test_deduce_with_qual(AnyThreeLevelPtr a3) { + int * const * const * const ip = a3; +} + +struct AnyPtrMem { + template<typename Class, typename T> + operator T Class::*() const + { + T x = 0; + // FIXME: looks like we get this wrong, too! + // x = 0; // will fail if T is deduced to a const type. + // (EDG and GCC get this wrong) + return 0; + } +}; + +void test_deduce_ptrmem_with_qual(AnyPtrMem apm) { + const float X::* pm = apm; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp new file mode 100644 index 0000000..99a265a --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> + T f0(T, int); + +void test_f0() { + int (*f0a)(int, int) = f0; + int (*f0b)(int, int) = &f0; + float (*f0c)(float, int) = &f0; +} + +template<typename T> T f1(T, int); +template<typename T> T f1(T); + +void test_f1() { + float (*f1a)(float, int) = f1; + float (*f1b)(float, int) = &f1; + float (*f1c)(float) = f1; + float (*f1d)(float) = (f1); + float (*f1e)(float) = &f1; + float (*f1f)(float) = (&f1); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp new file mode 100644 index 0000000..01155e1 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> T* f(int); // #1 +template <class T, class U> T& f(U); // #2 + +void g() { + int *ip = f<int>(1); // calls #1 +} + +template<typename T> +struct identity { + typedef T type; +}; + +template <class T> + T* f2(int, typename identity<T>::type = 0); +template <class T, class U> + T& f2(U, typename identity<T>::type = 0); + +void g2() { + int* ip = f2<int>(1); +} + +template<class T, class U> struct A { }; + +template<class T, class U> inline int *f3( U, A<U,T>* p = 0 ); // #1 expected-note{{candidate function [with T = int, U = int]}} +template< class U> inline float *f3( U, A<U,U>* p = 0 ); // #2 expected-note{{candidate function [with U = int]}} + +void g3() { + float *fp = f3<int>( 42, (A<int,int>*)0 ); // Ok, picks #2. + f3<int>( 42 ); // expected-error{{call to 'f3' is ambiguous}} + +} + +namespace PR9006 { + struct X { + template <class Get> + int &f(char const* name, Get fget, char const* docstr = 0); + + template <class Get, class Set> + float &f(char const* name, Get fget, Set fset, char const* docstr = 0); + }; + + void test(X x) { + int &ir = x.f("blah", 0, "blah"); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp new file mode 100644 index 0000000..b965300 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Note: Partial ordering of function templates containing template +// parameter packs is independent of the number of deduced arguments +// for those template parameter packs. +template<class ...> struct Tuple { }; +template<class ... Types> int &g(Tuple<Types ...>); // #1 +template<class T1, class ... Types> float &g(Tuple<T1, Types ...>); // #2 +template<class T1, class ... Types> double &g(Tuple<T1, Types& ...>); // #3 + +void test_g() { + int &ir1 = g(Tuple<>()); + float &fr1 = g(Tuple<int, float>()); + double &dr1 = g(Tuple<int, float&>()); + double &dr2 = g(Tuple<int>()); +} + +template<class ... Types> int &h(int (*)(Types ...)); // #1 +template<class T1, class ... Types> float &h(int (*)(T1, Types ...)); // #2 +template<class T1, class ... Types> double &h(int (*)(T1, Types& ...)); // #3 + +void test_h() { + int &ir1 = h((int(*)())0); + float &fr1 = h((int(*)(int, float))0); + double &dr1 = h((int(*)(int, float&))0); + double &dr2 = h((int(*)(int))0); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp new file mode 100644 index 0000000..f204caf --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> int &f0(T&); +template<typename T> float &f0(T&&); + +// Core issue 1164 +void test_f0(int i) { + int &ir0 = f0(i); + float &fr0 = f0(5); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp new file mode 100644 index 0000000..8183061 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +template<typename T> void f(T&&); +template<> void f(int&) { } +void (*fp)(int&) = &f; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp new file mode 100644 index 0000000..bf5f962 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<int i> class A { }; +template<short s> void f(A<s>); // expected-note{{candidate template ignored: substitution failure}} + +void k1() { + A<1> a; + f(a); // expected-error{{no matching function for call}} + f<1>(a); +} +template<const short cs> class B { }; +template<short s> void g(B<s>); +void k2() { + B<1> b; + g(b); // OK: cv-qualifiers are ignored on template parameter types +} + +template<short s> void h(int (&)[s]); // expected-note{{candidate function template not viable: requires 1 argument, but 2 were provided}} +void k3() { + int array[5]; + h(array); + h<5>(array); +} + +template<short s> void h(int (&)[s], A<s>); // expected-note{{candidate template ignored: substitution failure}} +void k4() { + A<5> a; + int array[5]; + h(array, a); // expected-error{{no matching function for call}} + h<5>(array, a); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp new file mode 100644 index 0000000..5b031c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If type deduction cannot be done for any P/A pair, or if for any +// pair the deduction leads to more than one possible set of deduced +// values, or if different pairs yield different deduced values, or if +// any template argument remains neither deduced nor explicitly +// specified, template argument deduction fails. + +template<typename ...> struct tuple; + +template<typename T, typename U> +struct same_tuple { + static const bool value = false; +}; + +template<typename ...Types1> +struct same_tuple<tuple<Types1...>, tuple<Types1...> > { + static const bool value = true; +}; + +int same_tuple_check1[same_tuple<tuple<int, float>, tuple<int, double>>::value? -1 : 1]; +int same_tuple_check2[same_tuple<tuple<float, double>, tuple<float, double>>::value? 1 : -1]; + diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp new file mode 100644 index 0000000..4e98a6d --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Note: Template argument deduction involving parameter packs +// (14.5.3) can deduce zero or more arguments for each parameter pack. + +template<class> struct X { + static const unsigned value = 0; +}; + +template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { + static const unsigned value = 1; +}; + +template<class ... Types> struct Y { + static const unsigned value = 0; +}; + +template<class T, class ... Types> struct Y<T, Types& ...> { + static const unsigned value = 1; +}; + +template<class ... Types> int f(void (*)(Types ...)); +void g(int, float); + +int check0[X<int>::value == 0? 1 : -1]; // uses primary template +int check1[X<int(int, float, double)>::value == 1? 1 : -1]; // uses partial specialization +int check2[X<int(float, int)>::value == 0? 1 : -1]; // uses primary template +int check3[Y<>::value == 0? 1 : -1]; // uses primary template +int check4[Y<int&, float&, double&>::value == 1? 1 : -1]; // uses partial specialization +int check5[Y<int, float, double>::value == 0? 1 : -1]; // uses primary template +int fv = f(g); // okay diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp new file mode 100644 index 0000000..fcc6cf7 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If the original function parameter associated with A is a function +// parameter pack and the function parameter associated with P is not +// a function parameter pack, then template argument deduction fails. +template<class ... Args> int& f(Args ... args); +template<class T1, class ... Args> float& f(T1 a1, Args ... args); +template<class T1, class T2> double& f(T1 a1, T2 a2); + +void test_f() { + int &ir1 = f(); + float &fr1 = f(1, 2, 3); + double &dr1 = f(1, 2); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp new file mode 100644 index 0000000..c819d97 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// FIXME: More bullets to go! + +template<typename T, typename U> +struct has_nondeduced_pack_test { + static const bool value = false; +}; + +template<typename R, typename FirstType, typename ...Types> +struct has_nondeduced_pack_test<R(FirstType, Types..., int), + R(FirstType, Types...)> { + static const bool value = true; +}; + +// - A function parameter pack that does not occur at the end of the +// parameter-declaration-clause. +int check_nondeduced_pack_test0[ + has_nondeduced_pack_test<int(float, double, int), + int(float, double)>::value? 1 : -1]; + + diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp new file mode 100644 index 0000000..a6b1172 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Deductions specific to C++0x. + +template<typename T> +struct member_pointer_kind { + static const unsigned value = 0; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...)> { + static const unsigned value = 1; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) &> { + static const unsigned value = 2; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) &&> { + static const unsigned value = 3; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const> { + static const unsigned value = 4; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const &> { + static const unsigned value = 5; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const &&> { + static const unsigned value = 6; +}; + +struct X { }; + +static_assert(member_pointer_kind<int (X::*)(int)>::value == 1, ""); +static_assert(member_pointer_kind<int (X::*)(int) &>::value == 2, ""); +static_assert(member_pointer_kind<int (X::*)(int) &&>::value == 3, ""); +static_assert(member_pointer_kind<int (X::*)(int) const>::value == 4, ""); +static_assert(member_pointer_kind<int (X::*)(int) const&>::value == 5, ""); +static_assert(member_pointer_kind<int (X::*)(int) const&&>::value == 6, ""); diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp new file mode 100644 index 0000000..7774b5c --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename ...Types> struct tuple; +template<unsigned> struct unsigned_c; + +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 PackExpansionNotAtEnd { + template<typename T, typename U> + struct tuple_same_with_int { + static const bool value = false; + }; + + template<typename ...Types> + struct tuple_same_with_int<tuple<Types...>, tuple<Types..., int>> { + static const bool value = true; + }; + + int tuple_same_with_int_1[tuple_same_with_int<tuple<int, float, double>, + tuple<int, float, double, int> + >::value? 1 : -1]; + + template<typename ... Types> struct UselessPartialSpec; + + template<typename ... Types, // expected-note{{non-deducible template parameter 'Types'}} + typename Tail> // expected-note{{non-deducible template parameter 'Tail'}} + struct UselessPartialSpec<Types..., Tail>; // expected-warning{{class template partial specialization contains template parameters that can not be deduced; this partial specialization will never be used}} +} + +namespace DeduceNonTypeTemplateArgsInArray { + template<typename ...ArrayTypes> + struct split_arrays; + + template<typename ...ElementTypes, unsigned ...Bounds> + struct split_arrays<ElementTypes[Bounds]...> { + typedef tuple<ElementTypes...> element_types; + + // FIXME: Would like to have unsigned_tuple<Bounds...> here. + typedef tuple<unsigned_c<Bounds>...> bounds_types; + }; + + int check1[is_same<split_arrays<int[1], float[2], double[3]>::element_types, + tuple<int, float, double>>::value? 1 : -1]; + int check2[is_same<split_arrays<int[1], float[2], double[3]>::bounds_types, + tuple<unsigned_c<1>, unsigned_c<2>, unsigned_c<3>> + >::value? 1 : -1]; +} diff --git a/clang/test/CXX/temp/temp.names/p2.cpp b/clang/test/CXX/temp/temp.names/p2.cpp new file mode 100644 index 0000000..93e45dd --- /dev/null +++ b/clang/test/CXX/temp/temp.names/p2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Ensure that when enforcing access control an unqualified template name with +// explicit template arguments, we don't lose the context of the name lookup +// because of the required early lookup to determine if it names a template. +namespace PR7163 { + template <typename R, typename P> void h(R (*func)(P)) {} + class C { + template <typename T> static void g(T*) {}; + public: + void f() { h(g<int>); } + }; +} diff --git a/clang/test/CXX/temp/temp.names/p4.cpp b/clang/test/CXX/temp/temp.names/p4.cpp new file mode 100644 index 0000000..103a1bd --- /dev/null +++ b/clang/test/CXX/temp/temp.names/p4.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct meta { + template<typename U> + struct apply { + typedef U* type; + }; +}; + +template<typename T, typename U> +void f(typename T::template apply<U>::type); + +void test_f(int *ip) { + f<meta, int>(ip); +} diff --git a/clang/test/CXX/temp/temp.param/p1.cpp b/clang/test/CXX/temp/temp.param/p1.cpp new file mode 100644 index 0000000..e9a9789 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p1.cpp @@ -0,0 +1,12 @@ +// Suppress 'no run line' failure. +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<template<> class C> class D; // expected-error{{template template parameter must have its own template parameters}} + + +struct A {}; +template<class M, + class T = A, // expected-note{{previous default template argument defined here}} + class C> // expected-error{{template parameter missing a default argument}} +class X0 {}; // expected-note{{template is declared here}} +X0<int> x0; // expected-error{{too few template arguments for class template 'X0'}} diff --git a/clang/test/CXX/temp/temp.param/p10-0x.cpp b/clang/test/CXX/temp/temp.param/p10-0x.cpp new file mode 100644 index 0000000..37bb284 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p10-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template<typename> struct Y1; +template<typename, int> struct Y2; + +template<class T1, class T2 = int> using B2 = T1; +template<class T1 = int, class T2> using B2 = T1; + +template<template<class> class F, template<class> class G = Y1> using B2t = F<G<int>>; +template<template<class> class F = Y2, template<class> class G> using B2t = F<G<int>>; + +template<int N, int M = 5> using B2n = Y2<int, N + M>; +template<int N = 5, int M> using B2n = Y2<int, N + M>; diff --git a/clang/test/CXX/temp/temp.param/p10.cpp b/clang/test/CXX/temp/temp.param/p10.cpp new file mode 100644 index 0000000..b9dac75 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p10.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct Y1; +template<typename, int> struct Y2; + +template<class T1, class T2 = int> class B2; +template<class T1 = int, class T2> class B2; + +template<template<class, int> class, template<class> class = Y1> class B2t; +template<template<class, int> class = Y2, template<class> class> class B2t; + +template<int N, int M = 5> class B2n; +template<int N = 5, int M> class B2n; diff --git a/clang/test/CXX/temp/temp.param/p11-0x.cpp b/clang/test/CXX/temp/temp.param/p11-0x.cpp new file mode 100644 index 0000000..d2276a3 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p11-0x.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If a template-parameter of a class template or alias template has a default +// template-argument, each subsequent template-parameter shall either have a +// default template-argument supplied or be a template parameter pack. +template<typename> struct vector; + +template<typename T = int, typename> struct X3t; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<typename T = int, typename> using A3t = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<int V = 0, int> struct X3nt; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<int V = 0, int> using A3nt = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<template<class> class M = vector, template<class> class> struct X3tt; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<template<class> class M = vector, template<class> class> using A3tt = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} + +template<typename T = int, typename ...Types> struct X2t; +template<typename T = int, typename ...Types> using A2t = X2t<T, Types...>; +template<int V = 0, int ...Values> struct X2nt; +template<int V = 0, int ...Values> using A2nt = X2nt<V, Values...>; +template<template<class> class M = vector, template<class> class... Metas> + struct X2tt; +template<template<class> class M = vector, template<class> class... Metas> + using A2tt = X2tt<M, Metas...>; + +// If a template-parameter of a primary class template or alias template is a +// template parameter pack, it shall be the last template-parameter. +template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} + int After, int After2> +struct X0t; +X0t<int> pr9789(); +template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} + int After> +using A0t = int; + +template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0nt; +template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}} + int After> +using A0nt = int; + +template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0tt; +template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}} + int After> +using A0tt = int; + +// [ Note: These are not requirements for function templates or class +// template partial specializations because template arguments can be +// deduced (14.8.2). -- end note] +template<typename... Types> struct X1t; +template<typename ...Types, typename T> struct X1t<T, Types...> { }; + +template<int... Values> struct X1nt; +template<int ...Values, int V> struct X1nt<V, Values...> { }; + +template<template<int> class... Meta> struct X1tt; +template<template<int> class... Meta, template<int> class M> + struct X1tt<M, Meta...> { }; + +template<typename ...Types, typename T> +void f1t(X1t<T, Types...>); + +template<int ...Values, int V> +void f1nt(X1nt<V, Values...>); + +template<template<int> class... Meta, template<int> class M> +void f1tt(X1tt<M, Meta...>); + +namespace DefaultTemplateArgsInFunction { + template<typename T = int, typename U> T &f0(U) { T *x = 0; return *x; } + + void test_f0() { + int &ir0 = f0(3.14159); + int &ir1 = f0<int>(3.14159); + float &fr0 = f0<float>(3.14159); + } + + template<> int &f0(int*); + template int &f0(double&); +} diff --git a/clang/test/CXX/temp/temp.param/p11.cpp b/clang/test/CXX/temp/temp.param/p11.cpp new file mode 100644 index 0000000..5af0c4e --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p11.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct Y1; +template<typename, int> struct Y2; + +template<class T1 = int, // expected-note{{previous default template argument defined here}} + class T2> // expected-error{{template parameter missing a default argument}} + class B1; + +template<template<class> class = Y1, // expected-note{{previous default template argument defined here}} + template<class> class> // expected-error{{template parameter missing a default argument}} + class B1t; + +template<int N = 5, // expected-note{{previous default template argument defined here}} + int M> // expected-error{{template parameter missing a default argument}} + class B1n; diff --git a/clang/test/CXX/temp/temp.param/p12.cpp b/clang/test/CXX/temp/temp.param/p12.cpp new file mode 100644 index 0000000..7be3879 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p12.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}} +template<typename, int> struct Y2; + +// C++ [temp.param]p12: +template<class T1, + class T2 = int> // expected-note{{previous default template argument defined here}} + class B3; +template<class T1, typename T2> class B3; +template<class T1, + typename T2 = float> // expected-error{{template parameter redefines default argument}} + class B3; + +template<template<class, int> class, + template<class> class = Y1> // expected-note{{previous default template argument defined here}} + class B3t; + +template<template<class, int> class, template<class> class> class B3t; + +template<template<class, int> class, + template<class> class = Y1> // expected-error{{template parameter redefines default argument}} + class B3t; + +template<int N, + int M = 5> // expected-note{{previous default template argument defined here}} + class B3n; + +template<int N, int M> class B3n; + +template<int N, + int M = 7> // expected-error{{template parameter redefines default argument}} + class B3n; + +// Check validity of default arguments +template<template<class, int> class // expected-note{{previous template template parameter is here}} + = Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + class C1 {}; + +C1<> c1; // expected-note{{while checking a default template argument}} diff --git a/clang/test/CXX/temp/temp.param/p13.cpp b/clang/test/CXX/temp/temp.param/p13.cpp new file mode 100644 index 0000000..7e7dbe5 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p13.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// The scope of atemplate-parameterextends from its point of +// declaration until the end of its template. In particular, a +// template-parameter can be used in the declaration of subsequent +// template-parameters and their default arguments. + +template<class T, T* p, class U = T> class X { /* ... */ }; +// FIXME: template<class T> void f(T* p = new T); + +// Check for bogus template parameter shadow warning. +template<template<class T> class, + template<class T> class> + class B1noshadow; diff --git a/clang/test/CXX/temp/temp.param/p14.cpp b/clang/test/CXX/temp/temp.param/p14.cpp new file mode 100644 index 0000000..a6c53c1 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p14.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * + +// A template-parameter shall not be used in its own default argument. +template<typename T = typename T::type> struct X; // expected-error{{default}} diff --git a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp new file mode 100644 index 0000000..5fc57a4 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +template<typename T> struct X; +template<int I> struct Y; + +X<X<int>> *x1; + +Y<(1 >> 2)> *y1; +Y<1 >> 2> *y2; // FIXME: expected-error{{expected unqualified-id}} + +X<X<X<X<X<int>>>>> *x2; + +template<> struct X<int> { }; +typedef X<int> X_int; +struct Z : X_int { }; + +void f(const X<int> x) { + (void)reinterpret_cast<X<int>>(x); // expected-error{{reinterpret_cast from}} + (void)reinterpret_cast<X<X<X<int>>>>(x); // expected-error{{reinterpret_cast from}} + + X<X<int>> *x1; +} + +template<typename T = void> struct X1 { }; +X1<X1<>> x1a; diff --git a/clang/test/CXX/temp/temp.param/p15.cpp b/clang/test/CXX/temp/temp.param/p15.cpp new file mode 100644 index 0000000..ee572e9 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p15.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s +template<typename T> struct X; +template<int I> struct Y; + +X<X<int> > *x1; +X<X<int>> *x2; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + +X<X<X<X<int>> // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + >> *x3; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + +Y<(1 >> 2)> *y1; +Y<1 >> 2> *y2; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++11}} diff --git a/clang/test/CXX/temp/temp.param/p2.cpp b/clang/test/CXX/temp/temp.param/p2.cpp new file mode 100644 index 0000000..fed6e9c --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// There is no semantic difference between class and typename in a +// template-parameter. typename followed by an unqualified-id names a +// template type parameter. +template<class T> struct X; +template<typename T> struct X; + +// typename followed by aqualified-id denotes the type in a non-type +// parameter-declaration. +template<typename T, typename T::type Value> struct Y0; +template<typename T, typename X<T>::type Value> struct Y1; + +// A storage class shall not be specified in a template-parameter declaration. +template<static int Value> struct Z; // FIXME: expect an error + +// Make sure that we properly disambiguate non-type template parameters that +// start with 'class'. +class X1 { }; +template<class X1 *xptr> struct Y2 { }; + +// FIXME: add the example from p2 diff --git a/clang/test/CXX/temp/temp.param/p3.cpp b/clang/test/CXX/temp/temp.param/p3.cpp new file mode 100644 index 0000000..dc40c4b --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p3.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A type-parameter defines its identifier to be a type-name (if +// declared with class or typename) or template-name (if declared with +// template) in the scope of the template declaration. +template<typename T> struct X0 { + T* value; +}; + +template<template<class T> class Y> struct X1 { + Y<int> value; +}; + +// [Note: because of the name lookup rules, a template-parameter that +// could be interpreted as either a non-type template-parameter or a +// type-parameter (because its identifier is the name of an already +// existing class) is taken as a type-parameter. For example, +class T { /* ... */ }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} +int i; + +template<class T, T i> struct X2 { + void f(T t) + { + T t1 = i; //template-parameters T and i + ::T t2 = ::i; // global namespace members T and i \ + // expected-error{{no viable conversion}} + } +}; + +namespace PR6831 { + namespace NA { struct S; } + namespace NB { struct S; } + + using namespace NA; + using namespace NB; + + template <typename S> void foo(); + template <int S> void bar(); + template <template<typename> class S> void baz(); +} diff --git a/clang/test/CXX/temp/temp.param/p4.cpp b/clang/test/CXX/temp/temp.param/p4.cpp new file mode 100644 index 0000000..809fb20 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p4.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class X; + +// C++ [temp.param]p4 +typedef int INT; +enum E { enum1, enum2 }; +template<int N> struct A1; +template<INT N, INT M> struct A2; +template<enum E x, E y> struct A3; +template<int &X> struct A4; +template<int *Ptr> struct A5; +template<int (&f)(int, int)> struct A6; +template<int (*fp)(float, double)> struct A7; +template<int X::*pm> struct A8; +template<float (X::*pmf)(float, int)> struct A9; +template<typename T, T x> struct A10; + +template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}} + +template<void *Ptr> struct A12; +template<int (*IncompleteArrayPtr)[]> struct A13; diff --git a/clang/test/CXX/temp/temp.param/p5.cpp b/clang/test/CXX/temp/temp.param/p5.cpp new file mode 100644 index 0000000..3cbb3b7 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p5.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify %s -std=c++11 + +template<const int I> struct S { + decltype(I) n; + int &&r = I; +}; +S<5> s; + +template<typename T, T v> struct U { + decltype(v) n; + int &&r = v; +}; +U<const int, 6> u; diff --git a/clang/test/CXX/temp/temp.param/p7.cpp b/clang/test/CXX/temp/temp.param/p7.cpp new file mode 100644 index 0000000..13f0367 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p7.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A non-type template-parameter shall not be declared to have +// floating point, class, or void type. +struct A; + +template<double d> class X; // expected-error{{cannot have type}} +template<double* pd> class Y; //OK +template<double& rd> class Z; //OK + +template<A a> class X0; // expected-error{{cannot have type}} + +typedef void VOID; +template<VOID a> class X01; // expected-error{{cannot have type}} + diff --git a/clang/test/CXX/temp/temp.param/p8.cpp b/clang/test/CXX/temp/temp.param/p8.cpp new file mode 100644 index 0000000..fed048c --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p8.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<int X[10]> struct A; +template<int *X> struct A; +template<int f(float, double)> struct B; +typedef float FLOAT; +template<int (*f)(FLOAT, double)> struct B; diff --git a/clang/test/CXX/temp/temp.param/p9-0x.cpp b/clang/test/CXX/temp/temp.param/p9-0x.cpp new file mode 100644 index 0000000..29a7549 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p9-0x.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// A default template-argument may be specified for any kind of +// template-parameter that is not a template parameter pack. +template<typename ...Types = int> // expected-error{{template parameter pack cannot have a default argument}} +struct X0; + +template<int ...Values = 0> // expected-error{{template parameter pack cannot have a default argument}} +struct X1; + +template<typename T> struct vector; + +template<template<class> class ...Templates = vector> // expected-error{{template parameter pack cannot have a default argument}} +struct X2; + +struct X3 { + template<typename T = int> // expected-error{{default template argument not permitted on a friend template}} + friend void f0(X3); + + template<typename T = int> + friend void f1(X3) { + } +}; + +namespace PR8748 { + // Testcase 1 + struct A0 { template<typename U> struct B; }; + template<typename U = int> struct A0::B { }; + + // Testcase 2 + template<typename T> struct A1 { template<typename U> struct B; }; + template<typename T> template<typename U = int> struct A1<T>::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + // Testcase 3 + template<typename T> + struct X2 { + void f0(); + template<typename U> void f1(); + }; + + template<typename T = int> void X2<T>::f0() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + template<typename T> template<typename U = int> void X2<T>::f1() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + namespace Inner { + template<typename T> struct X3; + template<typename T> void f2(); + } + + // Okay; not class members. + template<typename T = int> struct Inner::X3 { }; + template<typename T = int> void Inner::f2() {} +} + +namespace PR10069 { + template<typename T, T a, T b=0, T c=1> + T f(T x); + + void g() { + f<unsigned int, 0>(0); + } +} diff --git a/clang/test/CXX/temp/temp.param/p9.cpp b/clang/test/CXX/temp/temp.param/p9.cpp new file mode 100644 index 0000000..b2318c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p9.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s + +// A default template-argument shall not be specified in a function +// template declaration or a function template definition +template<typename T = int> // expected-warning{{default template arguments for a function template are a C++11 extension}} + void foo0(T); +template<typename T = int> // expected-warning{{default template arguments for a function template are a C++11 extension}} + void foo1(T) { } + +// [...] nor in the template-parameter-list of the definition of a +// member of a class template. +template<int N> +struct X0 { + void f(); +}; + +template<int N = 0> // expected-error{{cannot add a default template argument}} +void X0<N>::f() { } + +class X1 { + template<template<int> class TT = X0> // expected-error{{not permitted on a friend template}} + friend void f2(); +}; diff --git a/clang/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp b/clang/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp new file mode 100644 index 0000000..75580d2 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * + +// Note: we fail this test because we perform template instantiation +// at the end of the translation unit, so argument-dependent lookup +// finds functions that occur after the point of instantiation. Note +// that GCC fails this test; EDG passes the test in strict mode, but +// not in relaxed mode. +namespace N { + struct A { }; + struct B : public A { }; + + int& f0(A&); +} + +template<typename T, typename Result> +struct X0 { + void test_f0(T t) { + Result r = f0(t); + }; +}; + +void test_f0() { + X0<N::A, int&> xA; + xA.test_f0(N::A()); + X0<N::B, int&> xB; + xB.test_f0(N::B()); +} + +namespace N { + char& f0(B&); +} diff --git a/clang/test/CXX/temp/temp.res/temp.dep/p3.cpp b/clang/test/CXX/temp/temp.res/temp.dep/p3.cpp new file mode 100644 index 0000000..c41a4c6 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/p3.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A0 { + struct K { }; +}; + +template <typename T> struct B0: A0 { + static void f() { + K k; + } +}; + +namespace E1 { + typedef double A; + + template<class T> class B { + typedef int A; + }; + + template<class T> + struct X : B<T> { + A* blarg(double *dp) { + return dp; + } + }; +} + +namespace E2 { + struct A { + struct B; + int *a; + int Y; + }; + + int a; + template<class T> struct Y : T { + struct B { /* ... */ }; + B b; + void f(int i) { a = i; } + Y* p; + }; + + Y<A> ya; +} diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp new file mode 100644 index 0000000..0aba402 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<int n> struct S; + +template<int n> struct T { + T() { + // An identifier is value-dependent if it is: + // - a name declared with a dependent type + S<n> s; + S<s> check1; // ok, s is value-dependent + // - the name of a non-type template parameter + typename S<n>::T check2; // ok, n is value-dependent + // - a constant with literal type and is initialized with an expression + // that is value-dependent. + const int k = n; + typename S<k>::T check3a; // ok, u is value-dependent + + constexpr const int *p = &k; + typename S<*p>::T check3b; // ok, p is value-dependent + + // (missing from the standard) + // - a reference and is initialized with an expression that is + // value-dependent. + const int &i = k; + typename S<i>::T check4; // ok, i is value-dependent + } +}; diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp new file mode 100644 index 0000000..68a41c7 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++98 -verify %s + +template<int n> struct S; + +template<int n> struct T { + T() { + // An identifier is value-dependent if it is: + // - a name declared with a dependent type + S<n> s; + S<s> check1; // ok, s is value-dependent + // - the name of a non-type template parameter + typename S<n>::T check2; // ok, n is value-dependent + // - a constant with literal type and is initialized with an expression + // that is value-dependent. + const int k = n; + typename S<k>::T check3; // ok, u is value-dependent + + const int &i = k; + typename S<i>::T check4; // expected-error {{not an integral constant expression}} expected-error {{qualified name}} + } +}; diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp new file mode 100644 index 0000000..81b070f --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Examples from CWG1056. +namespace Example1 { + template<class T> struct A; + template<class T> using B = A<T>; + + template<class T> struct A { + struct C {}; + B<T>::C bc; // ok, B<T> is the current instantiation. + }; + + template<class T> struct A<A<T>> { + struct C {}; + B<B<T>>::C bc; // ok, B<B<T>> is the current instantiation. + }; + + template<class T> struct A<A<A<T>>> { + struct C {}; + B<B<T>>::C bc; // expected-error {{missing 'typename'}} + }; +} + +namespace Example2 { + template<class T> struct A { + void g(); + }; + template<class T> using B = A<T>; + template<class T> void B<T>::g() {} // ok. +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp new file mode 100644 index 0000000..1ad4464 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.local]p1: +// Like normal (non-template) classes, class templates have an +// injected-class-name (Clause 9). The injected-class-name can be used with +// or without a template-argument-list. When it is used without +// a template-argument-list, it is equivalent to the injected-class-name +// followed by the template-parameters of the class template enclosed in <>. + +template <typename T> struct X0 { + X0(); + ~X0(); + X0 f(const X0&); +}; + +// Test non-type template parameters. +template <int N1, const int& N2, const int* N3> struct X1 { + X1(); + ~X1(); + X1 f(const X1& x1a) { X1 x1b(x1a); return x1b; } +}; + +// When it is used with a template-argument-list, it refers to the specified +// class template specialization, which could be the current specialization +// or another specialization. +// FIXME: Test this clause. + +int i = 42; +void test() { + X0<int> x0; (void)x0; + X1<42, i, &i> x1; (void)x1; +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp new file mode 100644 index 0000000..54da885 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify %s + +template <class T> struct Base { // expected-note 4 {{member found by ambiguous name lookup}} + static void f(); +}; + +struct X0 { }; + +template <class T> struct Derived: Base<int>, Base<char> { + typename Derived::Base b; // expected-error{{member 'Base' found in multiple base classes of different types}} + typename Derived::Base<double> d; // OK + + void g(X0 *t) { + t->Derived::Base<T>::f(); + t->Base<T>::f(); + t->Base::f(); // expected-error{{member 'Base' found in multiple base classes of different types}} \ + // expected-error{{no member named 'f' in 'X0'}} \ + // expected-error{{expected a class or namespace}} + } +}; + +namespace PR6717 { + template <typename T> + class WebVector { + } // expected-error {{expected ';' after class}} + + WebVector(const WebVector<T>& other) { } // expected-error{{undeclared identifier 'T'}} \ + expected-error{{requires a type specifier}} + + template <typename C> + WebVector<T>& operator=(const C& other) { } // expected-error{{undeclared identifier 'T'}} +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p7.cpp b/clang/test/CXX/temp/temp.res/temp.local/p7.cpp new file mode 100644 index 0000000..bd05e75 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p7.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> struct A { + int B; + int f(); +}; + +template<class B> int A<B>::f() { + return B; +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp new file mode 100644 index 0000000..5d9d509 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + enum { C }; + template<class T> class B { + void f(T); + }; +} + +template<class C> void N::B<C>::f(C) { + C b; +} + +namespace N { + enum { D }; + namespace M { + enum { C , D }; + template<typename C> class X { + template<typename U> void f(C, U); + + template<typename D> void g(C, D) { + C c; + D d; + } + }; + + struct Y { + template<typename U> void f(U); + }; + } + + struct Y { + template<typename D> void f(D); + }; +} + +template<typename C> +template<typename D> +void N::M::X<C>::f(C, D) { + C c; + D d; +} + +template<typename C> +void N::M::Y::f(C) { + C c; +} + +template<typename D> +void N::Y::f(D) { + D d; +} + diff --git a/clang/test/CXX/temp/temp.res/temp.local/p9.cpp b/clang/test/CXX/temp/temp.res/temp.local/p9.cpp new file mode 100644 index 0000000..9ca8d88 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p9.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { + struct B { void f(); }; + int a; + int Y; +}; + +template<class B, class a> struct X : A { + B b; // A's B + a c; // expected-error{{unknown type name 'a'}} + + void g() { + b.g(); // expected-error{{no member named 'g' in 'A::B'}} + } +}; diff --git a/clang/test/CXX/temp/temp.spec/p5.cpp b/clang/test/CXX/temp/temp.spec/p5.cpp new file mode 100644 index 0000000..0e69a26 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/p5.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> inline void f(T) { } +template void f(int); // expected-note{{previous explicit instantiation}} +template void f(int); // expected-error{{duplicate explicit instantiation}} + +template<typename T> +struct X0 { + union Inner { }; + + void f(T) { } + + static T value; +}; + +template<typename T> +T X0<T>::value = 3.14; // expected-warning{{implicit conversion turns literal floating-point number into integer}} + +template struct X0<int>; // expected-note{{previous explicit instantiation}} \ + expected-note{{requested here}} +template struct X0<int>; // expected-error{{duplicate explicit instantiation}} + +template void X0<float>::f(float); // expected-note{{previous explicit instantiation}} +template void X0<float>::f(float); // expected-error{{duplicate explicit instantiation}} + +template union X0<float>::Inner; // expected-note{{previous explicit instantiation}} +template union X0<float>::Inner; // expected-error{{duplicate explicit instantiation}} + +template float X0<float>::value; // expected-note{{previous explicit instantiation}} +template float X0<float>::value; // expected-error{{duplicate explicit instantiation}} + +// Make sure that we don't get tricked by redeclarations of nested classes. +namespace NestedClassRedecls { + template<typename T> + struct X { + struct Nested; + friend struct Nested; + + struct Nested { + Nested() {} + } nested; + }; + + X<int> xi; + + template struct X<int>; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp new file mode 100644 index 0000000..aecbfb5 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp @@ -0,0 +1,334 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5907 { + template<typename T> struct identity { typedef T type; }; + struct A { A(); }; + identity<A>::type::A() { } + + struct B { void f(); }; + template<typename T> struct C { typedef B type; }; + + void C<int>::type::f() { } +} + +namespace PR9421 { + namespace N { template<typename T> struct S { void f(); }; } + typedef N::S<int> T; + namespace N { template<> void T::f() {} } +} + +namespace PR8277 { + template< typename S > + struct C + { + template< int > + void F( void ) + { + } + }; + + template< typename S > + struct D + { + typedef C< int > A; + }; + + typedef D< int >::A A; + + template<> + template<> + void A::F< 0 >( void ) + { + } +} + +namespace PR8277b { + template<typename S> struct C { + void f(); + }; + template<typename S> struct D { + typedef C<int> A; + }; + template<> void D<int>::A::f() { + } +} + +namespace PR8708 { + template<typename T> struct A { + template<typename U> struct B { + // #2 + void f(); + }; + }; + + // #A specialize the member template for + // implicit instantiation of A<int>, + // leaving the member template "unspecialized" + // (14.7.3/16). Specialization uses the syntax + // for explicit specialization (14.7.3/14) + template<> template<typename U> + struct A<int>::B { + // #1 + void g(); + }; + + // #1 define its function g. There is an enclosing + // class template, so we write template<> for each + // specialized template (14.7.3/15). + template<> template<typename U> + void A<int>::B<U>::g() { } + + // #2 define the unspecialized member template's + // f + template<typename T> template<typename U> + void A<T>::B<U>::f() { } + + + // specialize the member template again, now + // specializing the member too. This specializes + // #A + template<> template<> + struct A<int>::B<int> { + // #3 + void h(); + }; + + // defines #3. There is no enclosing class template, so + // we write no "template<>". + void A<int>::B<int>::h() { } + + void test() { + // calls #1 + A<int>::B<float> a; a.g(); + + // calls #2 + A<float>::B<int> b; b.f(); + + // calls #3 + A<int>::B<int> c; c.h(); + } +} + +namespace PR9482 { + namespace N1 { + template <typename T> struct S { + void foo() {} + }; + } + + namespace N2 { + typedef N1::S<int> X; + } + + namespace N1 { + template<> void N2::X::foo() {} + } +} + +namespace PR9668 { + namespace First + { + template<class T> + class Bar + { + protected: + + static const bool static_bool; + }; + } + + namespace Second + { + class Foo; + } + + typedef First::Bar<Second::Foo> Special; + + namespace + First + { + template<> + const bool Special::static_bool(false); + } +} + +namespace PR9877 { + template<int> + struct X + { + struct Y; + }; + + template<> struct X<0>::Y { static const int Z = 1; }; + template<> struct X<1>::Y { static const int Z = 1; }; + + const int X<0>::Y::Z; + template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}} +} + +namespace PR9913 { + template<class,class=int>struct S; + template<class X>struct S<X> { + template<class T> class F; + }; + + template<class A> + template<class B> + class S<A>::F{}; +} + +namespace template_class_spec_perClassDecl_nested +{ + template <typename T1> struct A { + template <typename T2> struct B { + template <typename T3> struct C { + static void foo(); + }; + }; + }; + + template <> struct A<int> { + template <typename T2> struct B { + template <typename T3> struct C { + static void foo(); + }; + }; + }; + + template <> template <typename T3> struct A<int>::B<int>::C { + static void foo(); + }; + + template <> template <> struct A<int>::B<int>::C<int> { + static void foo(); + }; + + template <> template<> template <typename T2> struct A<bool>::B<bool>::C { + static void foo(); + }; +} + + +namespace spec_vs_expl_inst { + + // Test all permutations of Specialization, + // explicit instantiation Declaration, and explicit instantiation defInition. + + namespace SDI { // PR11558 + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + } + + namespace SID { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::ISD::BasicStringPiece<int>'}} + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + } + + namespace IDS { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::IDS::BasicStringPiece<int>'}} // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece<int> { }; + } + + namespace DIS { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DIS::BasicStringPiece<int>'}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; + } + + namespace DSI { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DSI::BasicStringPiece<int>'}} + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; + } + + // The same again, with a defined template class. + + namespace SDI_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + } + + namespace SID_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::ISD_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + extern template class BasicStringPiece<int>; + } + + namespace IDS_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece<int>'}} + } + + namespace DIS_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + extern template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DIS_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + } + + namespace DSI_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + extern template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DSI_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + template class BasicStringPiece<int>; + } + + // And some more random tests. + + namespace SII_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{previous explicit instantiation is here}} + template class BasicStringPiece<int>; // expected-error {{duplicate explicit instantiation of 'BasicStringPiece<int>'}} + } + + namespace SIS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece<int>'}} + } + + namespace SDS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece<int>'}} + } + + namespace SDIS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece<int>'}} + } + +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp new file mode 100644 index 0000000..3843c0d --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The intent is to verify that +// implicit instantiations do not occur (because the explicit specialization +// is used instead). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +template<typename T> void f0(T) { + T t; +} + +template<> void f0(NonDefaultConstructible) { } + +void test_f0(NonDefaultConstructible NDC) { + f0(NDC); +} + +// -- class template +template<typename T> +struct X0 { + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; + + template<typename U> + struct InnerTemplate : public T { }; + + template<typename U> + void ft1(T t, U u); +}; + +template<typename T> +template<typename U> +void X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T X0<T>::member; + +template<> struct X0<void> { }; +X0<void> test_X0; + + +// -- member function of a class template +template<> void X0<void*>::f1(void *) { } + +void test_spec(X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +// -- static data member of a class template +template<> +NonDefaultConstructible X0<NonDefaultConstructible>::member = 17; + +NonDefaultConstructible &get_static_member() { + return X0<NonDefaultConstructible>::member; +} + +// -- member class of a class template +template<> +struct X0<void*>::Inner { }; + +X0<void*>::Inner inner0; + +// -- member class template of a class template +template<> +template<> +struct X0<void*>::InnerTemplate<int> { }; + +X0<void*>::InnerTemplate<int> inner_template0; + +// -- member function template of a class template +template<> +template<> +void X0<void*>::ft1(void*, const void*) { } + +void test_func_template(X0<void *> xvp, void *vp, const void *cvp) { + xvp.ft1(vp, cvp); +} + +// example from the standard: +template<class T> class stream; +template<> class stream<char> { /* ... */ }; +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v) { /* ... */ } +template<> void sort<char*>(Array<char*>&) ; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp new file mode 100644 index 0000000..b81c1e7 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> class X; +template<> class X<int>; // expected-note{{forward}} +X<int>* p; + +X<int> x; // expected-error{{incomplete type}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp new file mode 100644 index 0000000..5fa2f62 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v); + +// explicit specialization for sort(Array<int>&) +// with deduced template-argument of type int +template<> void sort(Array<int>&); diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp new file mode 100644 index 0000000..fb6d1be --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> void f(T); + +template<> void f(int) { } +void f(int) { } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp new file mode 100644 index 0000000..121cb8e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +template<class T> void f(T) { /* ... */ } +template<class T> inline void g(T) { /* ... */ } + +// CHECK: define void @_Z1gIiEvT_ +template<> void g<>(int) { /* ... */ } + +template<class T> +struct X { + void f() { } + void g(); + void h(); +}; + +template<class T> +void X<T>::g() { +} + +template<class T> +inline void X<T>::h() { +} + +// CHECK: define void @_ZN1XIiE1fEv +template<> void X<int>::f() { } + +// CHECK: define void @_ZN1XIiE1hEv +template<> void X<int>::h() { } + +// CHECK: define linkonce_odr void @_Z1fIiEvT_ +template<> inline void f<>(int) { /* ... */ } + +// CHECK: define linkonce_odr void @_ZN1XIiE1gEv +template<> inline void X<int>::g() { } + +void test(X<int> xi) { + f(17); + g(17); + xi.f(); + xi.g(); + xi.h(); +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp new file mode 100644 index 0000000..72f33df --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct NonDefaultConstructible { + NonDefaultConstructible(const NonDefaultConstructible&); // expected-note{{candidate constructor}} +}; + +template<typename T, typename U> +struct X { + static T member; +}; + +template<typename T, typename U> +T X<T, U>::member; // expected-error{{no matching constructor}} + +// Okay; this is a declaration, not a definition. +template<> +NonDefaultConstructible X<NonDefaultConstructible, long>::member; + +NonDefaultConstructible &test(bool b) { + return b? X<NonDefaultConstructible, int>::member // expected-note{{instantiation}} + : X<NonDefaultConstructible, long>::member; +} + +namespace rdar9422013 { + template<int> + struct X { + struct Inner { + static unsigned array[17]; + }; + }; + + template<> unsigned X<1>::Inner::array[]; // okay +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp new file mode 100644 index 0000000..c7597e9 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> struct A { + void f(T); + template<class X1> void g1(T, X1); + template<class X2> void g2(T, X2); + void h(T) { } +}; + +// specialization +template<> void A<int>::f(int); + +// out of class member template definition +template<class T> template<class X1> void A<T>::g1(T, X1) { } + +// member template specialization +template<> template<class X1> void A<int>::g1(int, X1); + +// member template specialization +template<> template<> + void A<int>::g1(int, char); // X1 deduced as char + +template<> template<> + void A<int>::g2<char>(int, char); // X2 specified as char + // member specialization even if defined in class definition + +template<> void A<int>::h(int) { } + +namespace PR10024 { + template <typename T> + struct Test{ + template <typename U> + void get(U i) {} + }; + + template <typename T> + template <> + void Test<T>::get<double>(double i) {} // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}} +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp new file mode 100644 index 0000000..56231e2 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T1> +class A { + template<class T2> class B { + void mf(); + }; +}; + +template<> template<> class A<int>::B<double>; +template<> template<> void A<char>::B<char>::mf(); + +template<> void A<char>::B<int>::mf(); // expected-error{{requires 'template<>'}} + +namespace test1 { + template <class> class A { + static int foo; + static int bar; + }; + typedef A<int> AA; + + template <> int AA::foo = 0; + int AA::bar = 1; // expected-error {{template specialization requires 'template<>'}} + int A<float>::bar = 2; // expected-error {{template specialization requires 'template<>'}} + + template <> class A<double> { + public: + static int foo; + static int bar; + }; + + typedef A<double> AB; + template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}} + int AB::bar = 1; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp new file mode 100644 index 0000000..4d175a8 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T1> class A { + template<class T2> class B { + template<class T3> void mf1(T3); + void mf2(); + }; +}; + +template<> template<class X> +class A<long>::B { }; + +template<> template<> template<class T> + void A<int>::B<double>::mf1(T t) { } + +template<> template<> template<class T> +void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}} + +// FIXME: This diagnostic could probably be better. +template<class Y> template<> + void A<Y>::B<double>::mf2() { } // expected-error{{does not refer}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp new file mode 100644 index 0000000..1c2ea7e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X { + template<typename U> struct Inner { }; + + template<typename U> void f(T, U) { } +}; + +template<> template<typename U> +struct X<int>::Inner { + U member; +}; + +template<> template<typename U> +void X<int>::f(int x, U y) { + x = y; // expected-error{{incompatible type}} +} + +void test(X<int> xi, X<long> xl, float *fp) { + X<int>::Inner<float*> xii; + xii.member = fp; + xi.f(17, 25); + xi.f(17, 3.14159); + xi.f(17, fp); // expected-note{{instantiation}} + X<long>::Inner<float*> xli; + + xli.member = fp; // expected-error{{no member}} + xl.f(17, fp); // okay +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp new file mode 100644 index 0000000..b0a19fb --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp @@ -0,0 +1,302 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The specializations are alternately +// declarations and definitions, and the intent of this test is to verify +// that we allow specializations only in the appropriate namespaces (and +// nowhere else). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +namespace N0 { + template<typename T> void f0(T) { + T t; + } + + template<> void f0(NonDefaultConstructible) { } + + void test_f0(NonDefaultConstructible NDC) { + f0(NDC); + } + + template<> void f0(int); + template<> void f0(long); +} + +template<> void N0::f0(int) { } // okay + +namespace N1 { + template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} +} + +template<> void N0::f0(double) { } + +struct X1 { + template<typename T> void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template<typename T> +struct X0 { // expected-note {{here}} + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; // expected-note 2{{here}} + + template<typename U> + struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template<typename U> + void ft1(T t, U u); +}; + +} + +template<typename T> +template<typename U> +void N0::X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T N0::X0<T>::member; + +template<> struct N0::X0<void> { }; +N0::X0<void> test_X0; + +namespace N1 { + template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' must originally be declared in namespace 'N0'}} +} + +namespace N0 { + template<> struct X0<volatile void>; +} + +template<> struct N0::X0<volatile void> { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0<void*>::f1(void *) { } + +void test_spec(N0::X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +namespace N0 { + template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}} + + template<> void X0<const volatile void*>::f1(const volatile void*); +} + +void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) { + x0.f1(cvp); // okay: we've explicitly specialized +} + +// -- static data member of a class template +namespace N0 { + // This actually tests p15; the following is a declaration, not a definition. + template<> + NonDefaultConstructible X0<NonDefaultConstructible>::member; + + template<> long X0<long>::member = 17; + + template<> float X0<float>::member; + + template<> double X0<double>::member; +} + +NonDefaultConstructible &get_static_member() { + return N0::X0<NonDefaultConstructible>::member; +} + +template<> int N0::X0<int>::member; + +template<> float N0::X0<float>::member = 3.14f; + +namespace N1 { + template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}} +} + +// -- member class of a class template +namespace N0 { + + template<> + struct X0<void*>::Inner { }; + + template<> + struct X0<int>::Inner { }; + + template<> + struct X0<unsigned>::Inner; + + template<> + struct X0<float>::Inner; + + template<> + struct X0<double>::Inner; // expected-note{{forward declaration}} +} + +template<> +struct N0::X0<long>::Inner { }; + +template<> +struct N0::X0<float>::Inner { }; + +namespace N1 { + template<> + struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}} + + template<> + struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}} +}; + +N0::X0<void*>::Inner inner0; +N0::X0<int>::Inner inner1; +N0::X0<long>::Inner inner2; +N0::X0<float>::Inner inner3; +N0::X0<double>::Inner inner4; // expected-error{{incomplete}} + +// -- member class template of a class template +namespace N0 { + template<> + template<> + struct X0<void*>::InnerTemplate<int> { }; + + template<> template<> + struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}} + + template<> template<> + struct X0<int>::InnerTemplate<long>; + + template<> template<> + struct X0<int>::InnerTemplate<double>; +} + +template<> template<> +struct N0::X0<int>::InnerTemplate<long> { }; // okay + +template<> template<> +struct N0::X0<int>::InnerTemplate<float> { }; + +namespace N1 { + template<> template<> + struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}} +} + +N0::X0<void*>::InnerTemplate<int> inner_template0; +N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}} +N0::X0<int>::InnerTemplate<long> inner_template2; +N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}} + +// -- member function template of a class template +namespace N0 { + template<> + template<> + void X0<void*>::ft1(void*, const void*) { } + + template<> template<> + void X0<void*>::ft1(void *, int); + + template<> template<> + void X0<void*>::ft1(void *, unsigned); + + template<> template<> + void X0<void*>::ft1(void *, long); +} + +template<> template<> +void N0::X0<void*>::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0<void*>::ft1(void *, float) { } + +namespace N1 { + template<> template<> + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} +} + + +void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp, + int i, unsigned u) { + xvp.ft1(vp, cvp); + xvp.ft1(vp, i); + xvp.ft1(vp, u); +} + +namespace has_inline_namespaces { + inline namespace inner { + template<class T> void f(T&); + + template<class T> + struct X0 { + struct MemberClass; + + void mem_func(); + + template<typename U> + struct MemberClassTemplate; + + template<typename U> + void mem_func_template(U&); + + static int value; + }; + } + + struct X1; + struct X2; + + // An explicit specialization whose declarator-id is not qualified + // shall be declared in the nearest enclosing namespace of the + // template, or, if the namespace is inline (7.3.1), any namespace + // from its enclosing namespace set. + template<> void f(X1&); + template<> void f<X2>(X2&); + + template<> struct X0<X1> { }; + + template<> struct X0<X2>::MemberClass { }; + + template<> void X0<X2>::mem_func(); + + template<> template<typename T> struct X0<X2>::MemberClassTemplate { }; + + template<> template<typename T> void X0<X2>::mem_func_template(T&) { } + + template<> int X0<X2>::value = 12; +} + +struct X3; +struct X4; + +template<> void has_inline_namespaces::f(X3&); +template<> void has_inline_namespaces::f<X4>(X4&); + +template<> struct has_inline_namespaces::X0<X3> { }; + +template<> struct has_inline_namespaces::X0<X4>::MemberClass { }; + +template<> void has_inline_namespaces::X0<X4>::mem_func(); + +template<> template<typename T> +struct has_inline_namespaces::X0<X4>::MemberClassTemplate { }; + +template<> template<typename T> +void has_inline_namespaces::X0<X4>::mem_func_template(T&) { } + +template<> int has_inline_namespaces::X0<X4>::value = 13; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp new file mode 100644 index 0000000..c972bf7 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -0,0 +1,252 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The specializations are alternately +// declarations and definitions, and the intent of this test is to verify +// that we allow specializations only in the appropriate namespaces (and +// nowhere else). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +namespace N0 { + template<typename T> void f0(T) { // expected-note{{here}} + T t; + } + + template<> void f0(NonDefaultConstructible) { } + + void test_f0(NonDefaultConstructible NDC) { + f0(NDC); + } + + template<> void f0(int); + template<> void f0(long); +} + +template<> void N0::f0(int) { } // okay + +namespace N1 { + template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} +} + +template<> void N0::f0(double); // expected-warning{{C++11 extension}} +template<> void N0::f0(double) { } + +struct X1 { + template<typename T> void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template<typename T> +struct X0 { // expected-note 2{{here}} + static T member; // expected-note{{here}} + + void f1(T t) { // expected-note{{explicitly specialized declaration is here}} + t = 17; + } + + struct Inner : public T { }; // expected-note 3{{here}} + + template<typename U> + struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template<typename U> + void ft1(T t, U u); // expected-note{{explicitly specialized}} +}; + +} + +template<typename T> +template<typename U> +void N0::X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T N0::X0<T>::member; + +template<> struct N0::X0<void> { }; // expected-warning{{C++11 extension}} +N0::X0<void> test_X0; + +namespace N1 { + template<> struct N0::X0<const void> { }; // expected-error{{originally}} +} + +namespace N0 { + template<> struct X0<volatile void>; +} + +template<> struct N0::X0<volatile void> { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0<void*>::f1(void *) { } // expected-warning{{member function specialization}} + +void test_spec(N0::X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +namespace N0 { + template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}} + + template<> void X0<const volatile void*>::f1(const volatile void*); +} + +void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) { + x0.f1(cvp); // okay: we've explicitly specialized +} + +// -- static data member of a class template +namespace N0 { + // This actually tests p15; the following is a declaration, not a definition. + template<> + NonDefaultConstructible X0<NonDefaultConstructible>::member; + + template<> long X0<long>::member = 17; + + template<> float X0<float>::member; + + template<> double X0<double>::member; +} + +NonDefaultConstructible &get_static_member() { + return N0::X0<NonDefaultConstructible>::member; +} + +template<> int N0::X0<int>::member; // expected-warning{{C++11 extension}} + +template<> float N0::X0<float>::member = 3.14f; + +namespace N1 { + template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}} +} + +// -- member class of a class template +namespace N0 { + + template<> + struct X0<void*>::Inner { }; + + template<> + struct X0<int>::Inner { }; + + template<> + struct X0<unsigned>::Inner; + + template<> + struct X0<float>::Inner; + + template<> + struct X0<double>::Inner; // expected-note{{forward declaration}} +} + +template<> +struct N0::X0<long>::Inner { }; // expected-warning{{C++11 extension}} + +template<> +struct N0::X0<float>::Inner { }; + +namespace N1 { + template<> + struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}} + + template<> + struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}} +}; + +N0::X0<void*>::Inner inner0; +N0::X0<int>::Inner inner1; +N0::X0<long>::Inner inner2; +N0::X0<float>::Inner inner3; +N0::X0<double>::Inner inner4; // expected-error{{incomplete}} + +// -- member class template of a class template +namespace N0 { + template<> + template<> + struct X0<void*>::InnerTemplate<int> { }; + + template<> template<> + struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}} + + template<> template<> + struct X0<int>::InnerTemplate<long>; + + template<> template<> + struct X0<int>::InnerTemplate<double>; +} + +template<> template<> +struct N0::X0<int>::InnerTemplate<long> { }; // okay + +template<> template<> +struct N0::X0<int>::InnerTemplate<float> { }; // expected-warning{{class template specialization}} + +namespace N1 { + template<> template<> + struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}} +} + +N0::X0<void*>::InnerTemplate<int> inner_template0; +N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}} +N0::X0<int>::InnerTemplate<long> inner_template2; +N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}} + +// -- member function template of a class template +namespace N0 { + template<> + template<> + void X0<void*>::ft1(void*, const void*) { } + + template<> template<> + void X0<void*>::ft1(void *, int); + + template<> template<> + void X0<void*>::ft1(void *, unsigned); + + template<> template<> + void X0<void*>::ft1(void *, long); +} + +template<> template<> +void N0::X0<void*>::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0<void*>::ft1(void *, float) { } // expected-warning{{function template specialization}} + +namespace N1 { + template<> template<> + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} +} + + +void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp, + int i, unsigned u) { + xvp.ft1(vp, cvp); + xvp.ft1(vp, i); + xvp.ft1(vp, u); +} + +namespace PR8979 { + template<typename Z> + struct X0 { + template <class T, class U> class Inner; + struct OtherInner; + template<typename T, typename U> void f(Inner<T, U>&); + + typedef Inner<OtherInner, OtherInner> MyInner; + template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}} + }; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp new file mode 100644 index 0000000..86cdcf8 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +void f(T); + +template<typename T> +struct A { }; + +struct X { + template<> friend void f<int>(int); // expected-error{{in a friend}} + template<> friend class A<int>; // expected-error{{cannot be a friend}} + + friend void f<float>(float); // okay + friend class A<float>; // okay +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp new file mode 100644 index 0000000..ab26f40 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X { + void mf1(T); + template<typename U> void mf2(T, U); // expected-note{{previous}} +}; + +template<> +void X<int>::mf1(int i = 17) // expected-error{{default}} +{ +} + +template<> template<> +void X<int>::mf2(int, int = 17) // expected-error{{default}} +{ } + +template<> template<typename U> +void X<int>::mf2(int, U = U()) // expected-error{{default}} +{ +} + +template<> +struct X<float> { + void mf1(float); +}; + +void X<float>::mf1(float = 3.14f) // okay +{ +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp new file mode 100644 index 0000000..84841cb --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + template<class T> class X; +} + +template<> class X<int> { /* ... */ }; // expected-error {{non-template class 'X'}} + +namespace N { + +template<> class X<char*> { /* ... */ }; // OK: X is a template + +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp new file mode 100644 index 0000000..772aef6 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct IntHolder { // expected-note{{here}} // expected-note 2{{candidate constructor (the implicit copy constructor)}} + IntHolder(int); // expected-note 2{{candidate constructor}} +}; + +template<typename T, typename U> +struct X { // expected-note{{here}} + void f() { + T t; // expected-error{{no matching}} + } + + void g() { } + + struct Inner { // expected-error{{implicit default}} + T value; // expected-note {{member is declared here}} + }; + + static T value; +}; + +template<typename T, typename U> +T X<T, U>::value; // expected-error{{no matching constructor}} + +IntHolder &test_X_IntHolderInt(X<IntHolder, int> xih) { + xih.g(); // okay + xih.f(); // expected-note{{instantiation}} + + X<IntHolder, int>::Inner inner; // expected-note {{first required here}} + + return X<IntHolder, int>::value; // expected-note{{instantiation}} +} + +// Explicitly specialize the members of X<IntHolder, long> to not cause +// problems with instantiation. +template<> +void X<IntHolder, long>::f() { } + +template<> +struct X<IntHolder, long>::Inner { + Inner() : value(17) { } + IntHolder value; +}; + +template<> +IntHolder X<IntHolder, long>::value = 17; + +IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X<IntHolder, long>::Inner inner; // okay, uses specialization + + return X<IntHolder, long>::value; // okay, uses specialization +} + +template<> +X<IntHolder, long>::X() { } // expected-error{{instantiated member}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp new file mode 100644 index 0000000..f49190e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> struct A { + struct B { }; + template<class U> struct C { }; +}; + template<> struct A<int> { + void f(int); +}; +void h() { + A<int> a; + a.f(16); +} +// A<int>::f must be defined somewhere +// template<> not used for a member of an // explicitly specialized class template +void A<int>::f(int) { /* ... */ } + template<> struct A<char>::B { + void f(); +}; +// template<> also not used when defining a member of // an explicitly specialized member class +void A<char>::B::f() { /* ... */ } + template<> template<class U> struct A<char>::C { + void f(); +}; + +template<> +template<class U> void A<char>::C<U>::f() { /* ... */ } + template<> struct A<short>::B { + void f(); +}; +template<> void A<short>::B::f() { /* ... */ } // expected-error{{no function template matches function template specialization 'f'}} + template<> template<class U> struct A<short>::C { + void f(); +}; +template<class U> void A<short>::C<U>::f() { /* ... */ } // expected-error{{template parameter list matching the non-templated nested type 'A<short>' should be empty ('template<>')}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp new file mode 100644 index 0000000..512ea47 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct IntHolder { + IntHolder(int); +}; + +template<typename T, typename U> +struct X { + void f() { + T t; + } + + void g() { } + + struct Inner { + T value; + }; + + static T value; +}; + +template<typename T, typename U> +T X<T, U>::value; + +// Explicitly specialize the members of X<IntHolder, long> to not cause +// problems with instantiation, but only provide declarations (not definitions). +template<> +void X<IntHolder, long>::f(); + +template<> +struct X<IntHolder, long>::Inner; // expected-note{{forward declaration}} + +template<> +IntHolder X<IntHolder, long>::value; + +IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X<IntHolder, long>::Inner inner; // expected-error {{incomplete}} + + return X<IntHolder, long>::value; // okay, uses specialization +} + + +template<class T> struct A { + void f(T) { /* ... */ } +}; + +template<> struct A<int> { + void f(int); +}; + +void h() { + A<int> a; + a.f(16); // A<int>::f must be defined somewhere +} + +// explicit specialization syntax not used for a member of +// explicitly specialized class template specialization +void A<int>::f(int) { /* ... */ } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp new file mode 100644 index 0000000..f539471 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + void f(); + + template<typename U> + void g(U); + + struct Nested { + }; + + static T member; +}; + +int &use_X0_int(X0<int> x0i, // expected-note{{implicit instantiation first required here}} + int i) { + x0i.f(); // expected-note{{implicit instantiation first required here}} + x0i.g(i); // expected-note{{implicit instantiation first required here}} + X0<int>::Nested nested; // expected-note{{implicit instantiation first required here}} + return X0<int>::member; // expected-note{{implicit instantiation first required here}} +} + +template<> +void X0<int>::f() { // expected-error{{after instantiation}} +} + +template<> template<> +void X0<int>::g(int) { // expected-error{{after instantiation}} +} + +template<> +struct X0<int>::Nested { }; // expected-error{{after instantiation}} + +template<> +int X0<int>::member = 17; // expected-error{{after instantiation}} + +template<> +struct X0<int> { }; // expected-error{{after instantiation}} + +// Example from the standard +template<class T> class Array { /* ... */ }; + +template<class T> void sort(Array<T>& v) { /* ... */ } + +struct String {}; + +void f(Array<String>& v) { + + sort(v); // expected-note{{required}} + // use primary template + // sort(Array<T>&), T is String +} + +template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}} +template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used + +namespace PR6160 { + template<typename T> void f(T); + template<> void f(int); + extern template void f(int); + template<> void f(int) { } +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp new file mode 100644 index 0000000..d4ce01f --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + template<class T> class X { /* ... */ }; + template<class T> class Y { /* ... */ }; + template<> class X<int> { /* ... */ }; + template<> class Y<double>; + + const unsigned NumElements = 17; +} + +template<> class N::Y<double> { + int array[NumElements]; +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp new file mode 100644 index 0000000..80f0598 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T> +struct X { + void f() {} +}; + +template inline void X<int>::f(); // expected-error{{explicit instantiation cannot be 'inline'}} + +template<typename T> +struct Y { + constexpr int f() { return 0; } +}; + +template constexpr int Y<int>::f(); // expected-error{{explicit instantiation cannot be 'constexpr'}} + +template<typename T> +struct Z { + enum E : T { e1, e2 }; + T t; // expected-note {{refers here}} +}; + +template enum Z<int>::E; // expected-error {{enumerations cannot be explicitly instantiated}} +template int Z<int>::t; // expected-error {{explicit instantiation of 't' does not refer to}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp new file mode 100644 index 0000000..d0df305 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s +template<typename T> +struct X { + static T member1; + static T member2; + static T member3; +}; + +template<typename T> +T X<T>::member1; + +template<typename T> +T X<T>::member2 = 17; + +// CHECK: @_ZN1XIiE7member1E = weak_odr global i32 0 +template int X<int>::member1; + +// CHECK: @_ZN1XIiE7member2E = weak_odr global i32 17 +template int X<int>::member2; + +// For implicit instantiation of +long& get(bool Cond1, bool Cond2) { + // CHECK: @_ZN1XIlE7member1E = weak_odr global i64 0 + // CHECK: @_ZN1XIlE7member2E = weak_odr global i64 17 + // CHECK: @_ZN1XIlE7member3E = external global i64 + return Cond1? X<long>::member1 + : Cond2? X<long>::member2 + : X<long>::member3; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp new file mode 100644 index 0000000..b426339 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct C { }; + +template<typename T> +struct X0 { + T value; // expected-error{{incomplete}} +}; + +// Explicitly instantiate a class template specialization +template struct X0<int>; +template struct X0<void>; // expected-note{{instantiation}} + +// Explicitly instantiate a function template specialization +template<typename T> +void f0(T t) { + ++t; // expected-error{{cannot increment}} +} + +template void f0(int); +template void f0<long>(long); +template void f0<>(unsigned); +template void f0(int C::*); // expected-note{{instantiation}} + +// Explicitly instantiate a member template specialization +template<typename T> +struct X1 { + template<typename U> + struct Inner { + T member1; + U member2; // expected-error{{incomplete}} + }; + + template<typename U> + void f(T& t, U u) { + t = u; // expected-error{{incompatible}} + } +}; + +template struct X1<int>::Inner<float>; +template struct X1<int>::Inner<double>; +template struct X1<int>::Inner<void>; // expected-note{{instantiation}} + +template void X1<int>::f(int&, float); +template void X1<int>::f<long>(int&, long); +template void X1<int>::f<>(int&, double); +template void X1<int>::f<>(int&, int*); // expected-note{{instantiation}} + +// Explicitly instantiate members of a class template +struct Incomplete; // expected-note{{forward declaration}} +struct NonDefaultConstructible { // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + NonDefaultConstructible(int); // expected-note{{candidate constructor}} +}; + +template<typename T, typename U> +struct X2 { + void f(T &t, U u) { + t = u; // expected-error{{incompatible}} + } + + struct Inner { + T member1; + U member2; // expected-error{{incomplete}} + }; + + static T static_member1; + static U static_member2; +}; + +template<typename T, typename U> +T X2<T, U>::static_member1 = 17; // expected-error{{cannot initialize}} + +template<typename T, typename U> +U X2<T, U>::static_member2; // expected-error{{no matching}} + +template void X2<int, float>::f(int &, float); +template void X2<int, float>::f(int &, double); // expected-error{{does not refer}} +template void X2<int, int*>::f(int&, int*); // expected-note{{instantiation}} + +template struct X2<int, float>::Inner; +template struct X2<int, Incomplete>::Inner; // expected-note{{instantiation}} + +template int X2<int, float>::static_member1; +template int* X2<int*, float>::static_member1; // expected-note{{instantiation}} +template + NonDefaultConstructible X2<NonDefaultConstructible, int>::static_member1; + +template + NonDefaultConstructible X2<int, NonDefaultConstructible>::static_member2; // expected-note{{instantiation}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp new file mode 100644 index 0000000..290a874 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + void f(T&); + + struct Inner; + + static T static_var; +}; + +template<typename T> +void X0<T>::f(T& t) { + t = 1; // expected-error{{incompatible type}} +} + +template<typename T> +struct X0<T>::Inner { + T member; +}; + +template<typename T> +T X0<T>::static_var = 1; // expected-error{{cannot initialize}} + +extern template struct X0<void*>; +template struct X0<void*>; // expected-note 2{{instantiation}} + +template struct X0<int>; // expected-note 4{{explicit instantiation definition is here}} + +extern template void X0<int>::f(int&); // expected-error{{follows explicit instantiation definition}} +extern template struct X0<int>::Inner; // expected-error{{follows explicit instantiation definition}} +extern template int X0<int>::static_var; // expected-error{{follows explicit instantiation definition}} +extern template struct X0<int>; // expected-error{{follows explicit instantiation definition}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp new file mode 100644 index 0000000..4ca5428 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X { + template <typename T> class Y {}; +}; + +class A { + class B {}; + class C {}; +}; + +// C++0x [temp.explicit] 14.7.2/11: +// The usual access checking rules do not apply to names used to specify +// explicit instantiations. +template class X::Y<A::B>; + +// As an extension, this rule is applied to explicit specializations as well. +template <> class X::Y<A::C> {}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp new file mode 100644 index 0000000..c756486 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +char* p = 0; +template<class T> T g(T x = &p) { return x; } +template int g<int>(int); // OK even though &p isn't an int. + diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp new file mode 100644 index 0000000..1dfcf0c --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s + +// Example from the standard +template<class T> class Array { void mf() { } }; + +template class Array<char>; +template void Array<int>::mf(); +template<class T> void sort(Array<T>& v) { /* ... */ } +template void sort(Array<char>&); +namespace N { + template<class T> void f(T&) { } +} +template void N::f<int>(int&); + + +template<typename T> +struct X0 { + struct Inner {}; + void f() { } + static T value; +}; + +template<typename T> +T X0<T>::value = 17; + +typedef X0<int> XInt; + +template struct XInt::Inner; // expected-warning{{template-id}} +template void XInt::f(); // expected-warning{{template-id}} +template int XInt::value; // expected-warning{{template-id}} + +namespace N { + template<typename T> + struct X1 { // expected-note{{explicit instantiation refers here}} + }; + + template<typename T> + void f1(T) {} // expected-note{{explicit instantiation refers here}} +} +using namespace N; + +template struct X1<int>; // expected-warning{{must occur in}} +template void f1(int); // expected-warning{{must occur in}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp new file mode 100644 index 0000000..1028830 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// If the name declared in the explicit instantiation is an +// unqualified name, the explicit instantiation shall appear in the +// namespace where its template is declared or, if that namespace is +// inline (7.3.1), any namespace from its enclosing namespace set. + +namespace has_inline_namespaces { + inline namespace inner { + template<class T> void f(T&) {} + + template<class T> + struct X0 { + struct MemberClass {}; + + void mem_func() {} + + template<typename U> + struct MemberClassTemplate {}; + + template<typename U> + void mem_func_template(U&) {} + + static int value; + }; + } + + template<typename T> int X0<T>::value = 17; + + struct X1 {}; + struct X2 {}; + + template void f(X1&); + template void f<X2>(X2&); + + template struct X0<X1>; + + template struct X0<X2>::MemberClass; + + template void X0<X2>::mem_func(); + + template struct X0<X2>::MemberClassTemplate<X1>; + + template void X0<X2>::mem_func_template(X1&); + + template int X0<X2>::value; +} + +struct X3; +struct X4; + +template void has_inline_namespaces::f(X3&); +template void has_inline_namespaces::f<X4>(X4&); + +template struct has_inline_namespaces::X0<X3>; + +template struct has_inline_namespaces::X0<X4>::MemberClass; + +template void has_inline_namespaces::X0<X4>::mem_func(); + +template +struct has_inline_namespaces::X0<X4>::MemberClassTemplate<X3>; + +template +void has_inline_namespaces::X0<X4>::mem_func_template(X3&); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp new file mode 100644 index 0000000..38ae768 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +// A declaration of a function template shall be in scope at the point of the +// explicit instantiation of the function template. +template<typename T> void f0(T); +template void f0(int); // okay +template<typename T> void f0(T) { } + +// A definition of the class or class template containing a member function +// template shall be in scope at the point of the explicit instantiation of +// the member function template. +struct X0; // expected-note {{forward declaration}} +template<typename> struct X1; // expected-note 5{{declared here}} + +template void X0::f0<int>(int); // expected-error {{incomplete type}} +template void X1<int>::f0<int>(int); // expected-error {{implicit instantiation of undefined template}} + +// A definition of a class template or class member template shall be in scope +// at the point of the explicit instantiation of the class template or class +// member template. +template struct X1<float>; // expected-error{{explicit instantiation of undefined template}} + +template<typename T> +struct X2 { // expected-note 4{{refers here}} + template<typename U> + struct Inner; // expected-note{{declared here}} + + struct InnerClass; // expected-note{{forward declaration}} +}; + +template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation of undefined template}} + +// A definition of a class template shall be in scope at the point of an +// explicit instantiation of a member function or a static data member of the +// class template. +template void X1<int>::f1(int); // expected-error {{undefined template}} +template void X1<int>::f1<int>(int); // expected-error {{undefined template}} + +template int X1<int>::member; // expected-error {{undefined template}} + +// A definition of a member class of a class template shall be in scope at the +// point of an explicit instantiation of the member class. +template struct X2<float>::InnerClass; // expected-error{{undefined member}} + +// If the declaration of the explicit instantiation names an implicitly-declared +// special member function (Clause 12), the program is ill-formed. +template X2<int>::X2(); // expected-error{{not an instantiation}} +template X2<int>::X2(const X2&); // expected-error{{not an instantiation}} +template X2<int>::~X2(); // expected-error{{not an instantiation}} +template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}} + + +// A definition of a class template is sufficient to explicitly +// instantiate a member of the class template which itself is not yet defined. +namespace PR7979 { + template <typename T> struct S { + void f(); + static void g(); + static int i; + struct S2 { + void h(); + }; + }; + + template void S<int>::f(); + template void S<int>::g(); + template int S<int>::i; + template void S<int>::S2::h(); + + template <typename T> void S<T>::f() {} + template <typename T> void S<T>::g() {} + template <typename T> int S<T>::i; + template <typename T> void S<T>::S2::h() {} +} + +namespace PR11599 { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + + extern template class BasicStringPiece<int>; // expected-error{{explicit instantiation of undefined template 'PR11599::BasicStringPiece<int>}} + template class BasicStringPiece<int>; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp new file mode 100644 index 0000000..09c428e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s + +template<typename T> void f0(T); // expected-note{{here}} +template void f0(int); // expected-error{{explicit instantiation of undefined function template}} + +template<typename T> +struct X0 { + struct Inner; + + void f1(); // expected-note{{here}} + + static T value; // expected-note{{here}} +}; + +template void X0<int>::f1(); // expected-error{{explicit instantiation of undefined member function}} + +template int X0<int>::value; // expected-error{{explicit instantiation of undefined static data member}} + +template<> void f0(long); // expected-note{{previous template specialization is here}} +template void f0(long); // expected-warning{{explicit instantiation of 'f0<long>' that occurs after an explicit specialization will be ignored}} + +template<> void X0<long>::f1(); // expected-note{{previous template specialization is here}} +template void X0<long>::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization will be ignored}} + +template<> struct X0<long>::Inner; // expected-note{{previous template specialization is here}} +template struct X0<long>::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization will be ignored}} + +template<> long X0<long>::value; // expected-note{{previous template specialization is here}} +template long X0<long>::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization will be ignored}} + +template<> struct X0<double>; // expected-note{{previous template specialization is here}} +template struct X0<double>; // expected-warning{{explicit instantiation of 'X0<double>' that occurs after an explicit specialization will be ignored}} + +// PR 6458 +namespace test0 { + template <class T> class foo { + int compare(T x, T y); + }; + + template <> int foo<char>::compare(char x, char y); + template <class T> int foo<T>::compare(T x, T y) { + // invalid at T=char; if we get a diagnostic here, we're + // inappropriately instantiating this template. + void *ptr = x; + } + extern template class foo<char>; // expected-warning {{extern templates are a C++11 extension}} + template class foo<char>; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp new file mode 100644 index 0000000..8422c51 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +namespace N { + template<class T> class Y { // expected-note{{explicit instantiation refers here}} + void mf() { } + }; +} + +template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}} + +// FIXME: This example from the standard is wrong; note posted to CWG reflector +// on 10/27/2009 +using N::Y; +template class Y<int>; // expected-warning{{must occur in}} + +template class N::Y<char*>; +template void N::Y<double>::mf(); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp new file mode 100644 index 0000000..1382272 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v) { } + +// instantiate sort(Array<int>&) - template-argument deduced +template void sort<>(Array<int>&); + +template void sort(Array<long>&); + +template<typename T, typename U> void f0(T, U*) { } + +template void f0<int>(int, float*); +template void f0<>(double, float*); + +template<typename T> struct hash { }; +struct S { + bool operator==(const S&) const { return false; } +}; + +template<typename T> struct Hash_map { + void Method(const T& x) { h(x); } + hash<T> h; +}; + +Hash_map<S> *x; +const Hash_map<S> *foo() { + return x; +} + +template<> struct hash<S> { + int operator()(const S& k) const { + return 0; + } +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp new file mode 100644 index 0000000..7398dca --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + struct MemberClass { + T member; // expected-error{{with function type}} + }; + + T* f0(T* ptr) { + return ptr + 1; // expected-error{{pointer to the function}} + } + + static T* static_member; +}; + +template<typename T> +T* X0<T>::static_member = ((T*)0) + 1; // expected-error{{pointer to the function}} + +template class X0<int>; // okay + +template class X0<int(int)>; // expected-note 3{{requested here}} + +// Specialize everything, so that the explicit instantiation does not trigger +// any diagnostics. +template<> +struct X0<int(long)>::MemberClass { }; + +typedef int int_long_func(long); +template<> +int_long_func *X0<int_long_func>::f0(int_long_func *) { return 0; } + +template<> +int_long_func *X0<int(long)>::static_member; + +template class X0<int(long)>; + diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp new file mode 100644 index 0000000..550078a --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template<typename T> +struct X0 { + struct MemberClass; + + T* f0(T* ptr); + + static T* static_member; +}; + +template class X0<int(int)>; // ok; nothing gets instantiated. + +template<typename T> +struct X0<T>::MemberClass { + T member; +}; + +template<typename T> +T* X0<T>::f0(T* ptr) { + return ptr + 1; +} + +template<typename T> +T* X0<T>::static_member = 0; + +template class X0<int>; // ok + + +template<typename T> +struct X1 { + enum class E { + e = T::error // expected-error 2{{no members}} + }; +}; +template struct X1<int>; // expected-note {{here}} + +extern template struct X1<char>; // ok + +template struct X1<char>; // expected-note {{here}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp new file mode 100644 index 0000000..04e7df5 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -O1 -emit-llvm -std=c++11 -o - %s | FileCheck %s + +template<typename T> +struct X0 { + void f(T &t) { + t = 0; + } + + void g(T &t); + + void h(T &t); + + static T static_var; +}; + +template<typename T> +inline void X0<T>::g(T & t) { + t = 0; +} + +template<typename T> +void X0<T>::h(T & t) { + t = 0; +} + +template<typename T> +T X0<T>::static_var = 0; + +extern template struct X0<int*>; + +int *&test(X0<int*> xi, int *ip) { + // CHECK: define available_externally void @_ZN2X0IPiE1fERS0_ + xi.f(ip); + // CHECK: define available_externally void @_ZN2X0IPiE1gERS0_ + xi.g(ip); + // CHECK: declare void @_ZN2X0IPiE1hERS0_ + xi.h(ip); + return X0<int*>::static_var; +} + +template<typename T> +void f0(T& t) { + t = 0; +} + +template<typename T> +inline void f1(T& t) { + t = 0; +} + +extern template void f0<>(int *&); +extern template void f1<>(int *&); + +void test_f0(int *ip, float *fp) { + // CHECK: declare void @_Z2f0IPiEvRT_ + f0(ip); + // CHECK: define linkonce_odr void @_Z2f0IPfEvRT_ + f0(fp); +} + +void test_f1(int *ip, float *fp) { + // CHECK: define available_externally void @_Z2f1IPiEvRT_ + f1(ip); + // CHECK: define linkonce_odr void @_Z2f1IPfEvRT_ + f1(fp); +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp new file mode 100644 index 0000000..8649017 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T> +struct X0 { + void f(T &t) { + t = 1; // expected-error{{incompatible type}} + } + + void g(T &t); + + void h(T &t); + + static T static_var; +}; + +template<typename T> +inline void X0<T>::g(T & t) { + t = 1; // expected-error{{incompatible type}} +} + +template<typename T> +void X0<T>::h(T & t) { + t = 1; +} + +template<typename T> +T X0<T>::static_var = 1; + +extern template struct X0<int*>; + +int *&test(X0<int*> xi, int *ip) { + xi.f(ip); // expected-note{{instantiation}} + xi.g(ip); // expected-note{{instantiation}} + xi.h(ip); + return X0<int*>::static_var; +} + +template<typename T> +void f0(T& t) { + t = 1; // expected-error{{incompatible type}} +} + +template<typename T> +inline void f1(T& t) { + t = 1; // expected-error 2{{incompatible type}} +} + +extern template void f0<>(int *&); +extern template void f1<>(int *&); + +void test_f0(int *ip, float *fp) { + f0(ip); + f0(fp); // expected-note{{instantiation}} +} + +void test_f1(int *ip, float *fp) { + f1(ip); // expected-note{{instantiation}} + f1(fp); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp new file mode 100644 index 0000000..8684fc4 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// The implicit specialization of a class template specialuzation causes the +// implicit instantiation of the declarations, but not the definitions or +// default arguments, of: + +// FIXME: Many omitted cases + +// - scoped member enumerations +namespace ScopedEnum { + template<typename T> struct ScopedEnum1 { + enum class E { + e = T::error // expected-error {{'double' cannot be used prior to '::'}} + }; + }; + ScopedEnum1<int> se1; // ok + + template<typename T> struct ScopedEnum2 { + enum class E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + ScopedEnum2<void*> se2; // expected-note {{here}} + + template<typename T> struct UnscopedEnum3 { + enum class E : T { + e = 4 + }; + int arr[(int)E::e]; + }; + UnscopedEnum3<int> ue3; // ok + + ScopedEnum1<double>::E e1; // ok + ScopedEnum1<double>::E e2 = decltype(e2)::e; // expected-note {{in instantiation of enumeration 'ScopedEnum::ScopedEnum1<double>::E' requested here}} + + // The behavior for enums defined within function templates is not clearly + // specified by the standard. We follow the rules for enums defined within + // class templates. + template<typename T> + int f() { + enum class E { + e = T::error + }; + return (int)E(); + } + int test1 = f<int>(); + + template<typename T> + int g() { + enum class E { + e = T::error // expected-error {{has no members}} + }; + return E::e; // expected-note {{here}} + } + int test2 = g<int>(); // expected-note {{here}} +} + +// And it cases the implicit instantiations of the definitions of: + +// - unscoped member enumerations +namespace UnscopedEnum { + template<typename T> struct UnscopedEnum1 { + enum E { + e = T::error // expected-error {{'int' cannot be used prior to '::'}} + }; + }; + UnscopedEnum1<int> ue1; // expected-note {{here}} + + template<typename T> struct UnscopedEnum2 { + enum E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + UnscopedEnum2<void*> ue2; // expected-note {{here}} + + template<typename T> struct UnscopedEnum3 { + enum E : T { + e = 4 + }; + int arr[E::e]; + }; + UnscopedEnum3<int> ue3; // ok + + template<typename T> + int f() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return (int)E(); + } + int test1 = f<int>(); // expected-note {{here}} + + template<typename T> + int g() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return E::e; + } + int test2 = g<int>(); // expected-note {{here}} +} + +// FIXME: +//- - member anonymous unions diff --git a/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp new file mode 100644 index 0000000..8184071 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -emit-llvm-only %s + +// rdar://problem/7838962 +namespace test0 { + template<typename T> unsigned f0() { + return T::MaxSize; // expected-error {{'int' cannot be used prior to '::'}} + }; + template<typename T> struct A { + void Allocate(unsigned Alignment + = f0<T>()) // expected-note {{in instantiation}} + {} + }; + void f1(A<int> x) { x.Allocate(); } + +} diff --git a/clang/test/CXX/temp/temp.type/p1-0x.cpp b/clang/test/CXX/temp/temp.type/p1-0x.cpp new file mode 100644 index 0000000..35d00c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.type/p1-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace Old { + template<template<class> class TT> struct X { }; + template<class> struct Y { }; + template<class T> using Z = Y<T>; + X<Y> y; + X<Z> z; + + using SameType = decltype(y); // expected-note {{here}} + using SameType = decltype(z); // expected-error {{different types}} +} + +namespace New { + template<class T> struct X { }; + template<class> struct Y { }; + template<class T> using Z = Y<T>; + X<Y<int>> y; + X<Z<int>> z; + + using SameType = decltype(y); + using SameType = decltype(z); // ok +} |