summaryrefslogtreecommitdiff
path: root/clang/test/CXX/temp/temp.decls/temp.variadic
diff options
context:
space:
mode:
authorZancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au>2012-09-24 09:58:17 +1000
committerZancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au>2012-09-24 09:58:17 +1000
commit222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch)
tree7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/CXX/temp/temp.decls/temp.variadic
parent3d206f03985b50beacae843d880bccdc91a9f424 (diff)
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/CXX/temp/temp.decls/temp.variadic')
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp50
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp352
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp86
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp260
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp46
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp127
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp75
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp274
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp251
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp9
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp22
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp193
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp403
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp43
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp61
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');
+}