aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-02-26 14:54:33 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-02-26 14:54:33 -0500
commit56cde07776d4b652dbd05066b5fed7ab28c294c2 (patch)
tree90c3696d72c4caa343b19adf28bcdfc121eee738 /gcc
parent622174b20dfaa584abcf950c89aaa1843b146669 (diff)
downloadgcc-56cde07776d4b652dbd05066b5fed7ab28c294c2.zip
gcc-56cde07776d4b652dbd05066b5fed7ab28c294c2.tar.gz
gcc-56cde07776d4b652dbd05066b5fed7ab28c294c2.tar.bz2
re PR c++/69958 (sizeof... computes wrong size)
PR c++/69958 * pt.c (make_argument_pack): New. (tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion. (tsubst_copy_and_build): Likewise. From-SVN: r233758
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/pt.c43
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C33
4 files changed, 108 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ecab545..ec99120 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-26 Jason Merrill <jason@redhat.com>
+
+ PR c++/69958
+ * pt.c (make_argument_pack): New.
+ (tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion.
+ (tsubst_copy_and_build): Likewise.
+
2016-02-25 Jason Merrill <jason@redhat.com>
PR c++/69889
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;