From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- .../temp/temp.decls/temp.variadic/deduction.cpp | 50 +++ .../temp/temp.decls/temp.variadic/example-bind.cpp | 352 ++++++++++++++++++ .../temp.decls/temp.variadic/example-function.cpp | 86 +++++ .../temp.decls/temp.variadic/example-tuple.cpp | 260 +++++++++++++ .../temp/temp.decls/temp.variadic/ext-blocks.cpp | 46 +++ .../temp.decls/temp.variadic/fixed-expansion.cpp | 127 +++++++ .../temp.variadic/injected-class-name.cpp | 75 ++++ .../temp.decls/temp.variadic/metafunctions.cpp | 274 ++++++++++++++ .../temp.variadic/multi-level-substitution.cpp | 251 +++++++++++++ .../test/CXX/temp/temp.decls/temp.variadic/p1.cpp | 9 + .../test/CXX/temp/temp.decls/temp.variadic/p2.cpp | 22 ++ .../test/CXX/temp/temp.decls/temp.variadic/p4.cpp | 193 ++++++++++ .../test/CXX/temp/temp.decls/temp.variadic/p5.cpp | 403 +++++++++++++++++++++ .../temp.variadic/parameter-matching.cpp | 43 +++ .../temp.decls/temp.variadic/partial-ordering.cpp | 61 ++++ 15 files changed, 2252 insertions(+) create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp (limited to 'clang/test/CXX/temp/temp.decls/temp.variadic') 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 + struct X { }; + + template + void f0(X) { } + + // 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(X<1, float&>); + template void f0(X<1, double&>); + + // Two explicitly-specialized arguments + template void f0(X<2, char&, unsigned char&>); + template void f0(X<2, signed char&, char&>); + + // FIXME: Extension of explicitly-specified arguments + // template void f0(X<3, short&, int&, long&>); +} + +namespace DeductionWithConversion { + template struct char_values { + static const unsigned value = 0; + }; + + template + struct char_values { + static const unsigned value = 1; + }; + + int check0[char_values<1, 12, 3>::value == 1? 1 : -1]; + + template struct int_values { + static const unsigned value = 0; + }; + + template + struct int_values { + 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 +struct add_reference { + typedef T &type; +}; + +template +struct add_reference { + typedef T &type; +}; + +template +struct add_const_reference { + typedef T const &type; +}; + +template +struct add_const_reference { + typedef T &type; +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +template +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template reference_wrapper ref(T& t) { + return reference_wrapper(t); +} +template reference_wrapper cref(const T& t) { + return reference_wrapper(t); +} + +template class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template +class tuple : private tuple { + typedef tuple inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference::type v, + typename add_const_reference::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template tuple(const tuple& other) + : m_head(other.head()), inherited(other.tail()) { } + + template tuple& + operator=(const tuple& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference::type head() { return m_head; } + typename add_reference::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + +protected: + Head m_head; +}; + +// Creation functions +template +struct make_tuple_result { + typedef T type; +}; + +template +struct make_tuple_result > { + typedef T& type; +}; + +template +tuple::type...> +make_tuple(const Values&... values) { + return tuple::type...>(values...); +} + +template +tuple tie(Values&... values) { + return tuple(values...); +} + +// Helper classes +template struct tuple_size; + +template struct tuple_size > { + static const int value = sizeof...(Values); +}; + +template struct tuple_element; + +template +struct tuple_element > { + typedef typename tuple_element >::type type; +}; + +template +struct tuple_element<0, tuple > { + typedef Head type; +}; + +// Element access +template class get_impl; +template +class get_impl > { + typedef typename tuple_element >::type Element; + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; + typedef get_impl > Next; +public: + static RJ get(tuple& t) { return Next::get(t.tail()); } + static PJ get(const tuple& t) { return Next::get(t.tail()); } +}; + +template +class get_impl<0, tuple > { + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; +public: + static RJ get(tuple& t) { return t.head(); } + static PJ get(const tuple& t) { return t.head(); } +}; + +template typename add_reference< +typename tuple_element >::type >::type +get(tuple& t) { + return get_impl >::get(t); +} + +template typename add_const_reference< +typename tuple_element >::type >::type +get(const tuple& t) { + return get_impl >::get(t); +} + +// Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template +bool operator==(const tuple& t, const tuple& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template +bool operator!=(const tuple& t, const tuple& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template +bool operator<(const tuple& t, const tuple& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template +bool operator>(const tuple& t, const tuple& u) { + return u < t; +} + +template +bool operator<=(const tuple& t, const tuple& u) { + return !(u < t); +} + +template +bool operator>=(const tuple& t, const tuple& u) { + return !(t < u); +} + +// make_indices helper +template struct int_tuple {}; +// make_indexes impl is a helper for make_indexes +template struct make_indexes_impl; + +template +struct make_indexes_impl, T, Types...> { + typedef typename make_indexes_impl, Types...>::type type; +}; + +template +struct make_indexes_impl > { + typedef int_tuple type; +}; + +template +struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { +}; + +// Bind +template struct is_bind_expression { + static const bool value = false; +}; + +template struct is_placeholder { + static const int value = 0; +}; + + +template class bound_functor { + typedef typename make_indexes::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 F::result_type operator()(Args&... args); +private: F f; + tuple bound_args; +}; + +template +inline bound_functor bind(const F& f, const BoundArgs&... bound_args) { + return bound_functor(f, bound_args...); +} + +template +struct is_bind_expression > { + static const bool value = true; +}; + +// enable_if helper +template +struct enable_if; + +template +struct enable_if { + typedef T type; +}; + +template +struct enable_if { }; + +// safe_tuple_element helper +template +struct safe_tuple_element { }; + +template +struct safe_tuple_element, + typename enable_if<(I >= 0 && I < tuple_size >::value)>::type> { + typedef typename tuple_element >::type type; +}; + +// mu +template +inline typename safe_tuple_element::value -1, + tuple >::type +mu(Bound& bound_arg, const tuple& args) { + return get::value-1>(args); +} + +template +inline T& mu(reference_wrapper& bound_arg, const tuple&) { + return bound_arg.get(); +} + +template +inline typename F::result_type +unwrap_and_forward(F& f, int_tuple, const tuple& args) { + return f(get(args)...); +} + +template +inline typename enable_if::value, + typename Bound::result_type>::type +mu(Bound& bound_arg, const tuple& args) { + typedef typename make_indexes::type Indexes; + return unwrap_and_forward(bound_arg, Indexes(), args); +} + +template +struct is_reference_wrapper { + static const bool value = false; +}; + +template +struct is_reference_wrapper> { + static const bool value = true; +}; + +template +inline typename enable_if<(!is_bind_expression::value + && !is_placeholder::value + && !is_reference_wrapper::value), + Bound&>::type +mu(Bound& bound_arg, const tuple&) { + return bound_arg; +} + +template +typename F::result_type apply_functor(F& f, tuple& bound_args, + int_tuple, + const tuple& args) { + return f(mu(get(bound_args), args)...); +} + +template +template +typename F::result_type bound_functor::operator()(Args&... args) { + return apply_functor(f, bound_args, indexes(), tie(args...)); +} + +template struct placeholder { }; +template +struct is_placeholder> { + static const int value = N; +}; + +template +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(), 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 class function; + +template class invoker_base { +public: + virtual ~invoker_base() { } + virtual R invoke(Args...) = 0; + virtual invoker_base* clone() = 0; +}; + +template +class functor_invoker : public invoker_base { +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 +class function { +public: + typedef R result_type; + function() : invoker (0) { } + function(const function& other) : invoker(0) { + if (other.invoker) + invoker = other.invoker->clone(); + } + + template function(const F& f) : invoker(0) { + invoker = new functor_invoker(f); + } + + ~function() { + if (invoker) + delete invoker; + } + + function& operator=(const function& other) { + function(other).swap(*this); + return *this; + } + + template + function& operator=(const F& f) { + function(f).swap(*this); + return *this; + } + + void swap(function& other) { + invoker_base* tmp = invoker; + invoker = other.invoker; + other.invoker = tmp; + } + + result_type operator()(Args... args) const { + return invoker->invoke(args...); + } + +private: + invoker_base* invoker; +}; + +template +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 f2a; + function f2b = add(); + function f2c = add(); + function f2d(f2b); + function 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 +struct add_reference { + typedef T &type; +}; + +template +struct add_reference { + typedef T &type; +}; + +template +struct add_const_reference { + typedef T const &type; +}; + +template +struct add_const_reference { + typedef T &type; +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +template +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template reference_wrapper ref(T& t) { + return reference_wrapper(t); +} +template reference_wrapper cref(const T& t) { + return reference_wrapper(t); +} + +template class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template +class tuple : private tuple { + typedef tuple inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference::type v, + typename add_const_reference::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template tuple(const tuple& other) + : m_head(other.head()), inherited(other.tail()) { } + + template tuple& + operator=(const tuple& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference::type head() { return m_head; } + typename add_reference::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 t1a; + tuple t1b(17); + tuple t1c(t1b); + t1a = t1b; + + tuple t1d(3.14159); + tuple t1e(t1d); + t1d = t1e; + + int i; + float f; + double d; + tuple t3a(&i, &f, &d); +} + +// Creation functions +template +struct make_tuple_result { + typedef T type; +}; + +template +struct make_tuple_result > { + typedef T& type; +}; + +template +tuple::type...> +make_tuple(const Values&... values) { + return tuple::type...>(values...); +} + +template +tuple tie(Values&... values) { + return tuple(values...); +} + +template const T *addr(const T& ref) { return &ref; } +void test_creation_functions() { + int i; + float f; + double d; + const tuple *t3p = addr(make_tuple(i, ref(f), cref(d))); + const tuple *t3q = addr(tie(i, f, d)); +} + +// Helper classes +template struct tuple_size; + +template struct tuple_size > { + static const int value = sizeof...(Values); +}; + +int check_tuple_size_0[tuple_size >::value == 0? 1 : -1]; +int check_tuple_size_1[tuple_size>::value == 1? 1 : -1]; +int check_tuple_size_2[tuple_size>::value == 2? 1 : -1]; +int check_tuple_size_3[tuple_size>::value == 3? 1 : -1]; + +template struct tuple_element; + +template +struct tuple_element > { + typedef typename tuple_element >::type type; +}; + +template +struct tuple_element<0, tuple > { + typedef Head type; +}; + +int check_tuple_element_0[is_same>::type, + int&>::value? 1 : -1]; + +int check_tuple_element_1[is_same>::type, + float>::value? 1 : -1]; + +int check_tuple_element_2[is_same>::type, + double>::value? 1 : -1]; + +// Element access +template class get_impl; +template +class get_impl > { + typedef typename tuple_element >::type Element; + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; + typedef get_impl > Next; +public: + static RJ get(tuple& t) { return Next::get(t.tail()); } + static PJ get(const tuple& t) { return Next::get(t.tail()); } +}; + +template +class get_impl<0, tuple > { + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; +public: + static RJ get(tuple& t) { return t.head(); } + static PJ get(const tuple& t) { return t.head(); } +}; + +template typename add_reference< +typename tuple_element >::type >::type +get(tuple& t) { + return get_impl >::get(t); +} + +template typename add_const_reference< +typename tuple_element >::type >::type +get(const tuple& t) { + return get_impl >::get(t); +} + +void test_element_access(tuple 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 +bool operator==(const tuple& t, const tuple& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template +bool operator!=(const tuple& t, const tuple& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template +bool operator<(const tuple& t, const tuple& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template +bool operator>(const tuple& t, const tuple& u) { + return u < t; +} + +template +bool operator<=(const tuple& t, const tuple& u) { + return !(u < t); +} + +template +bool operator>=(const tuple& t, const tuple& u) { + return !(t < u); +} + +void test_relational_operators(tuple 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 +int f0(Args ...args) { + return ^ { + return sizeof...(Args); + }() + ^ { + return sizeof...(args); + }(); +} + +template +int f1(Args ...args) { + return ^ { + return f0(args...); + }(); +} + +template int f0(int, float, double); +template int f1(const char*, int, float, double); + +template +int f2(Args ...args) { + return ^(Args ...block_args) { + return f1(block_args...); + }(args + 0 ...); +} + +template int f2(const char*, int, float, double); + +template +int f3(Args ...args) { + return ^(Args *...block_args) { + return f1(block_args...); + }(&args...); +} + +template int f3(const char*, int, float, double); + +template +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 struct pair { }; +template struct tuple { }; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +namespace ExpandIntoFixed { + template, + typename W = V*> + class X0 { }; + + template + class X1 { + public: + typedef X0 type; + }; + + static_assert(is_same::type, + X0, pair*>>::value, + "fails with two default arguments"); + + static_assert(is_same::type, + X0>::value, + "fails with one default argument"); + + static_assert(is_same::type, + X0>::value, + "fails with no default arguments"); +} + +namespace ExpandIntoFixedShifted { + template, + typename W = V*> + class X0 { }; + + template + class X1 { + public: + typedef X0 type; + }; + + static_assert(is_same::type, + X0, pair*>>::value, + "fails with two default arguments"); + + static_assert(is_same::type, + X0>::value, + "fails with one default argument"); + + static_assert(is_same::type, + X0>::value, + "fails with no default arguments"); +} + +namespace Deduction { + template struct Foo {}; + template tuple &foo(Foo); + + void call_foo(Foo foo_if, Foo foo_i) { + tuple &t1 = foo(foo_if); + tuple &t2 = foo(foo_i); + } +} + +namespace PR9021a { + template + struct A { }; + + template + struct B { + A a1; + }; + + void test() { + B c; + } +} + +namespace PR9021b { + template + struct t2 + { + + }; + + template class M> + struct m + { + template + using inner = M; + }; + + m sta2; +} + +namespace PartialSpecialization { + template + struct X0; // expected-note{{template is declared here}} + + template + struct X0 { + }; + + X0 x0i; // expected-error{{too few template arguments for class template 'X0'}} + X0 x0if; + X0 x0ifd; +} + +namespace FixedAliasTemplate { + template struct S {}; + template using U = S; + template U &f(U, Ts...); + S &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 +struct X0 { + typedef T type; + + void f0(T); + type f1(T); +}; + +template +void X0::f0(T) { } + +template +typename X0::type X0::f1(T) { } + +template +struct X0 { + typedef T* result; + result f3(); + + template + struct Inner; +}; + +template +typename X0::result X0::f3() { return 0; } + +template +template +struct X0::Inner { + template void f4(); +}; + +template +template +template +void X0::Inner::f4() { } + +namespace rdar8848837 { + // Out-of-line definitions that cause rebuilding in the current + // instantiation. + template struct X; + + template + struct X { + X f(); + }; + + template + X X::f() { return *this; } + + + X xif; + + template struct unsigned_c { }; + template int g(ArgTypes...); + + template struct X1; + + template + struct X1 { + unsigned_c f(); + }; + + template + unsigned_c X1::f() { + return unsigned_c(); + } + + X1 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 +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +template struct tuple { }; +template struct int_tuple { }; +template struct pair { }; + +namespace Count { + template + struct count { + static const unsigned value = 1 + count::value; + }; + + template + struct count { + static const unsigned value = 1; + }; + + int check1[count::value == 1? 1 : -1]; + int check2[count::value == 2? 1 : -1]; + int check3[count::value == 3? 1 : -1]; +} + +namespace CountWithPackExpansion { + template struct count; + + template + struct count { + static const unsigned value = 1 + count::value; + }; + + template<> + struct count<> { + static const unsigned value = 0; + }; + + int check0[count<>::value == 0? 1 : -1]; + int check1[count::value == 1? 1 : -1]; + int check2[count::value == 2? 1 : -1]; + int check3[count::value == 3? 1 : -1]; +} + +namespace Replace { + // Simple metafunction that replaces the template arguments of + // template template parameters with 'int'. + template + struct EverythingToInt; + + template class TT, typename T1, typename T2> + struct EverythingToInt > { + typedef TT type; + }; + + int check0[is_same>::type, + tuple>::value? 1 : -1]; +} + +namespace Math { + template + struct double_values { + typedef int_tuple type; + }; + + int check0[is_same::type, + int_tuple<2, 4, -6>>::value? 1 : -1]; + + template + struct square { + typedef int_tuple<(Values*Values)...> type; + }; + + int check1[is_same::type, + int_tuple<1, 4, 9>>::value? 1 : -1]; + + template struct square_tuple; + + template + struct square_tuple> { + typedef int_tuple<(Values*Values)...> type; + }; + + int check2[is_same >::type, + int_tuple<1, 4, 9>>::value? 1 : -1]; + + template struct sum; + + template + struct sum { + static const int value = First + sum::value; + }; + + template<> + struct sum<> { + static const int value = 0; + }; + + int check3[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1]; + + template + struct lazy_sum { + int operator()() { + return sum::value; + } + }; + + void f() { + lazy_sum<1, 2, 3, 4, 5>()(); + } +} + +namespace ListMath { + template struct add; + + template + struct add { + static const T value = i + add::value; + }; + + template + struct add { + static const T value = T(); + }; + + template + struct List { + struct sum { + static const T value = add::value; + }; + }; + + template + struct ListI : public List { + }; + + int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1]; +} + +namespace Indices { + template + struct build_indices_impl; + + template + struct build_indices_impl > + : build_indices_impl > { + }; + + template + struct build_indices_impl > { + typedef int_tuple type; + }; + + template + struct build_indices : build_indices_impl<0, N, int_tuple<> > { }; + + int check0[is_same::type, + int_tuple<0, 1, 2, 3, 4>>::value? 1 : -1]; +} + +namespace TemplateTemplateApply { + template class ...Meta> + struct apply_each { + typedef tuple::type...> type; + }; + + template + struct add_reference { + typedef T& type; + }; + + template + struct add_pointer { + typedef T* type; + }; + + template + struct add_const { + typedef const T type; + }; + + int check0[is_same::type, + tuple>::value? 1 : -1]; + + template class ...Meta> + struct apply_each_indirect { + typedef typename apply_each::type type; + }; + + int check1[is_same::type, + tuple>::value? 1 : -1]; + + template + struct apply_each_nested { + typedef typename apply_each::type type; + }; + + struct add_reference_meta { + template + struct apply { + typedef T& type; + }; + }; + + struct add_pointer_meta { + template + struct apply { + typedef T* type; + }; + }; + + struct add_const_meta { + template + struct apply { + typedef const T type; + }; + }; + + int check2[is_same::type, + tuple>::value? 1 : -1]; + +} + +namespace FunctionTypes { + template + struct Arity; + + template + struct Arity { + static const unsigned value = sizeof...(Types); + }; + + template + struct Arity { + static const unsigned value = sizeof...(Types); + }; + + template + struct Arity; // expected-note{{template is declared here}} + + int check0[Arity::value == 0? 1 : -1]; + int check1[Arity::value == 2? 1 : -1]; + int check2[Arity::value == 1? 1 : -1]; + int check3[Arity::value == 3? 1 : -1]; + Arity check4; // expected-error{{implicit instantiation of undefined template 'FunctionTypes::Arity'}} +} + +namespace SuperReplace { + template + struct replace_with_int { + typedef int type; + }; + + template class TT, typename ...Types> + struct replace_with_int> { + typedef TT::type...> type; + }; + + int check0[is_same, + pair>>::type, + pair, pair>>::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 struct value_tuple {}; +template struct tuple { }; +template struct pair { }; + +template struct value_c; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +template +struct X0 { + template + void f(value_tuple * = 0); +}; + +void test_X0() { + X0().f<1, 2, 3, 4, 5>(); +} + +namespace PacksAtDifferentLevels { + + template + struct X { + template struct Inner { + static const unsigned value = 1; + }; + + template + struct Inner...> > { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check0[X::Inner, + pair, + pair> + >::value == 0? 1 : -1]; + + int check1[X::Inner, + pair, + pair> + >::value == 1? 1 : -1]; + + template struct unsigned_tuple { }; + template + struct X1 { + template struct Inner { + static const unsigned value = 0; + }; + + template + struct Inner...>, + unsigned_tuple> { + static const unsigned value = 1; + }; + }; + + int check2[X1::Inner, + pair, + pair>, + unsigned_tuple + >::value == 1? 1 : -1]; + int check3[X1::Inner, + pair, + pair>, + unsigned_tuple + >::value == 0? 1 : -1]; + + template + struct X2 { + template struct Inner { + static const unsigned value = 1; + }; + + template + struct Inner...)> { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check4[X2::Inner, + pair, + pair) + >::value == 0? 1 : -1]; + + int check5[X2::Inner, + pair, + pair) + >::value == 1? 1 : -1]; + + template + struct some_function_object { + template + struct result_of; + }; + + template class...> struct metafun_tuple { }; + + template + struct X3 { + template struct Inner { + static const unsigned value = 0; + }; + + template + struct Inner...>, + metafun_tuple::template result_of...> > { + static const unsigned value = 1; + }; + }; + + int check6[X3::Inner, + pair, + pair>, + metafun_tuple< + some_function_object::result_of, + some_function_object::result_of, + some_function_object::result_of> + >::value == 1? 1 : -1]; + int check7[X3::Inner, + pair, + pair>, + metafun_tuple< + some_function_object::result_of, + some_function_object::result_of, + some_function_object::result_of> + >::value == 0? 1 : -1]; + + template struct unsigned_pair { }; + + template + struct X4 { + template struct Inner { + static const unsigned value = 0; + }; + + template + struct Inner...>> { + static const unsigned value = 1; + }; + }; + + int check8[X4<1, 3, 5>::Inner, + unsigned_pair<3, 4>, + unsigned_pair<5, 6>> + >::value == 1? 1 : -1]; + int check9[X4<1, 3>::Inner, + unsigned_pair<3, 4>, + unsigned_pair<5, 6>> + >::value == 0? 1 : -1]; + + template struct add_reference; + template struct add_pointer; + template struct add_const; + + template class ...Templates> + struct X5 { + template struct Inner { + static const unsigned value = 0; + }; + + template + struct Inner...>> { + static const unsigned value = 1; + }; + }; + + int check10[X5 + ::Inner, + add_pointer, + add_const>>::value == 1? 1 : -1]; + int check11[X5 + ::Inner, + add_pointer, + add_const>>::value == 0? 1 : -1]; + +} + +namespace ExpandingNonTypeTemplateParameters { + template + struct tuple_of_values { + template // 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...> type; + }; + }; + + int i; + float f; + int check_tuple_of_values_1[ + is_same::apply + ::type, + tuple, value_c, value_c, + value_c> + >::value? 1 : -1]; + + tuple_of_values tv1; // expected-note{{in instantiation of template class 'ExpandingNonTypeTemplateParameters::tuple_of_values' requested here}} + + tuple_of_values::apply::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}} + + tuple_of_values::apply::type tv3; // expected-error{{too few template arguments for class template 'apply'}} + + tuple_of_values::apply::type tv4; // expected-error{{too many template arguments for class template 'apply'}} +} + +namespace ExpandingFunctionParameters { + template + struct X0 { + typedef int type; + }; + + template + struct X1 { + template + typename X0::type f(U...); + }; + + void test() { + X1 x1; + x1.f(17, 3.14159); + } +} + +namespace PR10230 { + template + struct s + { + template + auto f() -> int(&)[sizeof...(Args)]; + }; + + void main() + { + int (&ir1)[1] = s().f(); + int (&ir3)[3] = s().f(); + } +} 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 struct Tuple; + +Tuple<> *t0; +Tuple *t1; +Tuple *t2a; +Tuple *t2b = t2a; // expected-error{{cannot initialize a variable of type 'Tuple *' with an lvalue of type 'Tuple *'}} +Tuple *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 void f(Types ... args); + +void test() { + f(); + f(1); + f(2, 1.0); +} + +// Test simple recursive variadic function template +template +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' requested here}} \ + // expected-note{{in instantiation of function template specialization 'recurse_until_fail' 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' 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 struct tuple; +template struct int_c; + +template +struct identity { + typedef T type; +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + 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 struct S { + int f(T...a, int b) { return b; } + }; + S<> s; + S t; + int k = s.f(0); + int l = t.f(&k, 'x', 5.9, 4); + + template struct A { + template struct B { + template struct C { + C(As..., Bs..., int &k, Cs...); + }; + }; + }; + A<>::B<>::C<> c000(k); + A::B<>::C c101(1, k, 3); + A<>::B::C c011(1, k, 3); + A::B::C<> c110(1, 2, k); + A::B::C c222(1, 2, 3, 4, k, 5, 6); + A::B<>::C<> c300(1, 2, 3, k); + + int &f(); + char &f(void*); + template struct U { + template struct V { + auto g(A...a, B...b) -> decltype(f(a...)); + }; + }; + U<>::V v0; + U::V<> v1; + int &v0f = v0.g(0); + char &v1f = v1.g(0); +} +namespace PR12096 { + void Foo(int) {} + void Foo(int, int) = delete; + template struct Var { + Var(const Args &...args, int *) { Foo(args...); } + }; + Var 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 +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 void f(Args... args) { + // An empty expression-list performs value initialization. + constexpr T t(args...); + }; + + template void f(); +} + +// In a base-specifier-list (Clause 10); the pattern is a base-specifier. +template +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; +B *checkB = new HasMixins; +D *checkD = new HasMixins; +C *checkC = new HasMixins; // expected-error{{cannot initialize a variable of type 'C *' with an rvalue of type 'HasMixins *'}} +HasMixins<> *checkNone = new HasMixins<>; + +template +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 +HasMixins::HasMixins(): Mixins()... { } + +template +HasMixins::HasMixins(const HasMixins &other): Mixins(other)... { } + +template +HasMixins::HasMixins(int i): Mixins(i)... { } // expected-error{{no matching constructor for initialization of 'A'}} + +void test_has_mixins() { + HasMixins ab; + HasMixins ab2 = ab; + HasMixins ab3(17); // expected-note{{in instantiation of member function 'HasMixins::HasMixins' requested here}} +} + +template +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 +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 +struct tuple_of_refs { + typedef tuple types; +}; + +tuple *t_int_ref_float_ref; +tuple_of_refs::types *t_int_ref_float_ref_2 = t_int_ref_float_ref; + +template +struct extract_nested_types { + typedef tuple types; +}; + +tuple *t_int_float; +extract_nested_types, identity >::types *t_int_float_2 + = t_int_float; + +template +struct tuple_of_ints { + typedef tuple...> type; +}; + +int check_temp_arg_1[is_same::type, + tuple, 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 +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 { + virtual void f() throw(int, float); +}; + +struct check_f_with_except_2 : f_with_except { + virtual void f() throw(int); +}; + +struct check_f_with_except_3 : f_with_except { + 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 struct pair; +template 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 +struct Expansion { + typedef pair expand_with_pacs; // okay + typedef pair expand_no_packs; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + typedef pair..., 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 +struct ExpansionLengthMismatch { + template + struct Inner { + typedef tuple...> type; // expected-error{{pack expansion contains parameter packs 'Types' and 'OtherTypes' that have different lengths (3 vs. 2)}} + }; +}; + +ExpansionLengthMismatch::Inner::type + *il_pairs; +tuple, pair >*il_pairs_2 = il_pairs; + +ExpansionLengthMismatch::Inner::type // expected-note{{in instantiation of template class 'ExpansionLengthMismatch::Inner' 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 +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(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(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 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 dependent_name_1; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef typename T::template apply 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 +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 +void TestPPNameFunc(int i) { + f(static_cast(i)); // expected-error{{expression contains unexpanded parameter pack 'Types'}} +} + +template class ...Meta> +struct TestUnexpandedTTP { + typedef tuple::type> type; // expected-error{{declaration type contains unexpanded parameter pack 'Meta'}} +}; + +// Test for unexpanded parameter packs in declarations. +template +// 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(0); // expected-error{{bit-field size contains unexpanded parameter pack 'Types'}} + static_assert(static_cast(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(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(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + T direct_init(0, static_cast(0)); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + T list_init = { static_cast(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + } + + T in_class_member_init = static_cast(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + TestUnexpandedDecls() : + Types(static_cast(0)), // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + Types(static_cast(0))..., + in_class_member_init(static_cast(0)) {} // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + + void default_function_args(T = static_cast(0)); // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + + template // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_1; + template(0)> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_2; + template class = Types::template apply> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_3; + + template // 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 + 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 +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(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXStaticCastExpr + (void)static_cast(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXDynamicCastExpr + (void)dynamic_cast(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXReinterpretCastExpr + (void)reinterpret_cast(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXConstCastExpr + (void)const_cast(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(); // 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(); // 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(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnresolvedMemberExpr + x.f(); // 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 +struct TestUnexpandedDecls; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}} + +// Test for diagnostics in the presence of multiple unexpanded +// parameter packs. +template struct pair; + +template +struct MemberTemplatePPNames { + template + struct Inner { + typedef pair* types; // expected-error{{declaration type contains unexpanded parameter packs 'OuterTypes' and 'InnerTypes'}} + + template + struct VeryInner { + typedef pair, pair > types; // expected-error{{declaration type contains unexpanded parameter packs 'VeryInnerTypes', 'OuterTypes', ...}} + }; + }; +}; + +// Example from working paper +namespace WorkingPaperExample { + template struct Tuple {}; + template struct Pair {}; + + template struct zip { + template struct with { + typedef Tuple ... > type; // expected-error{{pack expansion contains parameter packs 'Args1' and 'Args2' that have different lengths (1 vs. 2)}} + }; + }; + + typedef zip::with::type T1; // T1 is Tuple, Pair> + typedef Tuple, Pair> T1; + + typedef zip::with::type T2; // expected-note{{in instantiation of template class}} + + template void f(Args...); + template void h(Args...); + + template + void g(Args ... args) { + f(const_cast(&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 struct X0t; +template struct X0t; + +template struct X1t; // expected-note{{previous template type parameter pack declared here}} +template struct X1t; // expected-error{{template type parameter conflicts with previous template type parameter pack}} + +template struct X2t; // expected-note{{previous template type parameter declared here}} +template struct X2t; // expected-error{{template type parameter pack conflicts with previous template type parameter}} + +template class> struct X0t_intt; +template class> struct X0t_intt; + +template class> struct X1t_intt; // expected-note{{previous template type parameter pack declared here}} +template class> struct X1t_intt; // expected-error{{template type parameter conflicts with previous template type parameter pack}} + +template class> struct X2t_intt; // expected-note{{previous template type parameter declared here}} +template class> struct X2t_intt; // expected-error{{template type parameter pack conflicts with previous template type parameter}} + +template struct X1nt; // expected-note{{previous non-type template parameter pack declared here}} +template struct X1nt; // expected-error{{non-type template parameter conflicts with previous non-type template parameter pack}} + +template class> class X1tt; // expected-note{{previous template template parameter declared here}} +template 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 struct tuple { }; + template struct int_tuple { }; + + template + struct X { + template + X(tuple, int_tuple); + }; + + template + template + X::X(tuple, int_tuple) {} +} 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 struct tuple; + +template +struct X1 { + static const unsigned value = 0; +}; + +template +struct X1 > { + static const unsigned value = 1; +}; + +template +struct X1 > { + static const unsigned value = 2; +}; + +template +struct X1 > { + static const unsigned value = 3; +}; + +int check0[X1>::value == 0? 1 : -1]; +int check1[X1>::value == 2? 1 : -1]; +int check2[X1>::value == 1? 1 : -1]; +int check3[X1>::value == 2? 1 : -1]; +int check4[X1>::value == 3? 1 : -1]; + +// Partial ordering of function templates. +template +int &f0(T1, T2, Rest...); + +template +float &f0(T1, T2); + +void test_f0() { + int &ir1 = f0(1, 2.0, 'a'); + float &fr1 = f0(1, 2.0); +} + +template +int &f1(T1, T2, Rest...); + +template +float &f1(T1, T2, ...); + +void test_f1() { + int &ir1 = f1(1, 2.0, 'a'); +} + +template +int &f2(T1, T2, Rest...); + +float &f2(...); + +void test_f2() { + int &ir1 = f2(1, 2.0, 'a'); +} -- cgit v1.2.3