diff options
Diffstat (limited to 'clang/test/CXX/temp/temp.decls/temp.variadic')
15 files changed, 2252 insertions, 0 deletions
| 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'); +} | 
