From 56cde07776d4b652dbd05066b5fed7ab28c294c2 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 26 Feb 2016 14:54:33 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 7 +++ gcc/cp/pt.c | 43 +++++++++++++++---- gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C | 33 ++++++++++++++ .../g++.dg/cpp0x/variadic-sizeof4a.C | 33 ++++++++++++++ 4 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ecab54585f5..ec991201009 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2016-02-26 Jason Merrill + + 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 PR c++/69889 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cd3eb6757cf..b5855a8d13c 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 00000000000..1187429650c --- /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 +struct list { }; + +template +struct size { }; + +template +using size_for = size; + +template struct assert_same; +template struct assert_same {}; + +template +using wrapped = list>; + +// This assertion fails (produces size<4>) +assert_same< + list>, + wrapped> a3; + + +template +using wrapped2 = list>; + +// This assertion fails (produces size<2>) +assert_same< + list>, + wrapped2> 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 00000000000..0e8096de2fc --- /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 +struct list { }; + +template +struct size { }; + +template +using size_for = size; + +template struct assert_same; +template struct assert_same {}; + +template +using wrapped = list>; + +// This assertion fails (produces size<4>) +assert_same< + list>, + wrapped> a3; + + +template +using wrapped2 = list>; + +// This assertion fails (produces size<2>) +assert_same< + list>, + wrapped2> a4; -- 2.30.2