diff options
author | Jason Merrill <jason@redhat.com> | 2016-02-26 14:54:33 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-02-26 14:54:33 -0500 |
commit | 56cde07776d4b652dbd05066b5fed7ab28c294c2 (patch) | |
tree | 90c3696d72c4caa343b19adf28bcdfc121eee738 | |
parent | 622174b20dfaa584abcf950c89aaa1843b146669 (diff) | |
download | gcc-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
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/pt.c | 43 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C | 33 |
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; |