alias templates are supposed to be transparent, so when we see
template <typename T, typename...Ts>
using wrapped2 = list<T, size_for<Ts..., T>>;
the size_for<Ts..., T> needs to be expanded into sizeof...(something).
There is no way to write this "something" in C++, but it's simple enough
to leave it as an *_ARGUMENT_PACK within the compiler.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 772d7b6f7c13119525da6e470c8729f14f35152f
Author: Jason Merrill <ja...@redhat.com>
Date: Fri Feb 26 13:53:08 2016 -0500
PR c++/69958
* pt.c (make_argument_pack): New.
(tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion.
(tsubst_copy_and_build): Likewise.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cd3eb67..b5855a8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11117,6 +11117,25 @@ get_pattern_parm (tree parm, tree tmpl)
return patparm;
}
+/* Make an argument pack out of the TREE_VEC VEC. */
+
+static tree
+make_argument_pack (tree vec)
+{
+ tree pack;
+ tree elt = TREE_VEC_ELT (vec, 0);
+ if (TYPE_P (elt))
+ pack = cxx_make_type (TYPE_ARGUMENT_PACK);
+ else
+ {
+ pack = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_TYPE (pack) = TREE_TYPE (elt);
+ TREE_CONSTANT (pack) = 1;
+ }
+ SET_ARGUMENT_PACK_ARGS (pack, vec);
+ return pack;
+}
+
/* Substitute ARGS into the vector or list of template arguments T. */
static tree
@@ -14066,7 +14085,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
case SIZEOF_EXPR:
- if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
+ if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
+ || ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
{
tree expanded, op = TREE_OPERAND (t, 0);
int len = 0;
@@ -14077,7 +14097,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
- expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+ if (PACK_EXPANSION_P (op))
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+ else
+ expanded = tsubst_template_args (ARGUMENT_PACK_ARGS (op),
+ args, complain, in_decl);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
@@ -14093,13 +14117,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
else if (PACK_EXPANSION_P (expanded)
|| (TREE_CODE (expanded) == TREE_VEC
- && len > 0
- && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+ && pack_expansion_args_count (expanded)))
+
{
- if (TREE_CODE (expanded) == TREE_VEC)
- expanded = TREE_VEC_ELT (expanded, len - 1);
+ if (PACK_EXPANSION_P (expanded))
+ /* OK. */;
+ else if (TREE_VEC_LENGTH (expanded) == 1)
+ expanded = TREE_VEC_ELT (expanded, 0);
else
- PACK_EXPANSION_SIZEOF_P (expanded) = true;
+ expanded = make_argument_pack (expanded);
if (TYPE_P (expanded))
return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
@@ -16162,7 +16188,8 @@ tsubst_copy_and_build (tree t,
length, stride, TREE_TYPE (op1)));
}
case SIZEOF_EXPR:
- if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
+ if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
+ || ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
RETURN (tsubst_copy (t, args, complain, in_decl));
/* Fall through */
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C
new file mode 100644
index 0000000..1187429
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C
@@ -0,0 +1,33 @@
+// PR c++/69958
+// { dg-do compile { target c++11 } }
+
+typedef decltype(sizeof(int)) size_t;
+
+template <typename...Ts>
+struct list { };
+
+template <size_t N>
+struct size { };
+
+template <typename...Ts>
+using size_for = size<sizeof...(Ts)>;
+
+template<class T, class U> struct assert_same;
+template<class T> struct assert_same<T,T> {};
+
+template <typename T, typename...Ts>
+using wrapped = list<T, size_for<T, Ts...>>;
+
+// This assertion fails (produces size<4>)
+assert_same<
+ list<float, size<5>>,
+ wrapped<float, int, double, char, unsigned>> a3;
+
+
+template <typename T, typename...Ts>
+using wrapped2 = list<T, size_for<Ts..., T>>;
+
+// This assertion fails (produces size<2>)
+assert_same<
+ list<float, size<5>>,
+ wrapped2<float, int, double, char, unsigned>> a4;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C
new file mode 100644
index 0000000..0e8096d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C
@@ -0,0 +1,33 @@
+// PR c++/69958
+// { dg-do compile { target c++11 } }
+
+typedef decltype(sizeof(int)) size_t;
+
+template <typename...Ts>
+struct list { };
+
+template <size_t N>
+struct size { };
+
+template <unsigned...Ts>
+using size_for = size<sizeof...(Ts)>;
+
+template<class T, class U> struct assert_same;
+template<class T> struct assert_same<T,T> {};
+
+template <typename T, unsigned...Ts>
+using wrapped = list<T, size_for<0, Ts...>>;
+
+// This assertion fails (produces size<4>)
+assert_same<
+ list<float, size<5>>,
+ wrapped<float,2,3,4,5>> a3;
+
+
+template <typename T, unsigned...Ts>
+using wrapped2 = list<T, size_for<Ts..., 0>>;
+
+// This assertion fails (produces size<2>)
+assert_same<
+ list<float, size<5>>,
+ wrapped2<float,2,3,4,5>> a4;