diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/CXX/temp/temp.arg | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/CXX/temp/temp.arg')
6 files changed, 462 insertions, 0 deletions
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}} + } +} |